aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-06-18 14:36:06 +0100
committerGinger Bill <bill@gingerbill.org>2017-06-18 14:36:06 +0100
commit4236519b84e2bea73b1b7756a20a2df24d3fb070 (patch)
tree39e90d5650a9e84270d41b899eadc3aaed02a87c /src
parente4944b4f2ebf617d629184257ef81e9c3f212e6c (diff)
`#location(..)` and `#call_location`
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp112
-rw-r--r--src/check_stmt.cpp2
-rw-r--r--src/checker.cpp25
-rw-r--r--src/entity.cpp1
-rw-r--r--src/integer128.cpp7
-rw-r--r--src/ir.cpp61
-rw-r--r--src/main.cpp4
-rw-r--r--src/parser.cpp34
-rw-r--r--src/string.cpp7
-rw-r--r--src/types.cpp73
10 files changed, 229 insertions, 97 deletions
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<AstNode *> 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<AstNode *> make_ast_node_array(AstFile *f) {
+Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
Array<AstNode *> 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<AstNode *> parse_lhs_expr_list(AstFile *f);
Array<AstNode *> 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<AstNode *> rhs = {};
- array_init_count(&rhs, heap_allocator(), 1);
- rhs[0] = expr;
+ Array<AstNode *> 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<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list, bool ignore_flags) {
- Array<AstNode *> idents = {};
- array_init(&idents, heap_allocator(), list.count);
+ Array<AstNode *> 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<AstNode *> params = make_ast_node_array(f);
- Array<AstNodeAndFlags> list = {}; array_init(&list, heap_allocator()); // LEAK(bill):
+
+ Array<AstNodeAndFlags> 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_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 = 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_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;