mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-22 15:37:51 +00:00
enum_to_string
This commit is contained in:
+25
-7
@@ -159,6 +159,8 @@ enum BuiltinProcId {
|
||||
BuiltinProc_max,
|
||||
BuiltinProc_abs,
|
||||
|
||||
BuiltinProc_enum_to_string,
|
||||
|
||||
|
||||
BuiltinProc_Count,
|
||||
};
|
||||
@@ -200,6 +202,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
||||
{STR_LIT("max"), 2, false, Expr_Expr},
|
||||
{STR_LIT("abs"), 1, false, Expr_Expr},
|
||||
|
||||
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
||||
|
||||
};
|
||||
|
||||
struct CheckerContext {
|
||||
@@ -358,6 +362,9 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
|
||||
// Do not return imported entities even #load ones
|
||||
continue;
|
||||
}
|
||||
if (!is_entity_exported(e)) {
|
||||
continue;
|
||||
}
|
||||
if (entity_) *entity_ = e;
|
||||
if (scope_) *scope_ = shared;
|
||||
return;
|
||||
@@ -409,7 +416,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
||||
|
||||
void check_scope_usage(Checker *c, Scope *scope) {
|
||||
// TODO(bill): Use this?
|
||||
#if 0
|
||||
#if 1
|
||||
gb_for_array(i, scope->elements.entries) {
|
||||
auto *entry = scope->elements.entries + i;
|
||||
Entity *e = entry->value;
|
||||
@@ -445,7 +452,7 @@ void add_global_entity(Entity *entity) {
|
||||
return; // NOTE(bill): `untyped thing`
|
||||
}
|
||||
if (scope_insert_entity(universal_scope, entity)) {
|
||||
GB_PANIC("Compiler error: double declaration");
|
||||
compiler_error("double declaration");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,10 +499,6 @@ void init_universal_scope(void) {
|
||||
entity->Builtin.id = id;
|
||||
add_global_entity(entity);
|
||||
}
|
||||
|
||||
// Custom Runtime Types
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1112,12 +1115,27 @@ void check_parsed_files(Checker *c) {
|
||||
ExpressionInfo *info = &entry->value;
|
||||
if (info != NULL && expr != NULL) {
|
||||
if (is_type_typed(info->type)) {
|
||||
GB_PANIC("%s (type %s) is typed!", expr_to_string(expr), info->type);
|
||||
compiler_error("%s (type %s) is typed!", expr_to_string(expr), info->type);
|
||||
}
|
||||
add_type_and_value(&c->info, expr, info->mode, info->type, info->value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gb_for_array(i, c->parser->files) {
|
||||
AstFile *f = &c->parser->files[i];
|
||||
Scope *scope = f->scope;
|
||||
gb_for_array(j, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[j].value;
|
||||
switch (e->kind) {
|
||||
case Entity_ImportName: {
|
||||
if (!e->ImportName.used) {
|
||||
warning(e->token, "Unused import name: %.*s", LIT(e->ImportName.name));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+64
-10
@@ -385,25 +385,34 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
|
||||
|
||||
// TODO(bill): Cleanup struct field reordering
|
||||
// TODO(bill): Inline sorting procedure?
|
||||
gb_global BaseTypeSizes __checker_sizes = {};
|
||||
gb_global gbAllocator __checker_allocator = {};
|
||||
|
||||
GB_COMPARE_PROC(cmp_struct_entity_size) {
|
||||
// Rule: Biggest to smallest
|
||||
// if same size, order by order in source
|
||||
// Rule:
|
||||
// Biggest to smallest alignment
|
||||
// if same alignment: biggest to smallest size
|
||||
// if same size: order by source order
|
||||
Entity *x = *(Entity **)a;
|
||||
Entity *y = *(Entity **)b;
|
||||
GB_ASSERT(x != NULL);
|
||||
GB_ASSERT(y != NULL);
|
||||
GB_ASSERT(x->kind == Entity_Variable);
|
||||
GB_ASSERT(y->kind == Entity_Variable);
|
||||
i64 xa = type_align_of(__checker_sizes, __checker_allocator, x->type);
|
||||
i64 ya = type_align_of(__checker_sizes, __checker_allocator, y->type);
|
||||
i64 xs = type_size_of(__checker_sizes, __checker_allocator, x->type);
|
||||
i64 ys = type_size_of(__checker_sizes, __checker_allocator, y->type);
|
||||
if (xs == ys) {
|
||||
i32 diff = x->Variable.field_index - y->Variable.field_index;
|
||||
return diff < 0 ? -1 : diff > 0;
|
||||
|
||||
if (xa == ya) {
|
||||
if (xs == ys) {
|
||||
i32 diff = x->Variable.field_index - y->Variable.field_index;
|
||||
return diff < 0 ? -1 : diff > 0;
|
||||
}
|
||||
return xs > ys ? -1 : xs < ys;
|
||||
}
|
||||
return xs > ys ? -1 : xs < ys;
|
||||
return xa > ya ? -1 : xa < ya;
|
||||
}
|
||||
|
||||
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||
@@ -746,6 +755,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
||||
error(n->Ident,
|
||||
"Undeclared name: %.*s", LIT(n->Ident.string));
|
||||
}
|
||||
o->type = t_invalid;
|
||||
o->mode = Addressing_Invalid;
|
||||
if (named_type != NULL) {
|
||||
set_base_type(named_type, t_invalid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
add_entity_use(&c->info, n, e);
|
||||
@@ -761,7 +775,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
||||
check_entity_decl(c, e, NULL, named_type, cycle_checker);
|
||||
|
||||
if (e->type == NULL) {
|
||||
GB_PANIC("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
|
||||
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -820,7 +834,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
||||
return;
|
||||
|
||||
default:
|
||||
GB_PANIC("Compiler error: Unknown EntityKind");
|
||||
compiler_error("Compiler error: Unknown EntityKind");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2785,6 +2799,44 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
||||
|
||||
operand->type = type;
|
||||
} break;
|
||||
|
||||
case BuiltinProc_enum_to_string: {
|
||||
Type *type = get_base_type(operand->type);
|
||||
if (!is_type_enum(type)) {
|
||||
gbString type_str = type_to_string(operand->type);
|
||||
defer (gb_string_free(type_str));
|
||||
error(ast_node_token(call),
|
||||
"Expected an enum to `enum_to_string`, got `%s`",
|
||||
type_str);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (operand->mode == Addressing_Constant) {
|
||||
ExactValue value = make_exact_value_string(make_string(""));
|
||||
if (operand->value.kind == ExactValue_Integer) {
|
||||
i64 index = operand->value.value_integer;
|
||||
for (isize i = 0; i < type->Record.other_field_count; i++) {
|
||||
Entity *f = type->Record.other_fields[i];
|
||||
if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
|
||||
i64 fv = f->Constant.value.value_integer;
|
||||
if (index == fv) {
|
||||
value = make_exact_value_string(f->token.string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operand->value = value;
|
||||
operand->type = t_string;
|
||||
return true;
|
||||
}
|
||||
|
||||
add_type_info_type(c, operand->type);
|
||||
|
||||
operand->mode = Addressing_Value;
|
||||
operand->type = t_string;
|
||||
} break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2832,8 +2884,10 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
||||
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
|
||||
gb_for_array(arg_index, ce->args) {
|
||||
check_multi_expr(c, operand, ce->args[arg_index]);
|
||||
if (operand->mode == Addressing_Invalid)
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
param_index++;
|
||||
continue;
|
||||
}
|
||||
if (operand->type->kind != Type_Tuple) {
|
||||
check_not_tuple(c, operand);
|
||||
isize index = param_index;
|
||||
@@ -3083,7 +3137,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
case Type_Record: {
|
||||
if (!is_type_struct(t))
|
||||
break;
|
||||
if (gb_array_count(cl->elems) == 0) {
|
||||
if (cl->elems == NULL || gb_array_count(cl->elems) == 0) {
|
||||
break; // NOTE(bill): No need to init
|
||||
}
|
||||
{ // Checker values
|
||||
|
||||
+32
-12
@@ -8,9 +8,12 @@ enum StmtFlag : u32 {
|
||||
|
||||
|
||||
void check_stmt(Checker *c, AstNode *node, u32 flags);
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later);
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
|
||||
|
||||
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
// TODO(bill): Allow declaration (expect variable) in any order
|
||||
// even within a procedure
|
||||
|
||||
b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
|
||||
u32 f = flags & (~Stmt_FallthroughAllowed);
|
||||
|
||||
@@ -321,7 +324,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
}
|
||||
if (!is_type_constant_type(operand->type)) {
|
||||
// NOTE(bill): no need to free string as it's panicking
|
||||
GB_PANIC("Compiler error: Type `%s` not constant!!!", type_to_string(operand->type));
|
||||
compiler_error("Type `%s` not constant!!!", type_to_string(operand->type));
|
||||
}
|
||||
|
||||
if (e->type == NULL) // NOTE(bill): type inference
|
||||
@@ -482,7 +485,7 @@ b32 are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
|
||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
|
||||
@@ -494,6 +497,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
|
||||
|
||||
b32 is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
b32 is_link_name = (pd->tags & ProcTag_link_name) != 0;
|
||||
b32 is_inline = (pd->tags & ProcTag_inline) != 0;
|
||||
b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
|
||||
@@ -527,11 +531,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
d->scope = c->context.scope;
|
||||
|
||||
GB_ASSERT(pd->body->kind == AstNode_BlockStmt);
|
||||
if (check_body_later) {
|
||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body);
|
||||
} else {
|
||||
check_proc_body(c, e->token, d, proc_type, pd->body);
|
||||
}
|
||||
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body);
|
||||
}
|
||||
|
||||
if (is_foreign) {
|
||||
@@ -557,6 +557,23 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
|
||||
} else {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
} else if (is_link_name) {
|
||||
auto *fp = &c->info.foreign_procs;
|
||||
auto *proc_decl = &d->proc_decl->ProcDecl;
|
||||
String name = proc_decl->link_name;
|
||||
|
||||
HashKey key = hash_string(name);
|
||||
auto *found = map_get(fp, key);
|
||||
if (found) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
error(ast_node_token(d->proc_decl),
|
||||
"Non unique #link_name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
} else {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -610,7 +627,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
if (found) {
|
||||
d = *found;
|
||||
} else {
|
||||
GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
|
||||
e->type = t_invalid;
|
||||
return;
|
||||
// GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,7 +639,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
// defer (c->context.scope = prev);
|
||||
|
||||
if (e->kind == Entity_Procedure) {
|
||||
check_proc_decl(c, e, d, true);
|
||||
check_proc_decl(c, e, d);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -644,7 +663,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
check_proc_decl(c, e, d, true);
|
||||
check_proc_decl(c, e, d);
|
||||
} break;
|
||||
|
||||
|
||||
@@ -1261,6 +1280,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
// NOTE(bill): Dummy type
|
||||
Type *tag_ptr_type = make_type_pointer(c->allocator, tag_type);
|
||||
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tag_ptr_type);
|
||||
tag_var->Variable.used = true;
|
||||
add_entity(c, c->context.scope, ms->var, tag_var);
|
||||
add_entity_use(&c->info, ms->var, tag_var);
|
||||
}
|
||||
@@ -1481,7 +1501,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
DeclInfo *decl = make_declaration_info(c->allocator, e->scope);
|
||||
decl->proc_decl = node;
|
||||
check_proc_decl(c, e, decl, false);
|
||||
check_proc_decl(c, e, decl);
|
||||
case_end;
|
||||
|
||||
case_ast_node(td, TypeDecl, node);
|
||||
|
||||
+8
-10
@@ -7,12 +7,10 @@ enum BasicKind {
|
||||
Basic_i16,
|
||||
Basic_i32,
|
||||
Basic_i64,
|
||||
Basic_i128,
|
||||
Basic_u8,
|
||||
Basic_u16,
|
||||
Basic_u32,
|
||||
Basic_u64,
|
||||
Basic_u128,
|
||||
Basic_f32,
|
||||
Basic_f64,
|
||||
Basic_int,
|
||||
@@ -296,12 +294,10 @@ gb_global Type basic_types[] = {
|
||||
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||
{0, Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
|
||||
{0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||
{0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||
{0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||
{0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||
{0, Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
|
||||
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||
{0, Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
||||
@@ -328,12 +324,10 @@ gb_global Type *t_i8 = &basic_types[Basic_i8];
|
||||
gb_global Type *t_i16 = &basic_types[Basic_i16];
|
||||
gb_global Type *t_i32 = &basic_types[Basic_i32];
|
||||
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
||||
gb_global Type *t_i128 = &basic_types[Basic_i128];
|
||||
gb_global Type *t_u8 = &basic_types[Basic_u8];
|
||||
gb_global Type *t_u16 = &basic_types[Basic_u16];
|
||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||
gb_global Type *t_u128 = &basic_types[Basic_u128];
|
||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
gb_global Type *t_int = &basic_types[Basic_int];
|
||||
@@ -602,7 +596,12 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
break;
|
||||
|
||||
case TypeRecord_Enum:
|
||||
return are_types_identical(x->Record.enum_base, y->Record.enum_base);
|
||||
if (are_types_identical(x->Record.enum_base, y->Record.enum_base)) {
|
||||
if (x->Record.field_count == y->Record.field_count) {
|
||||
return x->Record.fields == y->Record.fields;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -679,12 +678,10 @@ gb_global i64 basic_type_sizes[] = {
|
||||
2, // Basic_i16
|
||||
4, // Basic_i32
|
||||
8, // Basic_i64
|
||||
16, // Basic_i128
|
||||
1, // Basic_u8
|
||||
2, // Basic_u16
|
||||
4, // Basic_u32
|
||||
8, // Basic_u64
|
||||
16, // Basic_u128
|
||||
4, // Basic_f32
|
||||
8, // Basic_f64
|
||||
};
|
||||
@@ -954,7 +951,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
} break;
|
||||
}
|
||||
|
||||
return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
|
||||
// return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
|
||||
return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.word_size);
|
||||
}
|
||||
|
||||
i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) {
|
||||
|
||||
+116
-21
@@ -67,16 +67,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) {
|
||||
}
|
||||
|
||||
void ssa_gen_tree(ssaGen *s) {
|
||||
if (v_zero == NULL) {
|
||||
v_zero = ssa_make_const_int (gb_heap_allocator(), 0);
|
||||
v_one = ssa_make_const_int (gb_heap_allocator(), 1);
|
||||
v_zero32 = ssa_make_const_i32 (gb_heap_allocator(), 0);
|
||||
v_one32 = ssa_make_const_i32 (gb_heap_allocator(), 1);
|
||||
v_two32 = ssa_make_const_i32 (gb_heap_allocator(), 2);
|
||||
v_false = ssa_make_const_bool(gb_heap_allocator(), false);
|
||||
v_true = ssa_make_const_bool(gb_heap_allocator(), true);
|
||||
}
|
||||
|
||||
struct ssaGlobalVariable {
|
||||
ssaValue *var, *init;
|
||||
DeclInfo *decl;
|
||||
@@ -85,9 +75,35 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaModule *m = &s->module;
|
||||
CheckerInfo *info = m->info;
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
if (v_zero == NULL) {
|
||||
v_zero = ssa_make_const_int (m->allocator, 0);
|
||||
v_one = ssa_make_const_int (m->allocator, 1);
|
||||
v_zero32 = ssa_make_const_i32 (m->allocator, 0);
|
||||
v_one32 = ssa_make_const_i32 (m->allocator, 1);
|
||||
v_two32 = ssa_make_const_i32 (m->allocator, 2);
|
||||
v_false = ssa_make_const_bool(m->allocator, false);
|
||||
v_true = ssa_make_const_bool(m->allocator, true);
|
||||
}
|
||||
|
||||
isize global_variable_max_count = 0;
|
||||
|
||||
gb_for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
if (e->kind == Entity_Variable) {
|
||||
global_variable_max_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
gbArray(ssaGlobalVariable) global_variables;
|
||||
gb_array_init(global_variables, gb_heap_allocator());
|
||||
defer (gb_array_free(global_variables));
|
||||
gb_array_init_reserve(global_variables, m->tmp_allocator, global_variable_max_count);
|
||||
|
||||
|
||||
|
||||
gb_for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
@@ -123,7 +139,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ExactValue v = tav->value;
|
||||
if (v.kind == ExactValue_String) {
|
||||
// NOTE(bill): The printer will fix the value correctly
|
||||
g->Global.value = ssa_add_global_string_array(m, v.value_string);
|
||||
// g->Global.value = ssa_add_global_string_array(m, v.value_string);
|
||||
} else {
|
||||
g->Global.value = ssa_make_value_constant(a, tav->type, v);
|
||||
}
|
||||
@@ -147,6 +163,8 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
}
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_name;
|
||||
} else if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
}
|
||||
|
||||
ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
|
||||
@@ -171,7 +189,18 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaDebugInfo *compile_unit = m->debug_info.entries[0].value;
|
||||
GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit);
|
||||
ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs);
|
||||
gb_array_init(all_procs->AllProcs.procs, gb_heap_allocator());
|
||||
|
||||
isize all_proc_max_count = 0;
|
||||
gb_for_array(i, m->debug_info.entries) {
|
||||
auto *entry = &m->debug_info.entries[i];
|
||||
ssaDebugInfo *di = entry->value;
|
||||
di->id = i;
|
||||
if (di->kind == ssaDebugInfo_Proc) {
|
||||
all_proc_max_count++;
|
||||
}
|
||||
}
|
||||
|
||||
gb_array_init_reserve(all_procs->AllProcs.procs, m->allocator, all_proc_max_count);
|
||||
map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped
|
||||
compile_unit->CompileUnit.all_procs = all_procs;
|
||||
|
||||
@@ -250,10 +279,12 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
|
||||
// Useful types
|
||||
Type *t_int_ptr = make_type_pointer(a, t_int);
|
||||
Type *t_i64_ptr = make_type_pointer(a, t_i64);
|
||||
Type *t_bool_ptr = make_type_pointer(a, t_bool);
|
||||
Type *t_string_ptr = make_type_pointer(a, t_string);
|
||||
Type *t_type_info_ptr_ptr = make_type_pointer(a, t_type_info_ptr);
|
||||
|
||||
Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64));
|
||||
Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string));
|
||||
|
||||
auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
|
||||
return ssa_emit_struct_gep(proc, type_info_data,
|
||||
@@ -302,12 +333,12 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
case Basic_i16:
|
||||
case Basic_i32:
|
||||
case Basic_i64:
|
||||
case Basic_i128:
|
||||
// case Basic_i128:
|
||||
case Basic_u8:
|
||||
case Basic_u16:
|
||||
case Basic_u32:
|
||||
case Basic_u64:
|
||||
case Basic_u128:
|
||||
// case Basic_u128:
|
||||
case Basic_int:
|
||||
case Basic_uint: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_integer);
|
||||
@@ -467,8 +498,72 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
if (enum_base == NULL) {
|
||||
enum_base = t_int;
|
||||
}
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, enum_base);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
|
||||
ssaValue *base = ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr);
|
||||
ssa_emit_store(proc, base, get_type_info_ptr(proc, type_info_data, enum_base));
|
||||
|
||||
if (t->Record.other_field_count > 0) {
|
||||
Entity **fields = t->Record.other_fields;
|
||||
isize count = t->Record.other_field_count;
|
||||
ssaValue *value_array = NULL;
|
||||
ssaValue *name_array = NULL;
|
||||
|
||||
|
||||
{
|
||||
Token token = {Token_Identifier};
|
||||
i32 id = cast(i32)entry_index;
|
||||
char name_base[] = "__$enum_values";
|
||||
isize name_len = gb_size_of(name_base) + 10;
|
||||
token.string.text = gb_alloc_array(a, u8, name_len);
|
||||
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
|
||||
"%s-%d", name_base, id)-1;
|
||||
Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_i64, count));
|
||||
value_array = ssa_make_value_global(a, e, NULL);
|
||||
value_array->Global.is_private = true;
|
||||
ssa_module_add_value(m, e, value_array);
|
||||
map_set(&m->members, hash_string(token.string), value_array);
|
||||
}
|
||||
{
|
||||
Token token = {Token_Identifier};
|
||||
i32 id = cast(i32)entry_index;
|
||||
char name_base[] = "__$enum_names";
|
||||
isize name_len = gb_size_of(name_base) + 10;
|
||||
token.string.text = gb_alloc_array(a, u8, name_len);
|
||||
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
|
||||
"%s-%d", name_base, id)-1;
|
||||
Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_string, count));
|
||||
name_array = ssa_make_value_global(a, e, NULL);
|
||||
name_array->Global.is_private = true;
|
||||
ssa_module_add_value(m, e, name_array);
|
||||
map_set(&m->members, hash_string(token.string), name_array);
|
||||
}
|
||||
|
||||
for (isize i = 0; i < count; i++) {
|
||||
ssaValue *value_gep = ssa_emit_struct_gep(proc, value_array, i, t_i64_ptr);
|
||||
ssaValue *name_gep = ssa_emit_struct_gep(proc, name_array, i, t_string_ptr);
|
||||
|
||||
ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
|
||||
ssa_emit_store(proc, name_gep, ssa_emit_global_string(proc, fields[i]->token.string));
|
||||
}
|
||||
|
||||
ssaValue *v_count = ssa_make_const_int(a, count);
|
||||
|
||||
|
||||
ssaValue *values = ssa_emit_struct_gep(proc, tag, v_one32, t_i64_slice_ptr);
|
||||
ssaValue *names = ssa_emit_struct_gep(proc, tag, v_two32, t_string_slice_ptr);
|
||||
ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr));
|
||||
ssaValue *name_slice = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr));
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_zero32, t_i64_ptr), ssa_array_elem(proc, value_array));
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_one32, t_int_ptr), v_count);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, value_slice, v_two32, t_int_ptr), v_count);
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_zero32, t_string_ptr), ssa_array_elem(proc, name_array));
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_one32, t_int_ptr), v_count);
|
||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, name_slice, v_two32, t_int_ptr), v_count);
|
||||
|
||||
ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice));
|
||||
ssa_emit_store(proc, names, ssa_emit_load(proc, name_slice));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
@@ -515,10 +610,10 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *variadic = ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr);
|
||||
|
||||
if (t->Proc.params) {
|
||||
ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
|
||||
ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
|
||||
}
|
||||
if (t->Proc.results) {
|
||||
ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
|
||||
ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
|
||||
}
|
||||
ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic));
|
||||
|
||||
|
||||
+18
-28
@@ -142,12 +142,12 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
||||
case Basic_i16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_i32: ssa_fprintf(f, "i32"); break;
|
||||
case Basic_i64: ssa_fprintf(f, "i64"); break;
|
||||
case Basic_i128: ssa_fprintf(f, "i128"); break;
|
||||
// case Basic_i128: ssa_fprintf(f, "i128"); break;
|
||||
case Basic_u8: ssa_fprintf(f, "i8"); break;
|
||||
case Basic_u16: ssa_fprintf(f, "i16"); break;
|
||||
case Basic_u32: ssa_fprintf(f, "i32"); break;
|
||||
case Basic_u64: ssa_fprintf(f, "i64"); break;
|
||||
case Basic_u128: ssa_fprintf(f, "i128"); break;
|
||||
// case Basic_u128: ssa_fprintf(f, "i128"); break;
|
||||
case Basic_f32: ssa_fprintf(f, "float"); break;
|
||||
case Basic_f64: ssa_fprintf(f, "double"); break;
|
||||
case Basic_rawptr: ssa_fprintf(f, "%%..rawptr"); break;
|
||||
@@ -346,27 +346,27 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
|
||||
if (scope != NULL) {
|
||||
in_global_scope = scope->is_global || scope->is_init;
|
||||
}
|
||||
if (type_hint != NULL && is_type_string(type_hint)) {
|
||||
ssa_fprintf(f, "{i8* getelementptr inbounds (");
|
||||
ssa_print_type(f, m, value->Global.entity->type);
|
||||
ssa_fprintf(f, ", ");
|
||||
ssa_print_type(f, m, value->Global.entity->type);
|
||||
ssa_fprintf(f, "* ");
|
||||
// if (type_hint != NULL && is_type_string(type_hint)) {
|
||||
// ssa_fprintf(f, "{i8* getelementptr inbounds (");
|
||||
// ssa_print_type(f, m, value->Global.entity->type);
|
||||
// ssa_fprintf(f, ", ");
|
||||
// ssa_print_type(f, m, value->Global.entity->type);
|
||||
// ssa_fprintf(f, "* ");
|
||||
// ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
|
||||
// ssa_fprintf(f, ", ");
|
||||
// ssa_print_type(f, m, t_int);
|
||||
// ssa_fprintf(f, " 0, i32 0), ");
|
||||
// ssa_print_type(f, m, t_int);
|
||||
// ssa_fprintf(f, " %lld}", 0);
|
||||
// } else {
|
||||
ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
|
||||
ssa_fprintf(f, ", ");
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " 0, i32 0), ");
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, " %lld}", 0);
|
||||
} else {
|
||||
ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope);
|
||||
}
|
||||
// }
|
||||
} break;
|
||||
case ssaValue_Param:
|
||||
ssa_print_encoded_local(f, value->Param.entity->token.string);
|
||||
break;
|
||||
case ssaValue_Proc:
|
||||
ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & ProcTag_foreign) != 0);
|
||||
ssa_print_encoded_global(f, value->Proc.name, (value->Proc.tags & (ProcTag_foreign|ProcTag_link_name)) != 0);
|
||||
break;
|
||||
case ssaValue_Instr:
|
||||
ssa_fprintf(f, "%%%d", value->id);
|
||||
@@ -788,11 +788,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
|
||||
}
|
||||
|
||||
ssa_fprintf(f, " ");
|
||||
if (are_strings_equal(proc->name, make_string("main"))) {
|
||||
ssa_print_encoded_global(f, proc->name, true);
|
||||
} else {
|
||||
ssa_print_encoded_global(f, proc->name, (proc->tags & ProcTag_foreign) != 0);
|
||||
}
|
||||
ssa_print_encoded_global(f, proc->name, (proc->tags & (ProcTag_foreign|ProcTag_link_name)) != 0);
|
||||
ssa_fprintf(f, "(");
|
||||
|
||||
if (proc_type->param_count > 0) {
|
||||
@@ -818,12 +814,6 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
|
||||
ssa_fprintf(f, "noinline ");
|
||||
}
|
||||
|
||||
// if (proc->tags & ProcTag_stdcall) {
|
||||
// ssa_fprintf(f, "\"cc\"=\"64\" ");
|
||||
// }
|
||||
// if (proc->tags & ProcTag_fastcall) {
|
||||
// ssa_fprintf(f, "\"cc\"=\"65\" ");
|
||||
// }
|
||||
|
||||
if (proc->module->generate_debug_info && proc->entity != NULL) {
|
||||
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||
|
||||
+48
-27
@@ -46,7 +46,9 @@ struct ssaModule {
|
||||
CheckerInfo * info;
|
||||
BaseTypeSizes sizes;
|
||||
gbArena arena;
|
||||
gbArena tmp_arena;
|
||||
gbAllocator allocator;
|
||||
gbAllocator tmp_allocator;
|
||||
b32 generate_debug_info;
|
||||
|
||||
u32 stmt_state_flags;
|
||||
@@ -364,7 +366,9 @@ void ssa_init_module(ssaModule *m, Checker *c) {
|
||||
isize token_count = c->parser->total_token_count;
|
||||
isize arena_size = 4 * token_count * gb_size_of(ssaValue);
|
||||
gb_arena_init_from_allocator(&m->arena, gb_heap_allocator(), arena_size);
|
||||
m->allocator = gb_arena_allocator(&m->arena);
|
||||
gb_arena_init_from_allocator(&m->tmp_arena, gb_heap_allocator(), arena_size);
|
||||
m->allocator = gb_arena_allocator(&m->arena);
|
||||
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
|
||||
m->info = &c->info;
|
||||
m->sizes = c->sizes;
|
||||
|
||||
@@ -770,6 +774,9 @@ ssaValue *ssa_make_const_int(gbAllocator a, i64 i) {
|
||||
ssaValue *ssa_make_const_i32(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_i32, make_exact_value_integer(i));
|
||||
}
|
||||
ssaValue *ssa_make_const_i64(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_i64, make_exact_value_integer(i));
|
||||
}
|
||||
ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) {
|
||||
return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0));
|
||||
}
|
||||
@@ -1066,8 +1073,10 @@ ssaValue *ssa_lvalue_load(ssaProcedure *proc, ssaAddr lval) {
|
||||
|
||||
|
||||
void ssa_begin_procedure_body(ssaProcedure *proc) {
|
||||
gb_array_init(proc->blocks, gb_heap_allocator());
|
||||
gb_array_init(proc->blocks, gb_heap_allocator());
|
||||
gb_array_init(proc->defer_stmts, gb_heap_allocator());
|
||||
gb_array_init(proc->children, gb_heap_allocator());
|
||||
|
||||
proc->decl_block = ssa_add_block(proc, proc->type_expr, make_string("decls"));
|
||||
proc->entry_block = ssa_add_block(proc, proc->type_expr, make_string("entry"));
|
||||
proc->curr_block = proc->entry_block;
|
||||
@@ -1466,7 +1475,7 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
|
||||
|
||||
|
||||
ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
|
||||
gbAllocator a = gb_heap_allocator();
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize max_len = 4+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
@@ -2005,9 +2014,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
case_end;
|
||||
|
||||
case_ast_node(pl, ProcLit, expr);
|
||||
if (proc->children == NULL) {
|
||||
gb_array_init(proc->children, gb_heap_allocator());
|
||||
}
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent$count
|
||||
isize name_len = proc->name.len + 1 + 8 + 1;
|
||||
@@ -2456,6 +2462,20 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
ssaValue *cond = ssa_emit_comp(proc, lt, x, v_zero);
|
||||
return ssa_emit_select(proc, cond, neg_x, x);
|
||||
} break;
|
||||
|
||||
|
||||
case BuiltinProc_enum_to_string: {
|
||||
ssa_emit_comment(proc, make_string("enum_to_string"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||
Type *t = ssa_type(x);
|
||||
ssaValue *ti = ssa_type_info(proc, t);
|
||||
|
||||
|
||||
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 2);
|
||||
args[0] = ti;
|
||||
args[1] = ssa_emit_conv(proc, x, t_i64);
|
||||
return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2673,7 +2693,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
String selector = unparen_expr(se->selector)->Ident.string;
|
||||
Type *type = get_base_type(type_of_expr(proc->module->info, se->expr));
|
||||
|
||||
|
||||
if (type == t_invalid) {
|
||||
// Imports
|
||||
Entity *imp = entity_of_ident(proc->module->info, se->expr);
|
||||
@@ -3039,13 +3058,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, VarDecl, node);
|
||||
ssaModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
if (gb_array_count(vd->names) == gb_array_count(vd->values)) { // 1:1 assigment
|
||||
gbArray(ssaAddr) lvals;
|
||||
gbArray(ssaValue *) inits;
|
||||
gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names));
|
||||
gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names));
|
||||
defer (gb_array_free(lvals));
|
||||
defer (gb_array_free(inits));
|
||||
gb_array_init_reserve(lvals, m->tmp_allocator, gb_array_count(vd->names));
|
||||
gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(vd->names));
|
||||
|
||||
gb_for_array(i, vd->names) {
|
||||
AstNode *name = vd->names[i];
|
||||
@@ -3079,10 +3100,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
} else { // Tuple(s)
|
||||
gbArray(ssaAddr) lvals;
|
||||
gbArray(ssaValue *) inits;
|
||||
gb_array_init_reserve(lvals, gb_heap_allocator(), gb_array_count(vd->names));
|
||||
gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(vd->names));
|
||||
defer (gb_array_free(lvals));
|
||||
defer (gb_array_free(inits));
|
||||
gb_array_init_reserve(lvals, m->tmp_allocator, gb_array_count(vd->names));
|
||||
gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(vd->names));
|
||||
|
||||
gb_for_array(i, vd->names) {
|
||||
AstNode *name = vd->names[i];
|
||||
@@ -3118,15 +3137,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, node);
|
||||
if (proc->children == NULL) {
|
||||
gb_array_init(proc->children, gb_heap_allocator());
|
||||
}
|
||||
|
||||
|
||||
if (pd->body != NULL) {
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent$name-guid
|
||||
String pd_name = pd->name->Ident.string;
|
||||
String original_name = pd->name->Ident.string;
|
||||
String pd_name = original_name;
|
||||
if (pd->link_name.len > 0) {
|
||||
pd_name = pd->link_name;
|
||||
}
|
||||
|
||||
isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1;
|
||||
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
|
||||
i32 guid = cast(i32)gb_array_count(proc->children);
|
||||
@@ -3205,11 +3224,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
ssa_emit_comment(proc, make_string("AssignStmt"));
|
||||
|
||||
ssaModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
switch (as->op.kind) {
|
||||
case Token_Eq: {
|
||||
gbArray(ssaAddr) lvals;
|
||||
gb_array_init(lvals, gb_heap_allocator());
|
||||
defer (gb_array_free(lvals));
|
||||
gb_array_init(lvals, m->tmp_allocator);
|
||||
|
||||
gb_for_array(i, as->lhs) {
|
||||
AstNode *lhs = as->lhs[i];
|
||||
@@ -3227,8 +3250,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_lvalue_store(proc, lvals[0], init);
|
||||
} else {
|
||||
gbArray(ssaValue *) inits;
|
||||
gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals));
|
||||
defer (gb_array_free(inits));
|
||||
gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(lvals));
|
||||
|
||||
gb_for_array(i, as->rhs) {
|
||||
ssaValue *init = ssa_build_expr(proc, as->rhs[i]);
|
||||
@@ -3241,8 +3263,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
}
|
||||
} else {
|
||||
gbArray(ssaValue *) inits;
|
||||
gb_array_init_reserve(inits, gb_heap_allocator(), gb_array_count(lvals));
|
||||
defer (gb_array_free(inits));
|
||||
gb_array_init_reserve(inits, m->tmp_allocator, gb_array_count(lvals));
|
||||
|
||||
gb_for_array(i, as->rhs) {
|
||||
ssaValue *init = ssa_build_expr(proc, as->rhs[i]);
|
||||
|
||||
+3
-3
@@ -190,7 +190,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
||||
}
|
||||
|
||||
failure:
|
||||
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
|
||||
compiler_error("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
|
||||
|
||||
ExactValue error_value = {};
|
||||
return error_value;
|
||||
@@ -212,7 +212,7 @@ i32 exact_value_order(ExactValue v) {
|
||||
return 4;
|
||||
|
||||
default:
|
||||
GB_PANIC("How'd you get here? Invalid Value.kind");
|
||||
compiler_error("How'd you get here? Invalid Value.kind");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,7 @@ void match_exact_values(ExactValue *x, ExactValue *y) {
|
||||
break;
|
||||
}
|
||||
|
||||
GB_PANIC("How'd you get here? Invalid ExactValueKind");
|
||||
compiler_error("How'd you get here? Invalid ExactValueKind");
|
||||
}
|
||||
|
||||
// TODO(bill): Allow for pointer arithmetic? Or are pointer slices good enough?
|
||||
|
||||
+5
-4
@@ -40,6 +40,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(DISPLAY_TIMING)
|
||||
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
|
||||
#define PRINT_TIMER(section) do { \
|
||||
@@ -82,7 +83,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
if (!init_parser(&parser))
|
||||
return 1;
|
||||
defer (destroy_parser(&parser));
|
||||
// defer (destroy_parser(&parser));
|
||||
|
||||
if (parse_files(&parser, init_filename) != ParseFile_None)
|
||||
return 1;
|
||||
@@ -99,7 +100,7 @@ int main(int argc, char **argv) {
|
||||
sizes.max_align = 16;
|
||||
|
||||
init_checker(&checker, &parser, sizes);
|
||||
defer (destroy_checker(&checker));
|
||||
// defer (destroy_checker(&checker));
|
||||
|
||||
check_parsed_files(&checker);
|
||||
|
||||
@@ -110,7 +111,7 @@ int main(int argc, char **argv) {
|
||||
ssaGen ssa = {};
|
||||
if (!ssa_gen_init(&ssa, &checker))
|
||||
return 1;
|
||||
defer (ssa_gen_destroy(&ssa));
|
||||
// defer (ssa_gen_destroy(&ssa));
|
||||
|
||||
ssa_gen_tree(&ssa);
|
||||
|
||||
@@ -146,7 +147,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
#if 1
|
||||
gbString lib_str = gb_string_make(gb_heap_allocator(), "-lKernel32.lib");
|
||||
defer (gb_string_free(lib_str));
|
||||
// defer (gb_string_free(lib_str));
|
||||
char lib_str_buf[1024] = {};
|
||||
gb_for_array(i, parser.system_libraries) {
|
||||
String lib = parser.system_libraries[i];
|
||||
|
||||
+51
-18
@@ -63,14 +63,15 @@ enum ProcTag : u64 {
|
||||
ProcTag_no_bounds_check = GB_BIT(1),
|
||||
|
||||
ProcTag_foreign = GB_BIT(10),
|
||||
ProcTag_inline = GB_BIT(11),
|
||||
ProcTag_no_inline = GB_BIT(12),
|
||||
ProcTag_dll_import = GB_BIT(13),
|
||||
ProcTag_dll_export = GB_BIT(14),
|
||||
ProcTag_link_name = GB_BIT(11),
|
||||
ProcTag_inline = GB_BIT(12),
|
||||
ProcTag_no_inline = GB_BIT(13),
|
||||
ProcTag_dll_import = GB_BIT(14),
|
||||
ProcTag_dll_export = GB_BIT(15),
|
||||
|
||||
ProcTag_stdcall = GB_BIT(15),
|
||||
ProcTag_fastcall = GB_BIT(16),
|
||||
// ProcTag_cdecl = GB_BIT(17),
|
||||
ProcTag_stdcall = GB_BIT(16),
|
||||
ProcTag_fastcall = GB_BIT(17),
|
||||
// ProcTag_cdecl = GB_BIT(18),
|
||||
};
|
||||
|
||||
enum VarDeclTag {
|
||||
@@ -237,6 +238,7 @@ AST_NODE_KIND(_DeclBegin, "", struct{}) \
|
||||
AstNode *body; \
|
||||
u64 tags; \
|
||||
String foreign_name; \
|
||||
String link_name; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeDecl, "type declaration", struct { Token token; AstNode *name, *type; }) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
@@ -806,13 +808,14 @@ gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params,
|
||||
return result;
|
||||
}
|
||||
|
||||
gb_inline AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name) {
|
||||
gb_inline AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
|
||||
AstNode *result = make_node(f, AstNode_ProcDecl);
|
||||
result->ProcDecl.name = name;
|
||||
result->ProcDecl.type = proc_type;
|
||||
result->ProcDecl.body = body;
|
||||
result->ProcDecl.tags = tags;
|
||||
result->ProcDecl.foreign_name = foreign_name;
|
||||
result->ProcDecl.link_name = link_name;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1165,10 +1168,10 @@ b32 is_foreign_name_valid(String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
|
||||
void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_name) {
|
||||
// TODO(bill): Add this to procedure literals too
|
||||
|
||||
|
||||
GB_ASSERT(foreign_name != NULL);
|
||||
GB_ASSERT(link_name != NULL);
|
||||
|
||||
while (f->cursor[0].kind == Token_Hash) {
|
||||
AstNode *tag_expr = parse_tag_expr(f, NULL);
|
||||
@@ -1186,11 +1189,24 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
|
||||
*foreign_name = f->cursor[0].string;
|
||||
// TODO(bill): Check if valid string
|
||||
if (!is_foreign_name_valid(*foreign_name)) {
|
||||
syntax_error(ast_node_token(tag_expr), "Invalid alternative foreign procedure name");
|
||||
syntax_error(ast_node_token(tag_expr), "Invalid alternative foreign procedure name: `%.*s`", LIT(*foreign_name));
|
||||
}
|
||||
|
||||
next_token(f);
|
||||
}
|
||||
} else if (are_strings_equal(tag_name, make_string("link_name"))) {
|
||||
check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
|
||||
if (f->cursor[0].kind == Token_String) {
|
||||
*link_name = f->cursor[0].string;
|
||||
// TODO(bill): Check if valid string
|
||||
if (!is_foreign_name_valid(*link_name)) {
|
||||
syntax_error(ast_node_token(tag_expr), "Invalid alternative link procedure name `%.*s`", LIT(*link_name));
|
||||
}
|
||||
|
||||
next_token(f);
|
||||
} else {
|
||||
expect_token(f, Token_String);
|
||||
}
|
||||
}
|
||||
ELSE_IF_ADD_TAG(bounds_check)
|
||||
ELSE_IF_ADD_TAG(no_bounds_check)
|
||||
@@ -1208,6 +1224,10 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
|
||||
#undef ELSE_IF_ADD_TAG
|
||||
}
|
||||
|
||||
if ((*tags & ProcTag_foreign) && (*tags & ProcTag_link_name)) {
|
||||
syntax_error(f->cursor[0], "You cannot apply both #foreign and #link_name to a procedure");
|
||||
}
|
||||
|
||||
if ((*tags & ProcTag_inline) && (*tags & ProcTag_no_inline)) {
|
||||
syntax_error(f->cursor[0], "You cannot apply both #inline and #no_inline to a procedure");
|
||||
}
|
||||
@@ -1219,6 +1239,10 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
|
||||
if (((*tags & ProcTag_bounds_check) || (*tags & ProcTag_no_bounds_check)) && (*tags & ProcTag_foreign)) {
|
||||
syntax_error(f->cursor[0], "You cannot apply both #bounds_check or #no_bounds_check to a procedure without a body");
|
||||
}
|
||||
|
||||
if ((*tags & ProcTag_stdcall) && (*tags & ProcTag_fastcall)) {
|
||||
syntax_error(f->cursor[0], "You cannot apply one calling convention to a procedure");
|
||||
}
|
||||
}
|
||||
|
||||
AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
@@ -1292,10 +1316,14 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
|
||||
u64 tags = 0;
|
||||
String foreign_name = {};
|
||||
parse_proc_tags(f, &tags, &foreign_name);
|
||||
String link_name = {};
|
||||
parse_proc_tags(f, &tags, &foreign_name, &link_name);
|
||||
if (tags & ProcTag_foreign) {
|
||||
syntax_error(f->cursor[0], "#foreign cannot be applied to procedure literals");
|
||||
}
|
||||
if (tags & ProcTag_link_name) {
|
||||
syntax_error(f->cursor[0], "#link_name cannot be applied to procedure literals");
|
||||
}
|
||||
|
||||
if (f->cursor[0].kind != Token_OpenBrace) {
|
||||
return type;
|
||||
@@ -2082,8 +2110,9 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
|
||||
AstNode *body = NULL;
|
||||
u64 tags = 0;
|
||||
String foreign_name = {};
|
||||
String link_name = {};
|
||||
|
||||
parse_proc_tags(f, &tags, &foreign_name);
|
||||
parse_proc_tags(f, &tags, &foreign_name, &link_name);
|
||||
|
||||
AstNode *curr_proc = f->curr_proc;
|
||||
f->curr_proc = proc_type;
|
||||
@@ -2096,7 +2125,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
|
||||
body = parse_body(f);
|
||||
}
|
||||
|
||||
return make_proc_decl(f, name, proc_type, body, tags, foreign_name);
|
||||
return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
|
||||
}
|
||||
|
||||
AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
||||
@@ -2794,7 +2823,7 @@ b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
||||
}
|
||||
|
||||
gb_global Rune illegal_import_runes[] = {
|
||||
'"', '\'', '`', ' ',
|
||||
'"', '\'', '`', ' ', '\t', '\r', '\n', '\v', '\f',
|
||||
'\\', // NOTE(bill): Disallow windows style filepaths
|
||||
'!', '$', '%', '^', '&', '*', '(', ')', '=', '+',
|
||||
'[', ']', '{', '}',
|
||||
@@ -2862,10 +2891,12 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
|
||||
if (!is_import_path_valid(file_str)) {
|
||||
if (id->is_load) {
|
||||
syntax_error(ast_node_token(node), "Invalid #load path");
|
||||
syntax_error(ast_node_token(node), "Invalid #load path: `%.*s`", LIT(file_str));
|
||||
} else {
|
||||
syntax_error(ast_node_token(node), "Invalid #import path");
|
||||
syntax_error(ast_node_token(node), "Invalid #import path: `%.*s`", LIT(file_str));
|
||||
}
|
||||
// NOTE(bill): It's a naughty name
|
||||
f->decls[i] = make_bad_decl(f, id->token, id->token);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2888,6 +2919,8 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
|
||||
if (!is_import_path_valid(file_str)) {
|
||||
syntax_error(ast_node_token(node), "Invalid `foreign_system_library` path");
|
||||
// NOTE(bill): It's a naughty name
|
||||
f->decls[i] = make_bad_decl(f, id->token, id->token);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user