From 4236519b84e2bea73b1b7756a20a2df24d3fb070 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 18 Jun 2017 14:36:06 +0100 Subject: [PATCH] `#location(..)` and `#call_location` --- core/_preload.odin | 13 ++++++ src/check_expr.cpp | 112 ++++++++++++++++++++++++++++++++++----------- src/check_stmt.cpp | 2 +- src/checker.cpp | 25 +++++++--- src/entity.cpp | 1 + src/integer128.cpp | 7 ++- src/ir.cpp | 61 ++++++++++++++++++++---- src/main.cpp | 4 +- src/parser.cpp | 34 ++++++++------ src/string.cpp | 7 ++- src/types.cpp | 71 ++++++++++++++-------------- 11 files changed, 241 insertions(+), 96 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index df6b2e79d..b0639860c 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -184,6 +184,19 @@ type ( #thread_local var __context: Context; + +type SourceCodeLocation struct { + fully_pathed_filename: string, + procedure: string, + line, column: i64, +} + +proc make_source_code_location(file, procedure: string, line, column: i64) -> SourceCodeLocation { + return SourceCodeLocation{file, procedure, line, column}; +} + + + const DEFAULT_ALIGNMENT = align_of([vector 4]f32); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8759f9f09..52d2edd36 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1062,22 +1062,30 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari ast_node(p, Field, param); AstNode *type_expr = p->type; Type *type = NULL; - AstNode *default_value = p->default_value; + AstNode *default_value = unparen_expr(p->default_value); ExactValue value = {}; bool default_is_nil = false; + bool default_is_location = false; if (type_expr == NULL) { - Operand o = {}; - check_expr_or_type(c, &o, default_value); - if (is_operand_nil(o)) { - default_is_nil = true; - } else if (o.mode != Addressing_Constant) { - error_node(default_value, "Default parameter must be a constant"); + if (default_value->kind == AstNode_BasicDirective && + default_value->BasicDirective.name == "caller_location") { + init_preload(c); + default_is_location = true; + type = t_source_code_location; } else { - value = o.value; - } + Operand o = {}; + check_expr_or_type(c, &o, default_value); + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error_node(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } - type = default_type(o.type); + type = default_type(o.type); + } } else { if (type_expr->kind == AstNode_Ellipsis) { type_expr = type_expr->Ellipsis.expr; @@ -1095,14 +1103,22 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari if (default_value != NULL) { Operand o = {}; - check_expr_with_type_hint(c, &o, default_value, type); - - if (is_operand_nil(o)) { - default_is_nil = true; - } else if (o.mode != Addressing_Constant) { - error_node(default_value, "Default parameter must be a constant"); + if (default_value->kind == AstNode_BasicDirective && + default_value->BasicDirective.name == "caller_location") { + init_preload(c); + default_is_location = true; + o.type = t_source_code_location; + o.mode = Addressing_Value; } else { - value = o.value; + check_expr_with_type_hint(c, &o, default_value, type); + + if (is_operand_nil(o)) { + default_is_nil = true; + } else if (o.mode != Addressing_Constant) { + error_node(default_value, "Default parameter must be a constant"); + } else { + value = o.value; + } } check_is_assignable_to(c, &o, type); @@ -1145,6 +1161,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari (p->flags&FieldFlag_using) != 0, false); param->Variable.default_value = value; param->Variable.default_is_nil = default_is_nil; + param->Variable.default_is_location = default_is_location; } if (p->flags&FieldFlag_no_alias) { param->flags |= EntityFlag_NoAlias; @@ -3639,7 +3656,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id // NOTE(bill): The first arg may be a Type, this will be checked case by case break; default: - check_multi_expr(c, operand, ce->args[0]); + if (ce->args.count > 0) { + check_multi_expr(c, operand, ce->args[0]); + } + break; } switch (id) { @@ -3647,6 +3667,32 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_procs[id].name)); break; + case BuiltinProc_DIRECTIVE: { + ast_node(bd, BasicDirective, ce->proc); + String name = bd->name; + GB_ASSERT(name == "location"); + if (ce->args.count > 1) { + error_node(ce->args[0], "`#location` expects either 0 or 1 arguments, got %td", ce->args.count); + } + if (ce->args.count > 0) { + AstNode *arg = ce->args[0]; + Entity *e = NULL; + Operand o = {}; + if (arg->kind == AstNode_Ident) { + e = check_ident(c, &o, arg, NULL, NULL, true); + } else if (arg->kind == AstNode_SelectorExpr) { + e = check_selector(c, &o, arg, NULL); + } + if (e == NULL) { + error_node(ce->args[0], "`#location` expected a valid entity name"); + } + } + + + operand->type = t_source_code_location; + operand->mode = Addressing_Value; + } break; + case BuiltinProc_len: case BuiltinProc_cap: { // proc len(Type) -> int @@ -4822,11 +4868,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) { } GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.default_value.kind != ExactValue_Invalid) { - param_count_excluding_defaults--; - continue; - } - if (e->Variable.default_is_nil) { + if (e->Variable.default_value.kind != ExactValue_Invalid || + e->Variable.default_is_nil || + e->Variable.default_is_location) { param_count_excluding_defaults--; continue; } @@ -5214,7 +5258,19 @@ Entity *find_using_index_expr(Type *t) { ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { GB_ASSERT(call->kind == AstNode_CallExpr); ast_node(ce, CallExpr, call); - check_expr_or_type(c, operand, ce->proc); + if (ce->proc != NULL && + ce->proc->kind == AstNode_BasicDirective) { + ast_node(bd, BasicDirective, ce->proc); + String name = bd->name; + GB_ASSERT(name == "location"); + operand->mode = Addressing_Builtin; + operand->builtin_id = BuiltinProc_DIRECTIVE; + operand->expr = ce->proc; + operand->type = t_invalid; + add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value); + } else { + check_expr_or_type(c, operand, ce->proc); + } if (ce->args.count > 0) { bool fail = false; @@ -5508,9 +5564,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t o->type = t_untyped_string; o->value = exact_value_string(c->context.proc_name); } - + } else if (bd->name == "caller_location") { + init_preload(c); + error_node(node, "#caller_location may only be used as a default argument parameter"); + o->type = t_source_code_location; + o->mode = Addressing_Value; } else { - GB_PANIC("Unknown basic basic directive"); + GB_PANIC("Unknown basic directive"); } o->mode = Addressing_Constant; case_end; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 318239b25..6c74e4017 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1161,7 +1161,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } - TokenKind op = {}; + TokenKind op = Token_Invalid; Operand a = lhs; Operand b = rhs; diff --git a/src/checker.cpp b/src/checker.cpp index c76c908d9..7ba6a091a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -65,9 +65,11 @@ enum BuiltinProcId { BuiltinProc_transmute, - BuiltinProc_Count, + BuiltinProc_DIRECTIVE, + + BuiltinProc_COUNT, }; -gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { +gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT(""), 0, false, Expr_Stmt}, {STR_LIT("len"), 1, false, Expr_Expr}, @@ -110,6 +112,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT("clamp"), 3, false, Expr_Expr}, {STR_LIT("transmute"), 2, false, Expr_Expr}, + + {STR_LIT(""), 0, true, Expr_Expr}, // DIRECTIVE }; @@ -660,9 +664,12 @@ void init_universal_scope(void) { // Builtin Procedures for (isize i = 0; i < gb_count_of(builtin_procs); i++) { BuiltinProcId id = cast(BuiltinProcId)i; - Entity *entity = alloc_entity(a, Entity_Builtin, NULL, make_token_ident(builtin_procs[i].name), t_invalid); - entity->Builtin.id = id; - add_global_entity(entity); + String name = builtin_procs[i].name; + if (name != "") { + Entity *entity = alloc_entity(a, Entity_Builtin, NULL, make_token_ident(name), t_invalid); + entity->Builtin.id = id; + add_global_entity(entity); + } } @@ -1284,6 +1291,12 @@ void init_preload(Checker *c) { t_context_ptr = make_type_pointer(c->allocator, t_context); } + if (t_source_code_location == NULL) { + Entity *e = find_core_entity(c, str_lit("SourceCodeLocation")); + t_source_code_location = e->type; + t_source_code_location_ptr = make_type_pointer(c->allocator, t_allocator); + } + if (t_map_key == NULL) { Entity *e = find_core_entity(c, str_lit("__MapKey")); t_map_key = e->type; @@ -1755,7 +1768,7 @@ void check_collect_entities(Checker *c, Array nodes, bool is_file_sco void check_all_global_entities(Checker *c) { - Scope *prev_file = {}; + Scope *prev_file = NULL; for_array(i, c->info.entities.entries) { auto *entry = &c->info.entities.entries[i]; diff --git a/src/entity.cpp b/src/entity.cpp index d6703f5b7..1327ae285 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -86,6 +86,7 @@ struct Entity { i32 field_src_index; ExactValue default_value; bool default_is_nil; + bool default_is_location; bool is_immutable; bool is_thread_local; bool is_foreign; diff --git a/src/integer128.cpp b/src/integer128.cpp index 3ebd811c6..58a21d6d7 100644 --- a/src/integer128.cpp +++ b/src/integer128.cpp @@ -152,7 +152,12 @@ u64 bit128__digit_value(Rune r) { return 16; // NOTE(bill): Larger than highest possible } -u128 u128_lo_hi(u64 lo, u64 hi) { return u128{lo, hi}; } +u128 u128_lo_hi(u64 lo, u64 hi) { + u128 r = {}; + r.lo = lo; + r.hi = hi; + return r; +} u128 u128_from_u32(u32 u) { return u128_lo_hi(cast(u64)u, 0); } u128 u128_from_u64(u64 u) { return u128_lo_hi(cast(u64)u, 0); } u128 u128_from_i64(i64 u) { return u128_lo_hi(cast(u64)u, u < 0 ? -1 : 0); } diff --git a/src/ir.cpp b/src/ir.cpp index c585c99df..03c0dc8c7 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3522,7 +3522,8 @@ irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) { } GB_PANIC("Unreachable"); - return irBranchBlocks{}; + irBranchBlocks empty = {}; + return empty; } @@ -3628,10 +3629,46 @@ bool is_double_pointer(Type *t) { return is_type_pointer(td); } -irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, Entity *e) { +irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos) { + gbAllocator a = proc->module->allocator; + irValue **args = gb_alloc_array(a, irValue *, 4); + args[0] = ir_const_string(a, pos.file); + args[1] = ir_const_string(a, procedure); + args[2] = ir_const_i64(a, pos.line); + args[3] = ir_const_i64(a, pos.column); + return ir_emit_global_call(proc, "make_source_code_location", args, 4); +} + +irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, BuiltinProcId id) { ast_node(ce, CallExpr, expr); - switch (e->Builtin.id) { + switch (id) { + case BuiltinProc_DIRECTIVE: { + ast_node(bd, BasicDirective, ce->proc); + String name = bd->name; + GB_ASSERT(name == "location"); + String procedure = proc->entity->token.string; + TokenPos pos = ast_node_token(ce->proc).pos; + if (ce->args.count > 0) { + AstNode *ident = ce->args[0];; + + while (ident->kind == AstNode_SelectorExpr) { + ident = ident->SelectorExpr.selector; + } + Entity *e = entity_of_ident(proc->module->info, ident); + GB_ASSERT(e != NULL); + + if (e->parent_proc_decl != NULL) { + procedure = e->parent_proc_decl->entities[0]->token.string; + } else { + procedure = str_lit(""); + } + pos = e->token.pos; + + } + return ir_emit_source_code_location(proc, procedure, pos); + } break; + case BuiltinProc_type_info: { Type *t = default_type(type_of_expr(proc->module->info, ce->args[0])); return ir_type_info(proc, t); @@ -4573,7 +4610,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { case_ast_node(ce, CallExpr, expr); - if (type_and_value_of_expr(proc->module->info, ce->proc).mode == Addressing_Type) { + TypeAndValue proc_tv = type_and_value_of_expr(proc->module->info, ce->proc); + AddressingMode proc_mode = proc_tv.mode; + if (proc_mode == Addressing_Type) { GB_ASSERT(ce->args.count == 1); irValue *x = ir_build_expr(proc, ce->args[0]); irValue *y = ir_emit_conv(proc, x, tv.type); @@ -4581,11 +4620,10 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { } AstNode *p = unparen_expr(ce->proc); - if (p->kind == AstNode_Ident) { + if (proc_mode == Addressing_Builtin) { Entity *e = entity_of_ident(proc->module->info, p); - if (e != NULL && e->kind == Entity_Builtin) { - return ir_build_builtin_proc(proc, expr, tv, e); - } + BuiltinProcId id = cast(BuiltinProcId)(e != NULL ? e->Builtin.id : BuiltinProc_DIRECTIVE); + return ir_build_builtin_proc(proc, expr, tv, id); } // NOTE(bill): Regular call @@ -4664,6 +4702,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { TypeTuple *pt = &type->params->Tuple; if (arg_count < type->param_count) { + String procedure = proc->entity->token.string; + TokenPos pos = ast_node_token(ce->proc).pos; + isize end = type->param_count; if (variadic) { end--; @@ -4673,6 +4714,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) { GB_ASSERT(e->kind == Entity_Variable); if (e->Variable.default_value.kind != ExactValue_Invalid) { args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value); + } else if (e->Variable.default_is_location) { + args[arg_index++] = ir_emit_source_code_location(proc, procedure, pos); } else { args[arg_index++] = ir_value_nil(proc->module->allocator, e->type); } @@ -6459,7 +6502,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *cond = v_false; if (is_ast_node_a_range(expr)) { ast_node(ie, BinaryExpr, expr); - TokenKind op = {}; + TokenKind op = Token_Invalid; switch (ie->op.kind) { case Token_Ellipsis: op = Token_LtEq; break; case Token_HalfClosed: op = Token_Lt; break; diff --git a/src/main.cpp b/src/main.cpp index e4c6e6606..9ae8dc88e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,4 @@ -#define USE_CUSTOM_BACKEND false +#define USE_CUSTOM_BACKEND 0 #include "common.cpp" #include "timings.cpp" @@ -205,7 +205,7 @@ int main(int argc, char **argv) { #endif -#if USE_CUSTOM_BACKEND +#if defined(USE_CUSTOM_BACKEND) && USE_CUSTOM_BACKEND if (global_error_collector.count != 0) { return 1; } diff --git a/src/parser.cpp b/src/parser.cpp index e48c8ce78..0849cf663 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -114,10 +114,9 @@ enum StmtAllowFlag { -Array make_ast_node_array(AstFile *f) { +Array make_ast_node_array(AstFile *f, isize init_capacity = 8) { Array a; - // array_init(&a, gb_arena_allocator(&f->arena)); - array_init(&a, heap_allocator()); + array_init(&a, heap_allocator(), init_capacity); return a; } @@ -2029,8 +2028,9 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven Array parse_lhs_expr_list(AstFile *f); Array parse_rhs_expr_list(AstFile *f); -AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); -AstNode * parse_type (AstFile *f); +AstNode * parse_simple_stmt (AstFile *f, StmtAllowFlag flags); +AstNode * parse_type (AstFile *f); +AstNode * parse_call_expr (AstFile *f, AstNode *operand); AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { if (statement == NULL) { @@ -2117,7 +2117,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) { } else if (name.string == "file") { return ast_basic_directive(f, token, name.string); } else if (name.string == "line") { return ast_basic_directive(f, token, name.string); } else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string); - // } else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false)); + } else if (name.string == "caller_location") { return ast_basic_directive(f, token, name.string); + } else if (name.string == "location") { + AstNode *tag = ast_basic_directive(f, token, name.string); + return parse_call_expr(f, tag); } else { operand = ast_tag_expr(f, token, name, parse_expr(f, false)); } @@ -2613,7 +2616,7 @@ AstNode *parse_gen_decl(AstFile *f, Token token, ParseSpecFunc *func) { expect_semicolon(f, NULL); } } else { - array_init(&specs, heap_allocator(), 1); + specs = make_ast_node_array(f, 1); AstNode *spec = func(f, token); array_add(&specs, spec); } @@ -2942,9 +2945,8 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) { AstNode *expr = parse_expr(f, false); f->allow_range = prev_allow_range; - Array rhs = {}; - array_init_count(&rhs, heap_allocator(), 1); - rhs[0] = expr; + Array rhs = make_ast_node_array(f, 1); + array_add(&rhs, expr); return ast_assign_stmt(f, token, lhs, rhs); } @@ -3031,8 +3033,8 @@ AstNode *parse_results(AstFile *f) { } AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) { - AstNode *params = {}; - AstNode *results = {}; + AstNode *params = NULL; + AstNode *results = NULL; expect_token(f, Token_OpenParen); params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen); @@ -3166,8 +3168,7 @@ struct AstNodeAndFlags { }; Array convert_to_ident_list(AstFile *f, Array list, bool ignore_flags) { - Array idents = {}; - array_init(&idents, heap_allocator(), list.count); + Array idents = make_ast_node_array(f, list.count); // Convert to ident list for_array(i, list) { AstNode *ident = list[i].node; @@ -3211,7 +3212,10 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok Token start_token = f->curr_token; Array params = make_ast_node_array(f); - Array list = {}; array_init(&list, heap_allocator()); // LEAK(bill): + + Array list = {}; array_init(&list, heap_allocator()); + defer (array_free(&list)); + isize total_name_count = 0; bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis; bool is_procedure = allowed_flags == FieldFlag_Signature; diff --git a/src/string.cpp b/src/string.cpp index 6b6302ede..f2ba05689 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -25,8 +25,11 @@ struct String { // NOTE(bill): used for printf style arguments #define LIT(x) ((int)(x).len), (x).text #define STR_LIT(c_str) {cast(u8 *)c_str, gb_size_of(c_str)-1} -#define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1} - +#if defined(GB_COMPILER_MSVC) && _MSC_VER < 1700 + #define str_lit(c_str) make_string(cast(u8 *)c_str, gb_size_of(c_str)-1) +#else + #define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1} +#endif // NOTE(bill): String16 is only used for Windows due to its file directories struct String16 { diff --git a/src/types.cpp b/src/types.cpp index ca74a1b77..ce0a57dc9 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -321,35 +321,35 @@ gb_global Type *t_string_slice = NULL; // Type generated for the "preload" file -gb_global Type *t_type_info = NULL; -gb_global Type *t_type_info_record = NULL; -gb_global Type *t_type_info_enum_value = NULL; -gb_global Type *t_type_info_ptr = NULL; -gb_global Type *t_type_info_record_ptr = NULL; -gb_global Type *t_type_info_enum_value_ptr = NULL; +gb_global Type *t_type_info = NULL; +gb_global Type *t_type_info_record = NULL; +gb_global Type *t_type_info_enum_value = NULL; +gb_global Type *t_type_info_ptr = NULL; +gb_global Type *t_type_info_record_ptr = NULL; +gb_global Type *t_type_info_enum_value_ptr = NULL; -gb_global Type *t_type_info_named = NULL; -gb_global Type *t_type_info_integer = NULL; -gb_global Type *t_type_info_rune = NULL; -gb_global Type *t_type_info_float = NULL; -gb_global Type *t_type_info_complex = NULL; -gb_global Type *t_type_info_any = NULL; -gb_global Type *t_type_info_string = NULL; -gb_global Type *t_type_info_boolean = NULL; -gb_global Type *t_type_info_pointer = NULL; -gb_global Type *t_type_info_atomic = NULL; -gb_global Type *t_type_info_procedure = NULL; -gb_global Type *t_type_info_array = NULL; -gb_global Type *t_type_info_dynamic_array = NULL; -gb_global Type *t_type_info_slice = NULL; -gb_global Type *t_type_info_vector = NULL; -gb_global Type *t_type_info_tuple = NULL; -gb_global Type *t_type_info_struct = NULL; -gb_global Type *t_type_info_raw_union = NULL; -gb_global Type *t_type_info_union = NULL; -gb_global Type *t_type_info_enum = NULL; -gb_global Type *t_type_info_map = NULL; -gb_global Type *t_type_info_bit_field = NULL; +gb_global Type *t_type_info_named = NULL; +gb_global Type *t_type_info_integer = NULL; +gb_global Type *t_type_info_rune = NULL; +gb_global Type *t_type_info_float = NULL; +gb_global Type *t_type_info_complex = NULL; +gb_global Type *t_type_info_any = NULL; +gb_global Type *t_type_info_string = NULL; +gb_global Type *t_type_info_boolean = NULL; +gb_global Type *t_type_info_pointer = NULL; +gb_global Type *t_type_info_atomic = NULL; +gb_global Type *t_type_info_procedure = NULL; +gb_global Type *t_type_info_array = NULL; +gb_global Type *t_type_info_dynamic_array = NULL; +gb_global Type *t_type_info_slice = NULL; +gb_global Type *t_type_info_vector = NULL; +gb_global Type *t_type_info_tuple = NULL; +gb_global Type *t_type_info_struct = NULL; +gb_global Type *t_type_info_raw_union = NULL; +gb_global Type *t_type_info_union = NULL; +gb_global Type *t_type_info_enum = NULL; +gb_global Type *t_type_info_map = NULL; +gb_global Type *t_type_info_bit_field = NULL; gb_global Type *t_type_info_named_ptr = NULL; gb_global Type *t_type_info_integer_ptr = NULL; @@ -375,13 +375,16 @@ gb_global Type *t_type_info_enum_ptr = NULL; gb_global Type *t_type_info_map_ptr = NULL; gb_global Type *t_type_info_bit_field_ptr = NULL; -gb_global Type *t_allocator = NULL; -gb_global Type *t_allocator_ptr = NULL; -gb_global Type *t_context = NULL; -gb_global Type *t_context_ptr = NULL; +gb_global Type *t_allocator = NULL; +gb_global Type *t_allocator_ptr = NULL; +gb_global Type *t_context = NULL; +gb_global Type *t_context_ptr = NULL; -gb_global Type *t_map_key = NULL; -gb_global Type *t_map_header = NULL; +gb_global Type *t_source_code_location = NULL; +gb_global Type *t_source_code_location_ptr = NULL; + +gb_global Type *t_map_key = NULL; +gb_global Type *t_map_header = NULL;