diff --git a/src/tilde/tb.h b/src/tilde/tb.h index 8b698ff30..4fb5d30ef 100644 --- a/src/tilde/tb.h +++ b/src/tilde/tb.h @@ -195,8 +195,6 @@ typedef union TB_DataType { typedef enum TB_NodeTypeEnum { TB_NULL = 0, - TB_RETURN, // fn(r: region, x: data) - // only one per function TB_START, // fn() @@ -823,7 +821,16 @@ TB_API TB_DebugType* tb_debug_create_array(TB_Module* m, TB_DebugType* base, siz TB_API TB_DebugType* tb_debug_create_struct(TB_Module* m, ptrdiff_t len, const char* tag); TB_API TB_DebugType* tb_debug_create_union(TB_Module* m, ptrdiff_t len, const char* tag); TB_API TB_DebugType* tb_debug_create_field(TB_Module* m, TB_DebugType* type, ptrdiff_t len, const char* name, TB_CharUnits offset); -TB_API void tb_debug_complete_record(TB_DebugType* type, TB_DebugType** members, size_t count, TB_CharUnits size, TB_CharUnits align); + +// returns the array you need to fill with fields +TB_API TB_DebugType** tb_debug_record_begin(TB_DebugType* type, size_t count); +TB_API void tb_debug_record_end(TB_DebugType* type, TB_CharUnits size, TB_CharUnits align); + +TB_API TB_DebugType* tb_debug_create_func(TB_Module* m, TB_CallingConv cc, size_t param_count, size_t return_count, bool has_varargs); + +// you'll need to fill these if you make a function +TB_API TB_DebugType** tb_debug_func_params(TB_DebugType* type); +TB_API TB_DebugType** tb_debug_func_returns(TB_DebugType* type); //////////////////////////////// // IR access @@ -850,6 +857,8 @@ TB_API TB_Global* tb_symbol_as_global(TB_Symbol* s); //////////////////////////////// // Function IR Generation //////////////////////////////// +TB_API void tb_get_data_type_size(TB_Module* mod, TB_DataType dt, size_t* size, size_t* align); + // the user_data is expected to be a valid FILE* TB_API void tb_default_print_callback(void* user_data, const char* fmt, ...); @@ -869,6 +878,12 @@ TB_API void tb_symbol_set_name(TB_Symbol* s, ptrdiff_t len, const char* name); TB_API void tb_symbol_bind_ptr(TB_Symbol* s, void* ptr); TB_API const char* tb_symbol_get_name(TB_Symbol* s); +// same as tb_function_set_prototype except it will handle lowering from types like the TB_DebugType +// into the correct ABI and exposing sane looking nodes to the parameters. +// +// returns the parameters +TB_API TB_Node** tb_function_set_prototype_from_dbg(TB_Function* f, TB_DebugType* dbg, TB_Arena* arena, size_t* out_param_count); + // if arena is NULL, defaults to module arena which is freed on tb_free_thread_resources TB_API void tb_function_set_prototype(TB_Function* f, TB_FunctionPrototype* p, TB_Arena* arena); TB_API TB_FunctionPrototype* tb_function_get_prototype(TB_Function* f); @@ -890,7 +905,6 @@ TB_API void tb_inst_keep_alive(TB_Function* f, TB_Node* src); TB_API TB_Node* tb_inst_poison(TB_Function* f); TB_API TB_Node* tb_inst_param(TB_Function* f, int param_id); -TB_API TB_Node* tb_inst_param_addr(TB_Function* f, int param_id); TB_API TB_Node* tb_inst_fpxt(TB_Function* f, TB_Node* src, TB_DataType dt); TB_API TB_Node* tb_inst_sxt(TB_Function* f, TB_Node* src, TB_DataType dt); @@ -902,7 +916,7 @@ TB_API TB_Node* tb_inst_int2float(TB_Function* f, TB_Node* src, TB_DataType dt, TB_API TB_Node* tb_inst_float2int(TB_Function* f, TB_Node* src, TB_DataType dt, bool is_signed); TB_API TB_Node* tb_inst_bitcast(TB_Function* f, TB_Node* src, TB_DataType dt); -TB_API TB_Node* tb_inst_local(TB_Function* f, uint32_t size, TB_CharUnits align); +TB_API TB_Node* tb_inst_local(TB_Function* f, TB_CharUnits size, TB_CharUnits align); TB_API TB_Node* tb_inst_load(TB_Function* f, TB_DataType dt, TB_Node* addr, TB_CharUnits align, bool is_volatile); TB_API void tb_inst_store(TB_Function* f, TB_DataType dt, TB_Node* addr, TB_Node* val, TB_CharUnits align, bool is_volatile); @@ -918,7 +932,7 @@ TB_API TB_Node* tb_inst_string(TB_Function* f, size_t len, const char* str); TB_API void tb_inst_memset(TB_Function* f, TB_Node* dst, TB_Node* val, TB_Node* count, TB_CharUnits align, bool is_volatile); // zero 'count' bytes on 'dst' -TB_API void tb_inst_memzero(TB_Function* f, TB_Node* dst, TB_Node* val, TB_Node* count, TB_CharUnits align, bool is_volatile); +TB_API void tb_inst_memzero(TB_Function* f, TB_Node* dst, TB_Node* count, TB_CharUnits align, bool is_volatile); // performs a copy of 'count' elements from one memory location to another // both locations cannot overlap. diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib index bad51e7e6..b52ce4c55 100644 Binary files a/src/tilde/tb.lib and b/src/tilde/tb.lib differ diff --git a/src/tilde_backend.cpp b/src/tilde_backend.cpp index dfe39c385..db759b767 100644 --- a/src/tilde_backend.cpp +++ b/src/tilde_backend.cpp @@ -31,7 +31,7 @@ gb_internal TB_DataType cg_data_type(Type *t) { case Basic_uint: case Basic_uintptr: case Basic_typeid: - return TB_TYPE_INTN(cast(u16)(8*sz)); + return TB_TYPE_INTN(cast(u16)gb_min(8*sz, 64)); case Basic_f16: return TB_TYPE_F16; case Basic_f32: return TB_TYPE_F32; @@ -58,7 +58,7 @@ gb_internal TB_DataType cg_data_type(Type *t) { case Basic_u64be: case Basic_i128be: case Basic_u128be: - return TB_TYPE_INTN(cast(u16)(8*sz)); + return TB_TYPE_INTN(cast(u16)gb_min(8*sz, 64)); case Basic_f16le: return TB_TYPE_F16; case Basic_f32le: return TB_TYPE_F32; diff --git a/src/tilde_backend.hpp b/src/tilde_backend.hpp index 073e81f5d..b2192cce4 100644 --- a/src/tilde_backend.hpp +++ b/src/tilde_backend.hpp @@ -8,7 +8,8 @@ #include "tilde/tb.h" #define TB_TYPE_F16 TB_DataType{ { TB_INT, 0, 16 } } -#define TB_TYPE_I128 TB_DataType{ { TB_INT, 0, 128 } } +// #define TB_TYPE_I128 TB_DataType{ { TB_INT, 0, 128 } } +#define TB_TYPE_I128 TB_TYPE_INTN(64) #define TB_TYPE_INT TB_TYPE_INTN(cast(u16)(8*build_context.int_size)) #define TB_TYPE_INTPTR TB_TYPE_INTN(cast(u16)(8*build_context.ptr_size)) diff --git a/src/tilde_const.cpp b/src/tilde_const.cpp index 35c87641f..75b66567e 100644 --- a/src/tilde_const.cpp +++ b/src/tilde_const.cpp @@ -86,7 +86,7 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type); case ExactValue_Integer: - GB_ASSERT(dt.raw != TB_TYPE_I128.raw); + // GB_ASSERT(dt.raw != TB_TYPE_I128.raw); if (is_type_unsigned(type)) { u64 i = exact_value_to_u64(value); return cg_value(tb_inst_uint(p->func, dt, i), type); diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index d763e2f8c..af9bee189 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -35,7 +35,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty case Basic_int: case Basic_uint: case Basic_uintptr: - param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + param.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; case Basic_f16: param.dt = TB_TYPE_F16; break; @@ -66,7 +66,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty break; case Basic_typeid: - param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + param.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; // Endian Specific Types @@ -86,7 +86,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty case Basic_u64be: case Basic_i128be: case Basic_u128be: - param.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + param.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; case Basic_f16le: param.dt = TB_TYPE_F16; break; @@ -171,7 +171,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty case Basic_int: case Basic_uint: case Basic_uintptr: - result.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + result.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; case Basic_f16: result.dt = TB_TYPE_I16; break; @@ -186,7 +186,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty break; case Basic_typeid: - result.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + result.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; // Endian Specific Types @@ -206,7 +206,7 @@ gb_internal TB_FunctionPrototype *cg_procedure_type_as_prototype(cgModule *m, Ty case Basic_u64be: case Basic_i128be: case Basic_u128be: - result.dt = TB_TYPE_INTN(cast(u16)(8*sz)); + result.dt = TB_TYPE_INTN(cast(u16)gb_min(64, 8*sz)); break; case Basic_f16le: result.dt = TB_TYPE_I16; break; @@ -395,70 +395,75 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { GB_ASSERT(p->type->kind == Type_Proc); TypeProc *pt = &p->type->Proc; - if (pt->params) { - int param_index = 0; - for (Entity *e : pt->params->Tuple.variables) { - if (e->kind != Entity_Variable) { - continue; - } - - if (param_index >= p->proto->param_count) { - break; - } - - TB_Node *ptr = tb_inst_param_addr(p->func, param_index); - cgValue local = cg_value(ptr, alloc_type_pointer(e->type)); - - if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { - // NOTE(bill): for debugging purposes only - String name = e->token.string; - TB_DebugType *debug_type = cg_debug_type(p->module, e->type); - tb_node_append_attrib(ptr, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); - - } - cgAddr addr = cg_addr(local); - if (e) { - map_set(&p->variable_map, e, addr); - } - - // if (arg_type->kind == lbArg_Ignore) { - // continue; - // } else if (arg_type->kind == lbArg_Direct) { - // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { - // LLVMTypeRef param_type = lb_type(p->module, e->type); - // LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index); - // LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type); - - // lbValue param = {}; - // param.value = value; - // param.type = e->type; - - // map_set(&p->direct_parameters, e, param); - - // lbValue ptr = lb_address_from_load_or_generate_local(p, param); - // GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); - // lb_add_entity(p->module, e, ptr); - - // lbBlock *block = p->decl_block; - // if (original_value != value) { - // block = p->curr_block; - // } - // LLVMValueRef debug_storage_value = value; - // if (original_value != value && LLVMIsALoadInst(value)) { - // debug_storage_value = LLVMGetOperand(value, 0); - // } - // lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block, arg_type->kind); - // } - // } else if (arg_type->kind == lbArg_Indirect) { - // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { - // lbValue ptr = {}; - // ptr.value = LLVMGetParam(p->value, param_offset+param_index); - // ptr.type = alloc_type_pointer(e->type); - // lb_add_entity(p->module, e, ptr); - // lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block, arg_type->kind); - // } - // } + if (pt->params == nullptr) { + return; + } + int param_index = 0; + for (Entity *e : pt->params->Tuple.variables) { + if (e->kind != Entity_Variable) { + continue; } + + if (param_index >= p->proto->param_count) { + break; + } + + // TB_Node *ptr = tb_inst_param_addr(p->func, param_index); + TB_Node *param = tb_inst_param(p->func, param_index); + TB_Node *ptr = tb_inst_local(p->func, cast(TB_CharUnits)type_size_of(e->type), cast(TB_CharUnits)type_align_of(e->type)); + TB_DataType dt = cg_data_type(e->type); + tb_inst_store(p->func, dt, ptr, param, cast(TB_CharUnits)type_align_of(e->type), false); + cgValue local = cg_value(ptr, alloc_type_pointer(e->type)); + + if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") { + // NOTE(bill): for debugging purposes only + String name = e->token.string; + TB_DebugType *debug_type = cg_debug_type(p->module, e->type); + tb_node_append_attrib(ptr, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); + + } + cgAddr addr = cg_addr(local); + if (e) { + map_set(&p->variable_map, e, addr); + } + + // if (arg_type->kind == lbArg_Ignore) { + // continue; + // } else if (arg_type->kind == lbArg_Direct) { + // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { + // LLVMTypeRef param_type = lb_type(p->module, e->type); + // LLVMValueRef original_value = LLVMGetParam(p->value, param_offset+param_index); + // LLVMValueRef value = OdinLLVMBuildTransmute(p, original_value, param_type); + + // lbValue param = {}; + // param.value = value; + // param.type = e->type; + + // map_set(&p->direct_parameters, e, param); + + // lbValue ptr = lb_address_from_load_or_generate_local(p, param); + // GB_ASSERT(LLVMIsAAllocaInst(ptr.value)); + // lb_add_entity(p->module, e, ptr); + + // lbBlock *block = p->decl_block; + // if (original_value != value) { + // block = p->curr_block; + // } + // LLVMValueRef debug_storage_value = value; + // if (original_value != value && LLVMIsALoadInst(value)) { + // debug_storage_value = LLVMGetOperand(value, 0); + // } + // lb_add_debug_param_variable(p, debug_storage_value, e->type, e->token, param_index+1, block, arg_type->kind); + // } + // } else if (arg_type->kind == lbArg_Indirect) { + // if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { + // lbValue ptr = {}; + // ptr.value = LLVMGetParam(p->value, param_offset+param_index); + // ptr.type = alloc_type_pointer(e->type); + // lb_add_entity(p->module, e, ptr); + // lb_add_debug_param_variable(p, ptr.value, e->type, e->token, param_index+1, p->decl_block, arg_type->kind); + // } + // } } } @@ -466,7 +471,9 @@ gb_internal void cg_procedure_end(cgProcedure *p) { if (p == nullptr || p->func == nullptr) { return; } - tb_inst_ret(p->func, 0, nullptr); + if (tb_inst_get_control(p->func)) { + tb_inst_ret(p->func, 0, nullptr); + } if (p->name == "main") { TB_Arena *arena = tb_default_arena(); defer (arena->free(arena)); diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index a38886c2e..787b94a58 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -736,7 +736,33 @@ gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) { } gb_internal void cg_build_return_stmt(cgProcedure *p, Slice const &return_results) { + TypeTuple *tuple = &p->type->Proc.results->Tuple; + isize return_count = p->type->Proc.result_count; + gb_unused(tuple); + isize res_count = return_results.count; + gb_unused(res_count); + if (return_count == 0) { + tb_inst_ret(p->func, 0, nullptr); + return; + } else if (return_count == 1) { + Entity *e = tuple->variables[0]; + if (res_count == 0) { + cgValue zero = cg_const_nil(p, tuple->variables[0]->type); + if (zero.kind == cgValue_Value) { + tb_inst_ret(p->func, 1, &zero.node); + } + return; + } + cgValue res = cg_build_expr(p, return_results[0]); + res = cg_emit_conv(p, res, e->type); + if (res.kind == cgValue_Value) { + tb_inst_ret(p->func, 1, &res.node); + } + return; + } else { + GB_PANIC("TODO(bill): MUTLIPLE RETURN VALUES"); + } }