mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Updated with latest TB.
This commit is contained in:
@@ -41,23 +41,23 @@ TB_DataType tbtype(Type *type)
|
||||
{
|
||||
case TYPE_U8:
|
||||
case TYPE_I8:
|
||||
return TB_TYPE_VEC_I8(elements);
|
||||
return tb_vector_type(TB_I8, elements);
|
||||
case TYPE_U16:
|
||||
case TYPE_I16:
|
||||
return TB_TYPE_VEC_I16(elements);
|
||||
return tb_vector_type(TB_I16, elements);
|
||||
case TYPE_U32:
|
||||
case TYPE_I32:
|
||||
return TB_TYPE_VEC_I32(elements);
|
||||
return tb_vector_type(TB_I32, elements);
|
||||
case TYPE_U64:
|
||||
case TYPE_I64:
|
||||
return TB_TYPE_VEC_I64(elements);
|
||||
return tb_vector_type(TB_I64, elements);
|
||||
case TYPE_I128:
|
||||
case TYPE_U128:
|
||||
FATAL_ERROR("Unsupported int128");
|
||||
case TYPE_F64:
|
||||
return TB_TYPE_VEC_F64(elements);
|
||||
case TYPE_F32:
|
||||
return TB_TYPE_VEC_F32(elements);
|
||||
return tb_vector_type(TB_F32, elements);
|
||||
case TYPE_F64:
|
||||
return tb_vector_type(TB_F64, elements);
|
||||
case TYPE_F16:
|
||||
FATAL_ERROR("Unsupported f16");
|
||||
case TYPE_F128:
|
||||
@@ -340,9 +340,9 @@ void tinybackend_store_value(TbContext *c, TBEValue *destination, TBEValue *valu
|
||||
{
|
||||
// Here we do an optimized(?) memcopy.
|
||||
ByteSize size = type_size(value->type);
|
||||
TB_Register copy_size = tb_inst_iconst(c->f,
|
||||
size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64,
|
||||
size);
|
||||
TB_Register copy_size = tb_inst_uint(c->f,
|
||||
size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64,
|
||||
size);
|
||||
|
||||
alignment = type_min_alignment(destination->alignment, value->alignment);
|
||||
tb_inst_memcpy(c->f, destination->reg, value->reg, copy_size, alignment);
|
||||
@@ -371,7 +371,7 @@ static void tinybackend_emit_const_expr(TbContext *c, TBEValue *value, Expr *exp
|
||||
switch (expr->const_expr.const_kind)
|
||||
{
|
||||
case CONST_FLOAT:
|
||||
TBE_VALUE_set(value, tb_inst_fconst(c->f, tbtype(type), expr->const_expr.fxx.f), type);
|
||||
TBE_VALUE_set(value, tb_inst_float(c->f, tbtype(type), expr->const_expr.fxx.f), type);
|
||||
return;
|
||||
case CONST_INTEGER:
|
||||
{
|
||||
@@ -390,7 +390,7 @@ static void tinybackend_emit_const_expr(TbContext *c, TBEValue *value, Expr *exp
|
||||
//reg = tb_inst_iconst128(c->function, dt, (TB_Int128){ .lo = i.low, .hi = i.high });
|
||||
break;
|
||||
default:
|
||||
reg = tb_inst_iconst(c->f, dt, i.low);
|
||||
reg = type_kind_is_signed(expr->const_expr.ixx.type) ? tb_inst_sint(c->f, dt, i.low) : tb_inst_uint(c->f, dt, i.low);
|
||||
break;
|
||||
}
|
||||
TBE_VALUE_set(value, reg, type);
|
||||
@@ -539,12 +539,12 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
|
||||
case BINARYOP_MULT:
|
||||
if (is_float)
|
||||
{
|
||||
val = tb_inst_fmul(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_fmul(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO(NeGate): review this later, maybe it shouldn't be NO_WRAP
|
||||
val = tb_inst_mul(c->f, dt, lhs_value, rhs_value, TB_ASSUME_NUW);
|
||||
val = tb_inst_mul(c->f, lhs_value, rhs_value, TB_ASSUME_NUW);
|
||||
break;
|
||||
case BINARYOP_SUB:
|
||||
if (lhs_type->type_kind == TYPE_POINTER)
|
||||
@@ -564,10 +564,10 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
|
||||
}
|
||||
if (is_float)
|
||||
{
|
||||
val = tb_inst_fsub(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_fsub(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
}
|
||||
val = tb_inst_mul(c->f, dt, lhs_value, rhs_value, tinybackend_get_arith_behavior(lhs_type));
|
||||
val = tb_inst_mul(c->f, lhs_value, rhs_value, tinybackend_get_arith_behavior(lhs_type));
|
||||
break;
|
||||
case BINARYOP_ADD:
|
||||
if (lhs_type->type_kind == TYPE_POINTER)
|
||||
@@ -576,20 +576,20 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
|
||||
}
|
||||
if (is_float)
|
||||
{
|
||||
val = tb_inst_fadd(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_fadd(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
}
|
||||
val = tb_inst_add(c->f, dt, lhs_value, rhs_value, tinybackend_get_arith_behavior(lhs_type));
|
||||
val = tb_inst_add(c->f, lhs_value, rhs_value, tinybackend_get_arith_behavior(lhs_type));
|
||||
break;
|
||||
case BINARYOP_DIV:
|
||||
//llvm_emit_trap_zero(c, rhs_type, rhs_value, "% by zero", TOKLOC(expr->span.loc));
|
||||
if (is_float)
|
||||
{
|
||||
val = tb_inst_fdiv(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_fdiv(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
}
|
||||
|
||||
val = tb_inst_div(c->f, dt, lhs_value, rhs_value, !type_is_unsigned(lhs_type));
|
||||
val = tb_inst_div(c->f, lhs_value, rhs_value, !type_is_unsigned(lhs_type));
|
||||
break;
|
||||
case BINARYOP_MOD:
|
||||
{
|
||||
@@ -598,20 +598,20 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
|
||||
case BINARYOP_SHR:
|
||||
if (type_is_unsigned(lhs_type))
|
||||
{
|
||||
val = tb_inst_shr(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_shr(c->f, lhs_value, rhs_value);
|
||||
return;
|
||||
}
|
||||
|
||||
val = tb_inst_sar(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_sar(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
case BINARYOP_SHL:
|
||||
val = tb_inst_shl(c->f, dt, lhs_value, rhs_value, TB_ASSUME_NUW);
|
||||
val = tb_inst_shl(c->f, lhs_value, rhs_value, TB_ASSUME_NUW);
|
||||
break;
|
||||
case BINARYOP_BIT_AND:
|
||||
val = tb_inst_and(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_and(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
case BINARYOP_BIT_OR:
|
||||
val = tb_inst_or(c->f, dt, lhs_value, rhs_value);
|
||||
val = tb_inst_or(c->f, lhs_value, rhs_value);
|
||||
break;
|
||||
case BINARYOP_BIT_XOR:
|
||||
TODO
|
||||
@@ -726,10 +726,10 @@ static TB_Register tilde_emit_local_decl(TbContext *c, Decl *decl)
|
||||
scratch_buffer_append(decl->external_name);
|
||||
scratch_buffer_append(".f");
|
||||
TB_InitializerID initializer = tb_initializer_create(c->module, type_size(type_anyerr), type_alloca_alignment(type_anyerr), 1);
|
||||
decl->var.tb_failable_reg = tb_global_create(c->module, scratch_buffer_to_string(), initializer);
|
||||
decl->var.tb_failable_reg = tb_global_create(c->module, initializer, scratch_buffer_to_string(), TB_LINKAGE_PRIVATE);
|
||||
}
|
||||
TB_InitializerID static_initializer = tb_initializer_create(c->module, type_size(var_type), type_alloca_alignment(var_type), 1);
|
||||
decl->tb_register = tb_global_create(c->module, "tempglobal", static_initializer);
|
||||
decl->tb_register = tb_global_create(c->module, static_initializer, "tempglobal", TB_LINKAGE_PRIVATE);
|
||||
tilde_emit_global_initializer(c, decl);
|
||||
return decl->tb_register;
|
||||
}
|
||||
@@ -778,7 +778,7 @@ static void tilde_emit_function_body(TbContext *c, Decl *decl)
|
||||
c->current_func_decl = decl;
|
||||
|
||||
TB_FunctionPrototype *prototype = tilde_get_function_type(c->module, decl->type->func.prototype);
|
||||
TB_Function *function = tb_prototype_build(c->module, prototype, decl->external_name);
|
||||
TB_Function *function = tb_prototype_build(c->module, prototype, decl->external_name, TB_LINKAGE_PUBLIC);
|
||||
c->f = function;
|
||||
|
||||
AstId current = decl->func_decl.body->compound_stmt.first_stmt;
|
||||
|
||||
@@ -8,7 +8,7 @@ static void tbcontext_destroy(TbContext *context)
|
||||
|
||||
TB_Register tilde_emit_is_no_error(TbContext *c, TB_Reg reg)
|
||||
{
|
||||
return tb_inst_cmp_eq(c->f, tbtype(type_anyerr), reg, tilde_get_zero(c, type_anyerr));
|
||||
return tb_inst_cmp_eq(c->f, reg, tilde_get_zero(c, type_anyerr));
|
||||
}
|
||||
|
||||
void tilde_emit_global_initializer(TbContext *c, Decl *decl)
|
||||
|
||||
@@ -12,9 +12,9 @@ TB_Register tilde_get_zero(TbContext *c, Type *type)
|
||||
TB_DataType data_type = tbtype(type);
|
||||
if (type_is_float(type))
|
||||
{
|
||||
return tb_inst_fconst(c->f, data_type, 0);
|
||||
return tb_inst_float(c->f, data_type, 0);
|
||||
}
|
||||
return tb_inst_iconst(c->f, data_type, 0);
|
||||
return type_is_signed(type) ? tb_inst_sint(c->f, data_type, 0) : tb_inst_uint(c->f, data_type, 0);
|
||||
}
|
||||
|
||||
TBEValue tilde_emit_assign_expr(TbContext *c, TBEValue *ref, Expr *expr, TB_Reg failable)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
void tilde_emit_memclear_size_align(TbContext *c, TB_Register ref, uint64_t size, AlignSize align)
|
||||
{
|
||||
ByteSize min = type_min_alignment(align, size);
|
||||
TB_Register zero = tb_inst_iconst(c->f, TB_TYPE_I8, 0);
|
||||
TB_Register elements = tb_inst_iconst(c->f, size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64, size);
|
||||
TB_Register zero = tb_inst_uint(c->f, TB_TYPE_I8, 0);
|
||||
TB_Register elements = tb_inst_uint(c->f, size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64, size);
|
||||
tb_inst_memset(c->f, ref, zero, elements, min);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ TB_Reg tilde_emit_shl_fixed(TbContext *c, Type *type, TB_Reg reg, int shift)
|
||||
BitSize bit_width = type_kind_bitsize(type->type_kind);
|
||||
if (shift >= bit_width) return tilde_get_zero(c, type);
|
||||
TB_DataType int_type = tbtype(type);
|
||||
return tb_inst_shl(c->f, int_type, reg, tb_inst_iconst(c->f, int_type, (unsigned)shift), type_is_signed(type) ? TB_ASSUME_NSW : TB_ASSUME_NUW);
|
||||
return tb_inst_shl(c->f, reg, tb_inst_uint(c->f, int_type, (unsigned)shift), type_is_signed(type) ? TB_ASSUME_NSW : TB_ASSUME_NUW);
|
||||
}
|
||||
|
||||
TB_Reg tilde_emit_lshr_fixed(TbContext *c, Type *type, TB_Reg reg, int shift)
|
||||
@@ -32,7 +32,7 @@ TB_Reg tilde_emit_lshr_fixed(TbContext *c, Type *type, TB_Reg reg, int shift)
|
||||
BitSize bit_width = type_kind_bitsize(type->type_kind);
|
||||
if (shift >= bit_width) return tilde_get_zero(c, type);
|
||||
TB_DataType int_type = tbtype(type);
|
||||
return tb_inst_shr(c->f, int_type, reg, tb_inst_iconst(c->f, int_type, (unsigned)shift));
|
||||
return tb_inst_shr(c->f, reg, tb_inst_uint(c->f, int_type, (unsigned)shift));
|
||||
}
|
||||
|
||||
TB_Reg tilde_emit_alloca(TbContext *c, Type *type)
|
||||
|
||||
@@ -42,10 +42,10 @@ TB_Reg tilde_emit_local_decl(TbContext *c, Decl *decl)
|
||||
scratch_buffer_append(decl->external_name);
|
||||
scratch_buffer_append(".f");
|
||||
TB_InitializerID initializer = tb_initializer_create(c->module, type_size(type_anyerr), type_alloca_alignment(type_anyerr), 1);
|
||||
decl->var.tb_failable_reg = tb_global_create(c->module, scratch_buffer_to_string(), initializer);
|
||||
decl->var.tb_failable_reg = tb_global_create(c->module, initializer, scratch_buffer_to_string(), TB_LINKAGE_PRIVATE);
|
||||
}
|
||||
TB_InitializerID static_initializer = tb_initializer_create(c->module, type_size(var_type), type_alloca_alignment(var_type), 1);
|
||||
decl->tb_register = tb_global_create(c->module, "tempglobal", static_initializer);
|
||||
decl->tb_register = tb_global_create(c->module, static_initializer, "tempglobal", TB_LINKAGE_PRIVATE);
|
||||
tilde_emit_global_initializer(c, decl);
|
||||
return decl->tb_register;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ void tilde_store_value_aligned(TbContext *c, TB_Reg destination, TBEValue *value
|
||||
case TBE_ADDRESS:
|
||||
{
|
||||
ByteSize size = type_size(value->type);
|
||||
TB_Reg copy_size = tb_inst_iconst(c->f, size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64, size);
|
||||
TB_Reg copy_size = tb_inst_uint(c->f, size <= UINT32_MAX ? TB_TYPE_I32 : TB_TYPE_I64, size);
|
||||
tb_inst_memcpy(c->f, destination, value->reg, copy_size, type_min_alignment(alignment, value->alignment));
|
||||
}
|
||||
}
|
||||
@@ -91,8 +91,8 @@ void tilde_store_zero(TbContext *c, Type *type, TB_Reg addr, AlignSize alignment
|
||||
}
|
||||
ByteSize size = type_size(type);
|
||||
ByteSize min = type_min_alignment(alignment, size);
|
||||
TB_Register zero = tb_inst_iconst(c->f, TB_TYPE_I8, 0);
|
||||
TB_Register elements = tb_inst_iconst(c->f, tbtype(type_usize), size);
|
||||
TB_Register zero = tb_inst_uint(c->f, TB_TYPE_I8, 0);
|
||||
TB_Register elements = tb_inst_uint(c->f, tbtype(type_usize), size);
|
||||
tb_inst_memset(c->f, addr, zero, elements, min);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ void value_addr(TbContext *c, TBEValue *value)
|
||||
// TODO check whether new names must be added
|
||||
TB_InitializerID initializer_id = tb_initializer_create(c->module, type_size(value->type),
|
||||
type_alloca_alignment(value->type), 0);
|
||||
tb_global_create(c->module, ".taddr", initializer_id);
|
||||
tb_global_create(c->module, initializer_id, ".taddr", TB_LINKAGE_PRIVATE);
|
||||
// TODO set linkage
|
||||
/*
|
||||
llvm_set_private_linkage(ref);
|
||||
|
||||
229
tb/tb.h
229
tb/tb.h
@@ -32,7 +32,7 @@ extern "C" {
|
||||
|
||||
// https://semver.org/
|
||||
#define TB_VERSION_MAJOR 0
|
||||
#define TB_VERSION_MINOR 1
|
||||
#define TB_VERSION_MINOR 2
|
||||
#define TB_VERSION_PATCH 0
|
||||
|
||||
#ifndef TB_MAX_THREADS
|
||||
@@ -115,6 +115,20 @@ typedef enum TB_BranchHint {
|
||||
TB_BRANCH_HINT_UNLIKELY
|
||||
} TB_BranchHint;
|
||||
|
||||
typedef enum TB_Linkage {
|
||||
TB_LINKAGE_PUBLIC,
|
||||
TB_LINKAGE_PRIVATE
|
||||
} TB_Linkage;
|
||||
|
||||
typedef enum TB_MemoryOrder {
|
||||
TB_MEM_ORDER_RELAXED,
|
||||
TB_MEM_ORDER_CONSUME,
|
||||
TB_MEM_ORDER_ACQUIRE,
|
||||
TB_MEM_ORDER_RELEASE,
|
||||
TB_MEM_ORDER_ACQ_REL,
|
||||
TB_MEM_ORDER_SEQ_CST,
|
||||
} TB_MemoryOrder;
|
||||
|
||||
typedef enum TB_OptLevel {
|
||||
// no optimizer run
|
||||
TB_OPT_O0,
|
||||
@@ -151,7 +165,10 @@ typedef enum TB_DataTypeEnum {
|
||||
|
||||
typedef struct TB_DataType {
|
||||
TB_DataTypeEnum type : 8;
|
||||
uint8_t count; // 0 is illegal, except on VOID, it doesn't matter there
|
||||
|
||||
// 2^N where N is the width value.
|
||||
// Only integers and floats can be wide.
|
||||
uint8_t width;
|
||||
} TB_DataType;
|
||||
|
||||
typedef struct TB_FeatureSet {
|
||||
@@ -187,6 +204,9 @@ typedef struct TB_SwitchEntry {
|
||||
typedef int TB_Register;
|
||||
typedef int TB_Reg; // short-hand
|
||||
|
||||
// represents byte counts
|
||||
typedef uint32_t TB_CharUnits;
|
||||
|
||||
typedef unsigned int TB_FileID;
|
||||
typedef unsigned int TB_FunctionID;
|
||||
typedef unsigned int TB_ExternalID;
|
||||
@@ -197,52 +217,43 @@ typedef struct TB_Module TB_Module;
|
||||
typedef struct TB_Function TB_Function;
|
||||
typedef struct TB_FunctionPrototype TB_FunctionPrototype;
|
||||
|
||||
// represents the atomic cmpxchg result since it's two values
|
||||
typedef struct TB_CmpXchgResult {
|
||||
TB_Register success;
|
||||
TB_Register old_value;
|
||||
} TB_CmpXchgResult;
|
||||
|
||||
// *******************************
|
||||
// Public macros
|
||||
// *******************************
|
||||
#ifdef __cplusplus
|
||||
#define TB_TYPE_VOID TB_DataType{ TB_VOID, 1 }
|
||||
#define TB_TYPE_VOID TB_DataType{ TB_VOID }
|
||||
|
||||
#define TB_TYPE_I8 TB_DataType{ TB_I8, 1 }
|
||||
#define TB_TYPE_I16 TB_DataType{ TB_I16, 1 }
|
||||
#define TB_TYPE_I32 TB_DataType{ TB_I32, 1 }
|
||||
#define TB_TYPE_I64 TB_DataType{ TB_I64, 1 }
|
||||
#define TB_TYPE_I8 TB_DataType{ TB_I8 }
|
||||
#define TB_TYPE_I16 TB_DataType{ TB_I16 }
|
||||
#define TB_TYPE_I32 TB_DataType{ TB_I32 }
|
||||
#define TB_TYPE_I64 TB_DataType{ TB_I64 }
|
||||
|
||||
#define TB_TYPE_F32 TB_DataType{ TB_F32, 1 }
|
||||
#define TB_TYPE_F64 TB_DataType{ TB_F64, 1 }
|
||||
#define TB_TYPE_F32 TB_DataType{ TB_F32 }
|
||||
#define TB_TYPE_F64 TB_DataType{ TB_F64 }
|
||||
|
||||
#define TB_TYPE_BOOL TB_DataType{ TB_BOOL, 1 }
|
||||
#define TB_TYPE_PTR TB_DataType{ TB_PTR, 1 }
|
||||
|
||||
#define TB_TYPE_VEC_I8(c) TB_DataType{ TB_I8, c }
|
||||
#define TB_TYPE_VEC_I16(c) TB_DataType{ TB_I16, c }
|
||||
#define TB_TYPE_VEC_I32(c) TB_DataType{ TB_I32, c }
|
||||
#define TB_TYPE_VEC_I64(c) TB_DataType{ TB_I64, c }
|
||||
#define TB_TYPE_VEC_F32(c) TB_DataType{ TB_F32, c }
|
||||
#define TB_TYPE_VEC_F64(c) TB_DataType{ TB_F64, c }
|
||||
#define TB_TYPE_VEC_BOOL(c) TB_DataType{ TB_BOOL, c }
|
||||
#define TB_TYPE_BOOL TB_DataType{ TB_BOOL }
|
||||
#define TB_TYPE_PTR TB_DataType{ TB_PTR }
|
||||
|
||||
#else
|
||||
|
||||
#define TB_TYPE_VOID (TB_DataType){ TB_VOID, 1 }
|
||||
#define TB_TYPE_VOID (TB_DataType){ TB_VOID, 0 }
|
||||
|
||||
#define TB_TYPE_I8 (TB_DataType){ TB_I8, 1 }
|
||||
#define TB_TYPE_I16 (TB_DataType){ TB_I16, 1 }
|
||||
#define TB_TYPE_I32 (TB_DataType){ TB_I32, 1 }
|
||||
#define TB_TYPE_I64 (TB_DataType){ TB_I64, 1 }
|
||||
#define TB_TYPE_I8 (TB_DataType){ TB_I8, 0 }
|
||||
#define TB_TYPE_I16 (TB_DataType){ TB_I16, 0 }
|
||||
#define TB_TYPE_I32 (TB_DataType){ TB_I32, 0 }
|
||||
#define TB_TYPE_I64 (TB_DataType){ TB_I64, 0 }
|
||||
|
||||
#define TB_TYPE_F32 (TB_DataType){ TB_F32, 1 }
|
||||
#define TB_TYPE_F64 (TB_DataType){ TB_F64, 1 }
|
||||
#define TB_TYPE_F32 (TB_DataType){ TB_F32, 0 }
|
||||
#define TB_TYPE_F64 (TB_DataType){ TB_F64, 0 }
|
||||
|
||||
#define TB_TYPE_BOOL (TB_DataType){ TB_BOOL, 1 }
|
||||
#define TB_TYPE_PTR (TB_DataType){ TB_PTR, 1 }
|
||||
|
||||
#define TB_TYPE_VEC_I8(c) (TB_DataType){ TB_I8, c }
|
||||
#define TB_TYPE_VEC_I16(c) (TB_DataType){ TB_I16, c }
|
||||
#define TB_TYPE_VEC_I32(c) (TB_DataType){ TB_I32, c }
|
||||
#define TB_TYPE_VEC_I64(c) (TB_DataType){ TB_I64, c }
|
||||
#define TB_TYPE_VEC_F32(c) (TB_DataType){ TB_F32, c }
|
||||
#define TB_TYPE_VEC_F64(c) (TB_DataType){ TB_F64, c }
|
||||
#define TB_TYPE_BOOL (TB_DataType){ TB_BOOL, 0 }
|
||||
#define TB_TYPE_PTR (TB_DataType){ TB_PTR, 0 }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -302,7 +313,7 @@ TB_API void tb_prototype_add_params(TB_FunctionPrototype* p, size_t count, const
|
||||
// adds a parameter to the function prototype, TB doesn't support struct
|
||||
// parameters so the frontend must lower them to pointers or any other type
|
||||
// depending on their preferred ABI.
|
||||
TB_API TB_Function* tb_prototype_build(TB_Module* m, TB_FunctionPrototype* p, const char* name);
|
||||
TB_API TB_Function* tb_prototype_build(TB_Module* m, TB_FunctionPrototype* p, const char* name, TB_Linkage linkage);
|
||||
|
||||
////////////////////////////////
|
||||
// Constant Initializers
|
||||
@@ -317,11 +328,14 @@ TB_API void* tb_initializer_add_region(TB_Module* m, TB_InitializerID id, size_t
|
||||
////////////////////////////////
|
||||
// Constant Initializers
|
||||
////////////////////////////////
|
||||
TB_API TB_GlobalID tb_global_create(TB_Module* m, const char* name, TB_InitializerID initializer);
|
||||
TB_API TB_GlobalID tb_global_create(TB_Module* m, TB_InitializerID initializer, const char* name, TB_Linkage linkage);
|
||||
|
||||
////////////////////////////////
|
||||
// Function IR Generation
|
||||
////////////////////////////////
|
||||
// this only allows for power of two vector types
|
||||
TB_API TB_DataType tb_vector_type(TB_DataTypeEnum type, int width);
|
||||
|
||||
TB_API TB_Function* tb_function_clone(TB_Module* m, TB_Function* f, const char* name);
|
||||
TB_API void tb_function_print(TB_Function* f, FILE* out);
|
||||
TB_API void tb_function_free(TB_Function* f);
|
||||
@@ -339,75 +353,114 @@ TB_API TB_Register tb_inst_trunc(TB_Function* f, TB_Register src, TB_DataType dt
|
||||
TB_API TB_Register tb_inst_int2ptr(TB_Function* f, TB_Register src);
|
||||
TB_API TB_Register tb_inst_ptr2int(TB_Function* f, TB_Register src, TB_DataType dt);
|
||||
|
||||
TB_API TB_Register tb_inst_local(TB_Function* f, uint32_t size, uint32_t alignment);
|
||||
TB_API TB_Register tb_inst_load(TB_Function* f, TB_DataType dt, TB_Register addr, uint32_t alignment);
|
||||
TB_API void tb_inst_store(TB_Function* f, TB_DataType dt, TB_Register addr, TB_Register val, uint32_t alignment);
|
||||
TB_API TB_Register tb_inst_local(TB_Function* f, uint32_t size, TB_CharUnits align);
|
||||
TB_API TB_Register tb_inst_load(TB_Function* f, TB_DataType dt, TB_Register addr, TB_CharUnits align);
|
||||
TB_API void tb_inst_store(TB_Function* f, TB_DataType dt, TB_Register addr, TB_Register val, TB_CharUnits align);
|
||||
|
||||
TB_API TB_Register tb_inst_volatile_load(TB_Function* f, TB_DataType dt, TB_Register addr, uint32_t alignment);
|
||||
TB_API void tb_inst_volatile_store(TB_Function* f, TB_DataType dt, TB_Register addr, TB_Register val, uint32_t alignment);
|
||||
TB_API TB_Register tb_inst_volatile_load(TB_Function* f, TB_DataType dt, TB_Register addr, TB_CharUnits alignment);
|
||||
TB_API void tb_inst_volatile_store(TB_Function* f, TB_DataType dt, TB_Register addr, TB_Register val, TB_CharUnits alignment);
|
||||
|
||||
TB_API TB_Register tb_inst_bool(TB_Function* f, bool imm);
|
||||
TB_API TB_Register tb_inst_ptr(TB_Function* f, uint64_t imm);
|
||||
TB_API TB_Register tb_inst_sint(TB_Function* f, TB_DataType dt, int64_t imm);
|
||||
TB_API TB_Register tb_inst_uint(TB_Function* f, TB_DataType dt, uint64_t imm);
|
||||
TB_API TB_Register tb_inst_float(TB_Function* f, TB_DataType dt, double imm);
|
||||
TB_API TB_Register tb_inst_cstring(TB_Function* f, const char* str);
|
||||
TB_API TB_Register tb_inst_string(TB_Function* f, size_t len, const char* str);
|
||||
|
||||
// Applies an initializer to a memory region
|
||||
TB_API void tb_inst_initialize_mem(TB_Function* f, TB_Register addr, TB_InitializerID src);
|
||||
|
||||
TB_API TB_Register tb_inst_iconst(TB_Function* f, TB_DataType dt, uint64_t imm);
|
||||
TB_API TB_Register tb_inst_fconst(TB_Function* f, TB_DataType dt, double imm);
|
||||
// Broadcasts 'val' across 'count' elements starting 'dst'
|
||||
TB_API void tb_inst_memset(TB_Function* f, TB_Register dst, TB_Register val, TB_Register count, TB_CharUnits align);
|
||||
|
||||
// string is a UTF-8 null terminated string
|
||||
TB_API TB_Register tb_inst_const_cstr(TB_Function* f, const char* str);
|
||||
// performs a copy of 'count' elements from one memory location to another
|
||||
// both locations cannot overlap.
|
||||
TB_API void tb_inst_memcpy(TB_Function* f, TB_Register dst, TB_Register src, TB_Register count, TB_CharUnits align);
|
||||
|
||||
// string is a slice of bytes
|
||||
TB_API TB_Register tb_inst_const_string(TB_Function* f, const char* str, size_t len);
|
||||
// Clears a memory region to zeroes
|
||||
TB_API void tb_inst_memclr(TB_Function* f, TB_Register addr, TB_CharUnits size, TB_CharUnits align);
|
||||
|
||||
// result = base + (index * stride)
|
||||
TB_API TB_Register tb_inst_array_access(TB_Function* f, TB_Register base, TB_Register index, uint32_t stride);
|
||||
|
||||
// result = base + offset
|
||||
// where base is a pointer
|
||||
TB_API TB_Register tb_inst_member_access(TB_Function* f, TB_Register base, int32_t offset);
|
||||
|
||||
TB_API TB_Register tb_inst_get_func_address(TB_Function* f, const TB_Function* target);
|
||||
TB_API TB_Register tb_inst_get_extern_address(TB_Function* f, TB_ExternalID target);
|
||||
TB_API TB_Register tb_inst_get_global_address(TB_Function* f, TB_GlobalID target);
|
||||
|
||||
// Integer arithmatic
|
||||
TB_API TB_Register tb_inst_add(TB_Function* f, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_sub(TB_Function* f, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_mul(TB_Function* f, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_div(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_mod(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
|
||||
// Bitwise operations
|
||||
TB_API TB_Register tb_inst_not(TB_Function* f, TB_Register n);
|
||||
TB_API TB_Register tb_inst_neg(TB_Function* f, TB_Register n);
|
||||
TB_API TB_Register tb_inst_and(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_or(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_xor(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_sar(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_shl(TB_Function* f, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_shr(TB_Function* f, TB_Register a, TB_Register b);
|
||||
|
||||
// Atomics
|
||||
// By default you can use TB_MEM_ORDER_SEQ_CST for the memory order to get
|
||||
// correct but possibly slower results on certain platforms (those with relaxed
|
||||
// memory models).
|
||||
TB_API TB_Register tb_inst_atomic_test_and_set(TB_Function* f, TB_Register addr, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_clear(TB_Function* f, TB_Register addr, TB_MemoryOrder order);
|
||||
|
||||
// All atomic operations here return the old value and the operations are
|
||||
// performed in the same data type as 'src' with alignment of 'addr' being
|
||||
// the natural alignment of 'src'
|
||||
TB_API TB_Register tb_inst_atomic_xchg(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_add(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_sub(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_and(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_xor(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
TB_API TB_Register tb_inst_atomic_or(TB_Function* f, TB_Register addr, TB_Register src, TB_MemoryOrder order);
|
||||
|
||||
// if (*addr == expected) {
|
||||
// old_value = atomic_xchg(addr, desired);
|
||||
// return { true, old_value };
|
||||
// } else {
|
||||
// return { false };
|
||||
// }
|
||||
TB_API TB_CmpXchgResult tb_inst_atomic_cmpxchg(TB_Function* f, TB_Register addr, TB_Register expected, TB_Register desired, TB_MemoryOrder succ, TB_MemoryOrder fail);
|
||||
|
||||
// Float math
|
||||
TB_API TB_Register tb_inst_fadd(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fsub(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fmul(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fdiv(TB_Function* f, TB_Register a, TB_Register b);
|
||||
|
||||
// Comparisons
|
||||
TB_API TB_Register tb_inst_cmp_eq(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_ne(TB_Function* f, TB_Register a, TB_Register b);
|
||||
|
||||
TB_API TB_Register tb_inst_cmp_ilt(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_ile(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_igt(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_ige(TB_Function* f, TB_Register a, TB_Register b, bool signedness);
|
||||
|
||||
TB_API TB_Register tb_inst_cmp_flt(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fle(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fgt(TB_Function* f, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fge(TB_Function* f, TB_Register a, TB_Register b);
|
||||
|
||||
// Control flow
|
||||
TB_API TB_Register tb_inst_call(TB_Function* f, TB_DataType dt, const TB_Function* target, size_t param_count, const TB_Register* params);
|
||||
TB_API TB_Register tb_inst_vcall(TB_Function* f, TB_DataType dt, TB_Register target, size_t param_count, const TB_Register* params);
|
||||
TB_API TB_Register tb_inst_ecall(TB_Function* f, TB_DataType dt, const TB_ExternalID target, size_t param_count, const TB_Register* params);
|
||||
|
||||
TB_API void tb_inst_memset(TB_Function* f, TB_Register dst, TB_Register val, TB_Register size, int align);
|
||||
TB_API void tb_inst_memcpy(TB_Function* f, TB_Register dst, TB_Register src, TB_Register size, int align);
|
||||
|
||||
TB_API TB_Register tb_inst_not(TB_Function* f, TB_DataType dt, TB_Register n);
|
||||
TB_API TB_Register tb_inst_neg(TB_Function* f, TB_DataType dt, TB_Register n);
|
||||
|
||||
TB_API TB_Register tb_inst_and(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_or(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_xor(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_add(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_sub(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_mul(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_div(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, bool signedness);
|
||||
|
||||
TB_API TB_Register tb_inst_shl(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, TB_ArithmaticBehavior arith_behavior);
|
||||
TB_API TB_Register tb_inst_sar(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_shr(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
|
||||
TB_API TB_Register tb_inst_fadd(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fsub(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fmul(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_fdiv(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
|
||||
TB_API TB_Register tb_inst_cmp_eq(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_ne(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
|
||||
TB_API TB_Register tb_inst_cmp_ilt(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_ile(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_igt(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, bool signedness);
|
||||
TB_API TB_Register tb_inst_cmp_ige(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b, bool signedness);
|
||||
|
||||
TB_API TB_Register tb_inst_cmp_flt(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fle(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fgt(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
TB_API TB_Register tb_inst_cmp_fge(TB_Function* f, TB_DataType dt, TB_Register a, TB_Register b);
|
||||
|
||||
// Gives you a reference to a local label, doesn't place it anywhere.
|
||||
TB_API TB_Label tb_inst_new_label_id(TB_Function* f);
|
||||
|
||||
TB_API TB_Register tb_inst_phi2(TB_Function* f, TB_DataType dt, TB_Label a_label, TB_Register a, TB_Label b_label, TB_Register b);
|
||||
TB_API TB_Register tb_inst_phi2(TB_Function* f, TB_Label a_label, TB_Register a, TB_Label b_label, TB_Register b);
|
||||
TB_API TB_Register tb_inst_label(TB_Function* f, TB_Label id);
|
||||
TB_API void tb_inst_goto(TB_Function* f, TB_Label id);
|
||||
TB_API TB_Register tb_inst_if(TB_Function* f, TB_Register cond, TB_Label if_true, TB_Label if_false);
|
||||
@@ -437,7 +490,7 @@ TB_API bool tb_opt_copy_elision(TB_Function* f);
|
||||
// IR access
|
||||
////////////////////////////////
|
||||
TB_API TB_FunctionID tb_function_get_id(TB_Module* m, TB_Function* f);
|
||||
TB_API TB_Function* tb_get_function_by_id(TB_Module* m, TB_FunctionID id);
|
||||
TB_API TB_Function* tb_function_from_id(TB_Module* m, TB_FunctionID id);
|
||||
|
||||
TB_API TB_Register tb_node_get_last_register(TB_Function* f);
|
||||
TB_API TB_DataType tb_node_get_data_type(TB_Function* f, TB_Register r);
|
||||
|
||||
Reference in New Issue
Block a user