Update TB

This commit is contained in:
Christoffer Lerno
2022-05-21 19:57:11 +02:00
parent 3d1eaad6b9
commit 6035cb4600
6 changed files with 902 additions and 348 deletions

View File

@@ -4,6 +4,10 @@
static void tinybackend_emit_expr(TbContext *c, TBEValue *value, Expr *expr);
static inline void tilde_emit_block(TbContext *c, TB_Label label);
static inline void tinybackend_emit_exprid(TbContext *c, TBEValue *value, ExprId id)
{
tinybackend_emit_expr(c, value, exprptr(id));
}
static TB_Register tilde_value_rvalue_get(TbContext *c, TBEValue *value);
static void TBE_VALUE_set_reg(TBEValue *value, TB_Register reg, Type *type);
@@ -36,8 +40,8 @@ TB_DataType tbtype(Type *type)
uint8_t elements = 1;
if (type->type_kind == TYPE_VECTOR)
{
elements = (uint8_t)type->vector.len;
switch (type->vector.base->type_kind)
elements = (uint8_t)type->array.len;
switch (type->array.base->type_kind)
{
case TYPE_U8:
case TYPE_I8:
@@ -111,6 +115,23 @@ static TB_DataType tilde_get_abi_type(AbiType type)
TODO
}
TB_DataType tilde_get_int_type_of_bytesize(int byte_size)
{
switch (byte_size)
{
case 1:
return TB_TYPE_I8;
case 2:
return TB_TYPE_I16;
case 4:
return TB_TYPE_I32;
case 8:
return TB_TYPE_I64;
default:
FATAL_ERROR("Unsupported size");
}
}
static void param_expand(TB_DataType **params_ref, Type *type)
{
switch (type->type_kind)
@@ -192,24 +213,24 @@ static inline void add_func_type_param(Type *param_type, ABIArgInfo *arg_info, T
case ABI_ARG_DIRECT:
vec_add(*params, tbtype(param_type));
break;
case ABI_ARG_DIRECT_SPLIT_STRUCT:
{
// Normal direct.
TB_DataType coerce_type = tbtype(arg_info->direct_struct_expand.type);
for (unsigned idx = 0; idx < arg_info->direct_struct_expand.elements; idx++)
{
vec_add(*params, coerce_type);
}
break;
}
case ABI_ARG_DIRECT_COERCE_INT:
vec_add(*params, tilde_get_int_type_of_bytesize(type_size(param_type)));
break;
case ABI_ARG_DIRECT_COERCE:
{
// Normal direct.
if (!abi_type_is_valid(arg_info->direct_coerce.type))
{
vec_add(*params, tbtype(param_type));
break;
}
TB_DataType coerce_type = tilde_get_abi_type(arg_info->direct_coerce.type);
if (!abi_info_should_flatten(arg_info))
{
vec_add(*params, coerce_type);
break;
}
for (unsigned idx = 0; idx < arg_info->direct_coerce.elements; idx++)
{
vec_add(*params, coerce_type);
}
TB_DataType coerce_type = tbtype(arg_info->direct_coerce_type);
vec_add(*params, coerce_type);
break;
}
case ABI_ARG_DIRECT_PAIR:
@@ -268,13 +289,13 @@ static TB_FunctionPrototype *tilde_get_function_type(TB_Module *module, Function
case ABI_ARG_DIRECT:
return_type = tbtype(call_return_type);
break;
case ABI_ARG_DIRECT_SPLIT_STRUCT:
UNREACHABLE
case ABI_ARG_DIRECT_COERCE_INT:
return_type = tilde_get_int_type_of_bytesize(type_size(call_return_type));
break;
case ABI_ARG_DIRECT_COERCE:
assert(!abi_info_should_flatten(ret_arg_info));
TODO
/*
return_type = llvm_get_coerce_type(context, ret_arg_info);
if (!return_type) return_type = llvm_get_type(context, call_return_type);*/
return_type = tbtype(ret_arg_info->direct_coerce_type);
break;
}
@@ -508,12 +529,12 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
}
else
{
tinybackend_emit_expr(c, &lhs, expr->binary_expr.left);
tinybackend_emit_exprid(c, &lhs, expr->binary_expr.left);
}
value_rvalue(c, &lhs);
TBEValue rhs;
tinybackend_emit_expr(c, &rhs, expr->binary_expr.right);
tinybackend_emit_exprid(c, &rhs, expr->binary_expr.right);
value_rvalue(c, &rhs);
/*EMIT_LOC(c, expr);
@@ -525,7 +546,7 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
Type *lhs_type = lhs.type;
Type *rhs_type = rhs.type;
Type *vector_type = lhs_type->type_kind == TYPE_VECTOR ? lhs_type->vector.base : NULL;
Type *vector_type = lhs_type->type_kind == TYPE_VECTOR ? lhs_type->array.base : NULL;
bool is_float = type_is_float(lhs_type) || (vector_type && type_is_float(vector_type));
TB_Register val = TB_NULL_REG;
@@ -638,6 +659,9 @@ void tinybackend_emit_binary(TbContext *c, TBEValue *TBE_VALUE, Expr *expr, TBEV
case BINARYOP_SHR_ASSIGN:
case BINARYOP_SHL_ASSIGN:
UNREACHABLE
case BINARYOP_OR_ERR:
TODO
break;
}
assert(val);
TBE_VALUE_set(TBE_VALUE, val, expr->type);
@@ -658,7 +682,7 @@ static void tinybackend_emit_binary_expr(TbContext *c, TBEValue *TBE_VALUE, Expr
BinaryOp base_op = binaryop_assign_base_op(binary_op);
assert(base_op != BINARYOP_ERROR);
TBEValue addr;
tinybackend_emit_expr(c, &addr, expr->binary_expr.left);
tinybackend_emit_exprid(c, &addr, expr->binary_expr.left);
value_rvalue(c, &addr);
tinybackend_emit_binary(c, TBE_VALUE, expr, &addr, base_op);
tinybackend_store_value(c, &addr, TBE_VALUE);
@@ -667,11 +691,10 @@ static void tinybackend_emit_binary_expr(TbContext *c, TBEValue *TBE_VALUE, Expr
printf("B\n");
if (binary_op == BINARYOP_ASSIGN)
{
Expr *left = expr->binary_expr.left;
tinybackend_emit_expr(c, TBE_VALUE, expr->binary_expr.left);
tinybackend_emit_exprid(c, TBE_VALUE, expr->binary_expr.left);
assert(tinybackend_value_is_addr(TBE_VALUE));
*TBE_VALUE = tilde_emit_assign_expr(c, TBE_VALUE, expr->binary_expr.right, TB_NULL_REG /* failable_ref */);
*TBE_VALUE = tilde_emit_assign_expr(c, TBE_VALUE, exprptr(expr->binary_expr.right), TB_NULL_REG /* failable_ref */);
return;
}
@@ -694,7 +717,6 @@ static void tinybackend_emit_expr(TbContext *c, TBEValue *value, Expr *expr)
tinybackend_emit_binary_expr(c, value, expr);
return;
case EXPR_IDENTIFIER:
case EXPR_CONST_IDENTIFIER:
value_set_decl(value, expr->identifier_expr.decl);
return;
default:
@@ -724,13 +746,15 @@ static TB_Register tilde_emit_local_decl(TbContext *c, Decl *decl)
if (IS_FAILABLE(decl))
{
scratch_buffer_clear();
scratch_buffer_append(decl->external_name);
scratch_buffer_append(decl_get_extname(decl));
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, initializer, scratch_buffer_to_string(), TB_LINKAGE_PRIVATE);
decl->var.tb_failable_reg = tb_global_create(c->module, scratch_buffer_to_string(), TB_STORAGE_DATA, TB_LINKAGE_PRIVATE);
tb_global_set_initializer(c->module, decl->var.tb_failable_reg, initializer);
}
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, static_initializer, "tempglobal", TB_LINKAGE_PRIVATE);
decl->tb_register = tb_global_create(c->module, "tempglobal", TB_STORAGE_DATA, TB_LINKAGE_PRIVATE);
tb_global_set_initializer(c->module, decl->tb_register, static_initializer);
tilde_emit_global_initializer(c, decl);
return decl->tb_register;
}
@@ -750,14 +774,9 @@ static TB_Register tilde_emit_local_decl(TbContext *c, Decl *decl)
value_set_decl(&value, decl);
if (init)
{
// If we don't have undef, then make an assign.
if (init->expr_kind != EXPR_UNDEF)
{
tilde_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.tb_failable_reg);
}
// TODO trap on undef in debug mode.
tilde_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.tb_failable_reg);
}
else
else if (!decl->var.no_init)
{
if (decl->var.tb_failable_reg)
{
@@ -774,15 +793,15 @@ static TB_Register tilde_emit_local_decl(TbContext *c, Decl *decl)
static void tilde_emit_function_body(TbContext *c, Decl *decl)
{
printf("Function: %s\n", decl->external_name);
printf("Function: %s\n", decl_get_extname(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_LINKAGE_PUBLIC);
TB_Function *function = tb_prototype_build(c->module, prototype, decl_get_extname(decl), TB_LINKAGE_PUBLIC);
c->f = function;
AstId current = decl->func_decl.body->compound_stmt.first_stmt;
AstId current = astptr(decl->func_decl.body)->compound_stmt.first_stmt;
while (current)
{
tilde_emit_stmt(c, ast_next(&current));
@@ -816,7 +835,7 @@ static void tilde_emit_function_body(TbContext *c, Decl *decl)
context->function = prev_function;
*/
tb_function_print(c->f, stdout);
// tb_function_print(c->f, stdout);
// TODO
}
@@ -861,10 +880,13 @@ void *tinybackend_gen(Module *module)
TbContext *c = ccalloc(sizeof(TbContext), 1);
c->code_module = module;
c->module = tb_module_create(tilde_get_arch(), tilde_get_system(), &c->features);
c->module = tb_module_create(tilde_get_arch(), tilde_get_system(), TB_DEBUGFMT_NONE, &c->features);
const char *result = module_create_object_file_name(module);
c->object_filename = strformat("%s%s", result, get_object_extension());
scratch_buffer_clear();
scratch_buffer_printf("%s%s", result, get_object_extension());
c->object_filename = scratch_buffer_copy();
printf("Module: %.*s\n", module->name->len, module->name->module);
// Forward decls
@@ -887,7 +909,8 @@ void *tinybackend_gen(Module *module)
}
}
tb_module_compile(c->module);
// tb_module_compile(c->module);
TODO
return c;
}

View File

@@ -95,6 +95,25 @@ static void tilde_emit_parameter(TbContext *c, TB_Reg **args, ABIArgInfo *info,
case ABI_ARG_IGNORE:
// Skip.
return;
case ABI_ARG_DIRECT_SPLIT_STRUCT:
{
TODO
/*
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
assert(coerce_type && coerce_type != llvm_get_type(c, type));
AlignSize target_alignment = llvm_abi_alignment(c, coerce_type);
AlignSize alignment;
LLVMValueRef cast = llvm_emit_coerce_alignment(c, be_value, coerce_type, target_alignment, &alignment);
LLVMTypeRef element = llvm_get_type(c, info->direct_struct_expand.type);
for (unsigned idx = 0; idx < info->direct_struct_expand.elements; idx++)
{
AlignSize load_align;
LLVMValueRef element_ptr = llvm_emit_struct_gep_raw(c, cast, coerce_type, idx, alignment, &load_align);
vec_add(*args, llvm_load(c, element, element_ptr, load_align, ""));
}
return;*/
}
case ABI_ARG_INDIRECT:
{
// If we want we could optimize for structs by doing it by reference here.
@@ -109,40 +128,31 @@ static void tilde_emit_parameter(TbContext *c, TB_Reg **args, ABIArgInfo *info,
return;
case ABI_ARG_DIRECT_COERCE:
{
if (!abi_type_is_type(info->direct_coerce.type))
TB_DataType coerce_type = tbtype(info->direct_coerce_type);
if (coerce_type.type == tbtype(type).type)
{
vec_add(*args, tilde_load_value(c, be_value));
return;
}
TODO
vec_add(*args, tilde_load_value(c, be_value));
return;
/*
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
if (!coerce_type || coerce_type == llvm_get_type(c, type))
//vec_add(*args, llvm_emit_coerce(c, coerce_type, be_value, type));
//return;
}
case ABI_ARG_DIRECT_COERCE_INT:
{
TB_DataType coerce_type = tilde_get_int_type_of_bytesize(type_size(type));
if (coerce_type.type == tbtype(type).type)
{
vec_add(*args, llvm_load_value_store(c, be_value));
vec_add(*args, tilde_load_value(c, be_value));
return;
}
if (!abi_info_should_flatten(info))
{
vec_add(*args, llvm_emit_coerce(c, coerce_type, be_value, type));
return;
}
AlignSize target_alignment = llvm_abi_alignment(c, coerce_type);
AlignSize alignment;
LLVMValueRef cast = llvm_emit_coerce_alignment(c, be_value, coerce_type, target_alignment, &alignment);
LLVMTypeRef element = llvm_abi_type(c, info->direct_coerce.type);
for (unsigned idx = 0; idx < info->direct_coerce.elements; idx++)
{
AlignSize load_align;
LLVMValueRef element_ptr = llvm_emit_struct_gep_raw(c, cast, coerce_type, idx, alignment, &load_align);
vec_add(*args, llvm_load(c, element, element_ptr, load_align, ""));
}*/
return;
TODO
//vec_add(*args, llvm_emit_coerce(c, coerce_type, be_value, type));
//return;
}
case ABI_ARG_DIRECT_PAIR:
{
TODO
/*
llvm_value_addr(c, be_value);
REMINDER("Handle invalid alignment");
@@ -153,11 +163,7 @@ static void tilde_emit_parameter(TbContext *c, TB_Reg **args, ABIArgInfo *info,
LLVMTypeRef struct_type = llvm_get_coerce_type(c, info);
AlignSize struct_align;
LLVMValueRef cast = llvm_emit_coerce_alignment(c,
be_value,
struct_type,
llvm_abi_alignment(c, struct_type),
&struct_align);
LLVMValueRef cast = llvm_emit_coerce_alignment(c, be_value, struct_type, llvm_abi_alignment(c, struct_type), &struct_align);
// Get the lo value.
AlignSize alignment;
@@ -170,50 +176,36 @@ static void tilde_emit_parameter(TbContext *c, TB_Reg **args, ABIArgInfo *info,
}
case ABI_ARG_EXPAND_COERCE:
{
// Move this to an address (if needed)
value_addr(c, be_value);
/*
// Create the expand type:
LLVMTypeRef coerce_type = llvm_get_coerce_type(c, info);
AlignSize alignment;
LLVMValueRef temp = llvm_emit_coerce_alignment(c,
be_value,
coerce_type,
llvm_abi_alignment(c, coerce_type),
&alignment);
LLVMValueRef temp = LLVMBuildBitCast(c->builder, decl->backend_ref, LLVMPointerType(coerce_type, 0), "coerce");
llvm_emit_and_set_decl_alloca(c, decl);
AlignSize align;
LLVMValueRef gep_first = llvm_emit_struct_gep_raw(c,
temp,
coerce_type,
info->coerce_expand.lo_index,
alignment,
&align);
vec_add(*args, llvm_load(c, llvm_abi_type(c, info->coerce_expand.lo), gep_first, align, ""));
AlignSize alignment = decl->alignment;
AlignSize element_align;
LLVMValueRef gep_first = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.lo_index, alignment, &element_align);
llvm_store(c, gep_first, llvm_get_next_param(c, index), element_align);
if (abi_type_is_valid(info->coerce_expand.hi))
{
LLVMValueRef gep_second = llvm_emit_struct_gep_raw(c,
temp,
coerce_type,
info->coerce_expand.hi_index,
alignment,
&align);
vec_add(*args, llvm_load(c, llvm_abi_type(c, info->coerce_expand.hi), gep_second, align, ""));
}*/
return;
}
case ABI_ARG_EXPAND:
{
// Move this to an address (if needed)
value_addr(c, be_value);
TODO
/*
llvm_expand_type_to_args(c, type, be_value->value, args, be_value->alignment);
// Expand the padding here.
if (info->expand.padding_type)
LLVMValueRef gep_second = llvm_emit_struct_gep_raw(c, temp, coerce_type, info->coerce_expand.hi_index, alignment, &element_align);
llvm_store(c, gep_second, llvm_get_next_param(c, index), element_align);
}
break;*/
case ABI_ARG_EXPAND:
{
vec_add(*args, LLVMGetUndef(llvm_get_type(c, info->expand.padding_type)));
}*/
return;
TODO
/*
// Move this to an address (if needed)
llvm_value_addr(c, be_value);
llvm_expand_type_to_args(c, type, be_value->value, args, be_value->alignment);
// Expand the padding here.
if (info->expand.padding_type)
{
vec_add(*args, LLVMGetUndef(llvm_get_type(c, info->expand.padding_type)));
}
return;*/
}
}
}
@@ -237,7 +229,7 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
// 1. Call through a pointer.
if (expr->call_expr.is_pointer_call)
{
Expr *function = expr->call_expr.function;
Expr *function = exprptr(expr->call_expr.function);
// 1a. Find the pointee type for the function pointer:
Type *type = function->type->canonical->pointer;
@@ -247,7 +239,7 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
// 1c. Evaluate the pointer expression.
TBEValue func_value;
tilde_emit_expr(c, &func_value, expr->call_expr.function);
tilde_emit_expr(c, &func_value, function);
// 1d. Load it as a value
func = tilde_load_value(c, &func_value);
@@ -259,7 +251,7 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
{
// 2a. Get the function declaration
Decl *function_decl = expr->call_expr.func_ref;
Decl *function_decl = declptr(expr->call_expr.func_ref);
always_inline = function_decl->func_decl.attr_inline;
// 2b. Set signature, function and function type
@@ -269,6 +261,7 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
func_type = tbtype(function_decl->type);
}
(void)func_type;
TB_Reg *values = NULL;
Type **params = prototype->params;
ABIArgInfo **abi_args = prototype->abi_args;
@@ -308,7 +301,9 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
case ABI_ARG_DIRECT_COERCE:
case ABI_ARG_DIRECT:
case ABI_ARG_EXPAND_COERCE:
break;
case ABI_ARG_DIRECT_COERCE_INT:
case ABI_ARG_DIRECT_SPLIT_STRUCT:
TODO
}
@@ -424,13 +419,13 @@ void tilde_emit_call_expr(TbContext *c, TBEValue *result_value, Expr *expr)
{
// LLVMSetInstructionCallConv(call_value, llvm_call_convention_from_call(prototype->call_abi, platform_target.arch, platform_target.os));
}
if (expr->call_expr.force_noinline)
if (expr->call_expr.attr_force_noinline)
{
// llvm_attribute_add_call(c, call_value, attribute_id.noinline, -1, 0);
}
else
{
if (expr->call_expr.force_inline || always_inline)
if (expr->call_expr.attr_force_inline || always_inline)
{
// llvm_attribute_add_call(c, call_value, attribute_id.alwaysinline, -1, 0);
}

View File

@@ -14,12 +14,11 @@ void tilde_emit_compound_stmt(TbContext *context, Ast *ast)
{
tilde_emit_stmt(context, ast_next(&current));
}
tilde_emit_defer(context, ast->compound_stmt.defer_list.start, ast->compound_stmt.defer_list.end);
}
static void llvm_emit_ct_compound_stmt(TbContext *context, Ast *ast)
{
assert(ast->ast_kind == AST_CT_COMPOUND_STMT);
assert(ast->ast_kind == AST_COMPOUND_STMT);
AstId current = ast->compound_stmt.first_stmt;
while (current)
{
@@ -39,13 +38,15 @@ TB_Reg tilde_emit_local_decl(TbContext *c, Decl *decl)
if (IS_FAILABLE(decl))
{
scratch_buffer_clear();
scratch_buffer_append(decl->external_name);
scratch_buffer_append(decl_get_extname(decl));
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, initializer, scratch_buffer_to_string(), TB_LINKAGE_PRIVATE);
decl->var.tb_failable_reg = tb_global_create(c->module, scratch_buffer_to_string(), TB_STORAGE_DATA, TB_LINKAGE_PRIVATE);
tb_global_set_initializer(c->module, decl->var.tb_failable_reg, initializer);
}
decl->tb_register = tb_global_create(c->module, decl_get_extname(decl), TB_STORAGE_DATA, 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, static_initializer, "tempglobal", TB_LINKAGE_PRIVATE);
tb_global_set_initializer(c->module, decl->tb_register, static_initializer);
tilde_emit_global_initializer(c, decl);
return decl->tb_register;
}
@@ -65,14 +66,9 @@ TB_Reg tilde_emit_local_decl(TbContext *c, Decl *decl)
value_set_decl(&value, decl);
if (init)
{
// If we don't have undef, then make an assign.
if (init->expr_kind != EXPR_UNDEF)
{
tilde_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.tb_failable_reg);
}
// TODO trap on undef in debug mode.
tilde_emit_assign_expr(c, &value, decl->var.init_expr, decl->var.tb_failable_reg);
}
else
else if (!decl->var.no_init)
{
if (decl->var.tb_failable_reg)
{
@@ -84,24 +80,6 @@ TB_Reg tilde_emit_local_decl(TbContext *c, Decl *decl)
}
void tilde_emit_defer(TbContext *c, AstId defer_start, AstId defer_end)
{
if (defer_start == defer_end) return;
AstId defer = defer_start;
while (defer && defer != defer_end)
{
Ast *def = astptr(defer);
TB_Label exit = tb_inst_new_label_id(c->f);
Ast *body = def->defer_stmt.body;
def->defer_stmt.codegen.exit_val = exit;
tilde_emit_stmt(c, body);
tb_inst_goto(c->f, exit);
tb_inst_label(c->f, exit);
defer = def->defer_stmt.prev_defer;
}
}
void tilde_emit_stmt(TbContext *c, Ast *ast)
{

View File

@@ -34,9 +34,11 @@ void value_addr(TbContext *c, TBEValue *value)
TODO
// TB_Register val = value_rvalue_get(c, value);
// TODO check whether new names must be added
TB_Register val = tb_global_create(c->module, ".taddr", TB_STORAGE_DATA, TB_LINKAGE_PRIVATE);
TB_InitializerID initializer_id = tb_initializer_create(c->module, type_size(value->type),
type_alloca_alignment(value->type), 0);
tb_global_create(c->module, initializer_id, ".taddr", TB_LINKAGE_PRIVATE);
tb_global_set_initializer(c->module, val, initializer_id);
TODO
// TODO set linkage
/*
llvm_set_private_linkage(ref);

View File

@@ -90,7 +90,6 @@ TB_Reg tilde_emit_alloca(TbContext *c, Type *type);
// -- stmt ---
void tilde_emit_stmt(TbContext *c, Ast *ast);
void tilde_emit_defer(TbContext *c, AstId defer_start, AstId defer_end);
// -- general ---
TB_Register tilde_emit_is_no_error(TbContext *c, TB_Reg reg);
@@ -124,4 +123,6 @@ static inline TB_Reg decl_reg(Decl *decl)
return decl->tb_register;
}
TB_DataType tilde_get_int_type_of_bytesize(int byte_size);
#endif // TB_BACKEND

945
tb/tb.h

File diff suppressed because it is too large Load Diff