diff --git a/src/tilde.cpp b/src/tilde.cpp index a0f1fd844..b27c42a12 100644 --- a/src/tilde.cpp +++ b/src/tilde.cpp @@ -213,9 +213,9 @@ gb_internal cgAddr cg_addr_soa_variable(cgValue addr, cgValue index, Ast *index_ gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) { if (node) { TokenPos pos = ast_token(node).pos; - TB_FileID *file_id = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id); - if (file_id) { - tb_inst_set_location(p->func, *file_id, pos.line); + TB_SourceFile **file = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id); + if (file) { + tb_inst_set_location(p->func, *file, pos.line, pos.column); } } } @@ -464,8 +464,9 @@ gb_internal cgModule *cg_module_create(Checker *c) { for_array(id, global_files) { if (AstFile *f = global_files[id]) { - char const *path = alloc_cstring(permanent_allocator(), f->fullpath); - map_set(&m->file_id_map, cast(uintptr)id, tb_file_create(m->mod, path)); + char const *path = alloc_cstring(temporary_allocator(), f->fullpath); + TB_SourceFile *file = tb_get_source_file(m->mod, path); + map_set(&m->file_id_map, cast(uintptr)id, file); } } diff --git a/src/tilde.hpp b/src/tilde.hpp index 76417a9cf..7088912fd 100644 --- a/src/tilde.hpp +++ b/src/tilde.hpp @@ -243,7 +243,7 @@ struct cgModule { PtrMap map_cell_info_map; // NOTE(bill): no need to protect this with a mutex - PtrMap file_id_map; // Key: AstFile.id (i32 cast to uintptr) + PtrMap file_id_map; // Key: AstFile.id (i32 cast to uintptr) std::atomic nested_type_name_guid; std::atomic const_nil_guid; diff --git a/src/tilde/tb.h b/src/tilde/tb.h index b20b98b35..5df2cdc00 100644 --- a/src/tilde/tb.h +++ b/src/tilde/tb.h @@ -209,8 +209,8 @@ typedef enum TB_NodeTypeEnum { // projection TB_PROJ, - TB_CALL, // normal call - TB_SCALL, // system call + TB_CALL, // normal call + TB_SYSCALL, // system call // Managed ops TB_SAFEPOINT, @@ -334,8 +334,6 @@ typedef enum TB_NodeTypeEnum { } TB_NodeTypeEnum; typedef uint8_t TB_NodeType; -typedef int TB_Label; - // just represents some region of bytes, usually in file parsing crap typedef struct { size_t length; @@ -345,7 +343,13 @@ typedef struct { // represents byte counts typedef uint32_t TB_CharUnits; -typedef unsigned int TB_FileID; +// will get interned so each TB_Module has a unique identifier for the source file +typedef struct { + // used by the debug info export + int id; + size_t len; + uint8_t path[]; +} TB_SourceFile; // SO refers to shared objects which mean either shared libraries (.so or .dll) // or executables (.exe or ELF executables) @@ -362,11 +366,12 @@ typedef struct TB_External TB_External; typedef struct TB_Function TB_Function; typedef struct TB_Module TB_Module; -typedef struct TB_Attrib TB_Attrib; typedef struct TB_DebugType TB_DebugType; typedef struct TB_ModuleSection TB_ModuleSection; typedef struct TB_FunctionPrototype TB_FunctionPrototype; +typedef struct TB_Attrib TB_Attrib; + // Refers generically to objects within a module // // TB_Function, TB_Global, and TB_External are all subtypes of TB_Symbol @@ -404,8 +409,6 @@ typedef struct TB_Symbol { // after this point it's tag-specific storage } TB_Symbol; -typedef int TB_Reg; - typedef struct TB_Node TB_Node; struct TB_Node { TB_NodeType type; @@ -413,14 +416,12 @@ struct TB_Node { uint16_t input_count; // number of node inputs uint16_t extra_count; // number of bytes for extra operand data - TB_Attrib* first_attrib; + TB_Attrib* attribs; TB_Node** inputs; char extra[]; }; -#define TB_KILL_NODE(n) ((n)->type = TB_NULL) - // These are the extra data in specific nodes #define TB_NODE_GET_EXTRA(n) ((void*) n->extra) #define TB_NODE_GET_EXTRA_T(n, T) ((T*) (n)->extra) @@ -464,8 +465,8 @@ typedef struct { } TB_NodeLocal; typedef struct { - TB_FileID file; - int line; + TB_SourceFile* file; + int line, column; } TB_NodeLine; typedef struct { @@ -506,6 +507,10 @@ typedef struct { TB_Node* end; const char* tag; + // immediate dominator (can be approximate) + int dom_depth; + TB_Node* dom; + size_t succ_count; TB_Node** succ; @@ -736,7 +741,8 @@ TB_API TB_ExternalType tb_extern_get_type(TB_External* e); TB_Global* tb_extern_transmute(TB_External* e, TB_DebugType* dbg_type, TB_Linkage linkage); TB_API TB_External* tb_extern_create(TB_Module* m, ptrdiff_t len, const char* name, TB_ExternalType type); -TB_API TB_FileID tb_file_create(TB_Module* m, const char* path); + +TB_API TB_SourceFile* tb_get_source_file(TB_Module* m, const char* path); // Called once you're done with TB operations on a thread (or i guess when it's // about to be killed :p), not calling it can only result in leaks on that thread @@ -818,11 +824,10 @@ TB_API TB_ModuleSection* tb_module_get_tls(TB_Module* m); //////////////////////////////// // Function Attributes //////////////////////////////// -TB_API void tb_node_append_attrib(TB_Node* n, TB_Attrib* a); - // These are parts of a function that describe metadata for instructions -TB_API TB_Attrib* tb_function_attrib_variable(TB_Function* f, ptrdiff_t len, const char* name, TB_DebugType* type); -TB_API TB_Attrib* tb_function_attrib_scope(TB_Function* f, TB_Attrib* parent_scope); +TB_API void tb_function_attrib_variable(TB_Function* f, TB_Node* n, TB_Node* parent, ptrdiff_t len, const char* name, TB_DebugType* type); +TB_API void tb_function_attrib_scope(TB_Function* f, TB_Node* n, TB_Node* parent); +TB_API void tb_function_attrib_location(TB_Function* f, TB_Node* n, TB_SourceFile* file, int line, int column); //////////////////////////////// // Debug info Generation @@ -839,7 +844,7 @@ TB_API TB_DebugType* tb_debug_create_union(TB_Module* m, ptrdiff_t len, const ch TB_API TB_DebugType* tb_debug_create_field(TB_Module* m, TB_DebugType* type, ptrdiff_t len, const char* name, TB_CharUnits offset); // 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 TB_DebugType** tb_debug_record_begin(TB_Module* m, 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); @@ -877,11 +882,13 @@ TB_API void tb_get_data_type_size(TB_Module* mod, TB_DataType dt, size_t* size, // the user_data is expected to be a valid FILE* TB_API void tb_default_print_callback(void* user_data, const char* fmt, ...); -TB_API void tb_inst_set_location(TB_Function* f, TB_FileID file, int line); +TB_API void tb_inst_set_location(TB_Function* f, TB_SourceFile* file, int line, int column); +TB_API void tb_inst_reset_location(TB_Function* f); // if section is NULL, default to .text TB_API TB_Function* tb_function_create(TB_Module* m, ptrdiff_t len, const char* name, TB_Linkage linkage, TB_ComdatType comdat); +TB_API TB_Arena* tb_function_get_arena(TB_Function* f); TB_API void* tb_function_get_jit_pos(TB_Function* f); // if len is -1, it's null terminated @@ -902,7 +909,7 @@ TB_API TB_Node* tb_inst_get_control(TB_Function* f); TB_API TB_Node* tb_inst_region(TB_Function* f); // if len is -1, it's null terminated -TB_API void tb_inst_set_region_name(TB_Node* n, ptrdiff_t len, const char* name); +TB_API void tb_inst_set_region_name(TB_Module* m, TB_Node* n, ptrdiff_t len, const char* name); TB_API void tb_inst_unreachable(TB_Function* f); TB_API void tb_inst_debugbreak(TB_Function* f); @@ -1072,16 +1079,22 @@ TB_API void tb_pass_exit(TB_Passes* opt); // data flow analysis possible on the code and allows to codegen // to place variables into registers. // +// cfg: performs simplifications on the CFG like `a && b => select(a, b, 0)` +// or removing redundant branches. +// // loop: NOT READY // TB_API bool tb_pass_peephole(TB_Passes* opt); TB_API bool tb_pass_mem2reg(TB_Passes* opt); TB_API bool tb_pass_loop(TB_Passes* opt); +TB_API bool tb_pass_cfg(TB_Passes* opt); // analysis // print: prints IR in a flattened text form. TB_API bool tb_pass_print(TB_Passes* opt); +TB_API void tb_pass_schedule(TB_Passes* opt); + // codegen TB_API TB_FunctionOutput* tb_pass_codegen(TB_Passes* opt, bool emit_asm); diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib index 1dc4f3557..c326899af 100644 Binary files a/src/tilde/tb.lib and b/src/tilde/tb.lib differ diff --git a/src/tilde/tb_arena.h b/src/tilde/tb_arena.h index d50e777da..2ec0d4584 100644 --- a/src/tilde/tb_arena.h +++ b/src/tilde/tb_arena.h @@ -68,6 +68,8 @@ TB_API void tb_arena_realign(TB_Arena* restrict arena); TB_API bool tb_arena_is_empty(TB_Arena* arena); +TB_API size_t tb_arena_current_size(TB_Arena* arena); + // savepoints TB_API TB_ArenaSavepoint tb_arena_save(TB_Arena* arena); TB_API void tb_arena_restore(TB_Arena* arena, TB_ArenaSavepoint sp); diff --git a/src/tilde_debug.cpp b/src/tilde_debug.cpp index 926cf9cd0..a4b82bf72 100644 --- a/src/tilde_debug.cpp +++ b/src/tilde_debug.cpp @@ -45,7 +45,7 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, map_set(&m->debug_type_map, type, record); } - TB_DebugType **fields = tb_debug_record_begin(record, bt->Struct.fields.count); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, bt->Struct.fields.count); for_array(i, bt->Struct.fields) { Entity *e = bt->Struct.fields[i]; Type *type = e->type; @@ -82,7 +82,7 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, record_count += 1; } } - TB_DebugType **fields = tb_debug_record_begin(record, record_count); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, record_count); for_array(i, bt->Tuple.variables) { Entity *e = bt->Tuple.variables[i]; if (e->kind != Entity_Variable) { @@ -120,7 +120,7 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, if (is_type_union_maybe_pointer(bt)) { // NO TAG GB_ASSERT(variant_count == 1); - TB_DebugType **fields = tb_debug_record_begin(record, variant_count); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, variant_count); TB_DebugType *variant_type = cg_debug_type(m, bt->Union.variants[0]); fields[0] = tb_debug_create_field(m->mod, variant_type, -1, "v0", 0); tb_debug_record_end( @@ -129,7 +129,7 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type, cast(TB_CharUnits)type_align_of(type) ); } else { - TB_DebugType **fields = tb_debug_record_begin(record, variant_count+1); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, variant_count+1); for_array(i, bt->Union.variants) { Type *v = bt->Union.variants[i]; TB_DebugType *variant_type = cg_debug_type(m, v); @@ -214,7 +214,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { TB_CharUnits elem_size = cast(TB_CharUnits)type_size_of(et); TB_DebugType *elem = cg_debug_type(m, et); - TB_DebugType **fields = tb_debug_record_begin(record, 2); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); fields[0] = tb_debug_create_field(m->mod, elem, -1, "real", 0*elem_size); fields[1] = tb_debug_create_field(m->mod, elem, -1, "imag", 1*elem_size); @@ -232,7 +232,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { TB_DebugType *elem = cg_debug_type(m, et); // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(record, 4); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 4); fields[0] = tb_debug_create_field(m->mod, elem, -1, "imag", 0*elem_size); fields[1] = tb_debug_create_field(m->mod, elem, -1, "jmag", 1*elem_size); fields[2] = tb_debug_create_field(m->mod, elem, -1, "kmag", 2*elem_size); @@ -253,7 +253,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { String name = basic_types[type->Basic.kind].Basic.name; TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(record, 2); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, t_u8_ptr), -1, "data", 0*int_size); fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); @@ -268,7 +268,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { String name = basic_types[type->Basic.kind].Basic.name; TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); // @QuaternionLayout - TB_DebugType **fields = tb_debug_record_begin(record, 2); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, t_rawptr), -1, "data", 0*ptr_size); fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_typeid), -1, "id", 1*ptr_size); @@ -317,7 +317,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { { String name = {}; TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(record, 2); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->Slice.elem)), -1, "data", 0*int_size); fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); @@ -328,7 +328,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { { String name = {}; TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(record, 4); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 4); fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->Slice.elem)), -1, "data", 0*int_size); fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "len", 1*int_size); fields[2] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "cap", 2*int_size); @@ -468,7 +468,7 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) { { String name = {}; TB_DebugType *record = tb_debug_create_struct(m->mod, name.len, cast(char const *)name.text); - TB_DebugType **fields = tb_debug_record_begin(record, 2); + TB_DebugType **fields = tb_debug_record_begin(m->mod, record, 2); fields[0] = tb_debug_create_field(m->mod, cg_debug_type(m, alloc_type_pointer(type->SoaPointer.elem)), -1, "ptr", 0*int_size); fields[1] = tb_debug_create_field(m->mod, cg_debug_type(m, t_int), -1, "offset", 1*int_size); diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index dfb04774e..cd4e9f2d3 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -55,7 +55,7 @@ gb_internal cgAddr cg_find_or_generate_context_ptr(cgProcedure *p) { GB_ASSERT(pt->Proc.calling_convention != ProcCC_Odin); cgAddr c = cg_add_local(p, t_context, nullptr, true); - tb_node_append_attrib(c.addr.node, tb_function_attrib_variable(p->func, -1, "context", cg_debug_type(p->module, t_context))); + tb_function_attrib_variable(p->func, c.addr.node, nullptr, -1, "context", cg_debug_type(p->module, t_context)); c.kind = cgAddr_Context; // lb_emit_init_context(p, c); cg_push_context_onto_stack(p, c); diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index a9a69e415..7fc2dbdfe 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -305,13 +305,12 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { param_ptr_to_use = dummy_param; param_debug_type = tb_debug_create_ptr(p->module->mod, param_debug_type); } - tb_node_append_attrib( + tb_function_attrib_variable( + p->func, param_ptr_to_use, - tb_function_attrib_variable( - p->func, - name.len, cast(char const *)name.text, - param_debug_type - ) + nullptr, // parent + name.len, cast(char const *)name.text, + param_debug_type ); } cgAddr addr = cg_addr(local); @@ -1097,8 +1096,25 @@ gb_internal cgProcedure *cg_equal_proc_for_type(cgModule *m, Type *type) { cg_emit_if(p, tag_eq, switch_region, false_region); size_t entry_count = type->Union.variants.count; + if (type->Union.kind != UnionType_no_nil) { + entry_count += 1; + } + + size_t entry_index = 0; + TB_SwitchEntry *keys = gb_alloc_array(temporary_allocator(), TB_SwitchEntry, entry_count); - for (size_t i = 0; i < entry_count; i++) { + if (type->Union.kind != UnionType_no_nil) { + TB_Node *region = cg_control_region(p, "bcase"); + keys[entry_index].key = 0; + keys[entry_index].value = region; + entry_index += 1; + + tb_inst_set_control(p->func, region); + cgValue ok = cg_const_bool(p, t_bool, true); + cg_build_return_stmt_internal_single(p, ok); + } + + for (size_t i = entry_index; i < entry_count; i++) { TB_Node *region = cg_control_region(p, "bcase"); Type *variant = type->Union.variants[i]; keys[i].key = union_variant_index(type, variant); diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 5caf5d52e..bebafe098 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -15,7 +15,7 @@ gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name) { n = -1 + gb_snprintf(new_name, n+11, "%.*s_%u", cast(int)n, name, p->control_regions.count); TB_Node *region = tb_inst_region(p->func); - tb_inst_set_region_name(region, n, new_name); + tb_inst_set_region_name(p->module->mod, region, n, new_name); GB_ASSERT(p->scope_index >= 0); array_add(&p->control_regions, cgControlRegion{region, p->scope_index}); @@ -808,7 +808,7 @@ gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero // NOTE(bill): for debugging purposes only String name = e->token.string; TB_DebugType *debug_type = cg_debug_type(p->module, type); - tb_node_append_attrib(local, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); + tb_function_attrib_variable(p->func, local, nullptr, name.len, cast(char const *)name.text, debug_type); } if (zero_init) { @@ -842,7 +842,7 @@ gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e) { // NOTE(bill): for debugging purposes only String name = e->token.string; TB_DebugType *debug_type = cg_debug_type(p->module, type); - tb_node_append_attrib(local, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type)); + tb_function_attrib_variable(p->func, local, nullptr, name.len, cast(char const *)name.text, debug_type); } cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type))); @@ -2414,8 +2414,7 @@ gb_internal void cg_build_type_switch_stmt(cgProcedure *p, Ast *node) { cg_add_entity(p->module, case_entity, ptr); String name = case_entity->token.string; - TB_Attrib *dbg = tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, cg_debug_type(p->module, ct)); - tb_node_append_attrib(ptr.node, dbg); + tb_function_attrib_variable(p->func, ptr.node, nullptr, name.len, cast(char const *)name.text, cg_debug_type(p->module, ct)); } else { if (case_entity->flags & EntityFlag_Value) { // by value @@ -2547,7 +2546,7 @@ gb_internal void cg_build_mutable_value_decl(cgProcedure *p, Ast *node) { // 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)); + tb_function_attrib_variable(p->func, ptr, nullptr, name.len, cast(char const *)name.text, debug_type); } cgAddr addr = cg_addr(inits[i]);