mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-27 16:53:55 +00:00
Remove: string overloads; defer
This commit is contained in:
@@ -47,8 +47,8 @@ rem pushd %build_dir%
|
||||
del *.ilk > NUL 2> NUL
|
||||
|
||||
cl %compiler_settings% "src\main.cpp" ^
|
||||
/link %linker_settings% -OUT:%exe_name% ^
|
||||
&& odin run code/demo.odin
|
||||
/link %linker_settings% -OUT:%exe_name%
|
||||
rem && odin run code/demo.odin
|
||||
rem odin run code/demo.odin
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@echo off
|
||||
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
||||
set _NO_DEBUG_HEAP=1
|
||||
|
||||
|
||||
@@ -508,10 +508,10 @@ void init_universal_scope(void) {
|
||||
}
|
||||
|
||||
// Constants
|
||||
add_global_constant(a, make_string("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||
add_global_constant(a, make_string("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||
add_global_constant(a, str_lit("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||
add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||
|
||||
add_global_entity(make_entity_nil(a, make_string("nil"), t_untyped_nil));
|
||||
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
||||
|
||||
// Builtin Procedures
|
||||
for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
|
||||
@@ -671,7 +671,7 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
|
||||
}
|
||||
|
||||
b32 add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
||||
if (entity->token.string != make_string("_")) {
|
||||
if (str_ne(entity->token.string, str_lit("_"))) {
|
||||
Entity *insert_entity = scope_insert_entity(scope, entity);
|
||||
if (insert_entity) {
|
||||
Entity *up = insert_entity->using_parent;
|
||||
@@ -714,7 +714,7 @@ void add_entity_use(Checker *c, AstNode *identifier, Entity *entity) {
|
||||
|
||||
|
||||
void add_entity_and_decl_info(Checker *c, AstNode *identifier, Entity *e, DeclInfo *d) {
|
||||
GB_ASSERT(identifier->Ident.string == e->token.string);
|
||||
GB_ASSERT(str_eq(identifier->Ident.string, e->token.string));
|
||||
add_entity(c, e->scope, identifier, e);
|
||||
map_set(&c->info.entities, hash_pointer(e), d);
|
||||
}
|
||||
@@ -925,7 +925,7 @@ void init_preload_types(Checker *c) {
|
||||
|
||||
|
||||
if (t_type_info == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Type_Info"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Type_Info`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -961,7 +961,7 @@ void init_preload_types(Checker *c) {
|
||||
}
|
||||
|
||||
if (t_allocator == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Allocator"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Allocator"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Allocator`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -971,7 +971,7 @@ void init_preload_types(Checker *c) {
|
||||
}
|
||||
|
||||
if (t_context == NULL) {
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Context"));
|
||||
Entity *e = current_scope_lookup_entity(c->global_scope, str_lit("Context"));
|
||||
if (e == NULL) {
|
||||
compiler_error("Could not find type declaration for `Context`\n"
|
||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||
@@ -992,14 +992,42 @@ void add_implicit_value(Checker *c, ImplicitValueId id, String name, String back
|
||||
c->info.implicit_values[id] = value;
|
||||
}
|
||||
|
||||
|
||||
void check_global_entity(Checker *c, EntityKind kind) {
|
||||
PROF_SCOPED("check_global_entity");
|
||||
for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
if (e->kind == kind) {
|
||||
DeclInfo *d = entry->value;
|
||||
|
||||
add_curr_ast_file(c, d->scope->file);
|
||||
|
||||
if (d->scope == e->scope) {
|
||||
if (kind != Entity_Procedure && str_eq(e->token.string, str_lit("main"))) {
|
||||
if (e->scope->is_init) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
} else if (e->scope->is_global && str_eq(e->token.string, str_lit("main"))) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
|
||||
Scope *prev_scope = c->context.scope;
|
||||
c->context.scope = d->scope;
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void check_parsed_files(Checker *c) {
|
||||
Array<AstNode *> import_decls;
|
||||
array_init(&import_decls, heap_allocator());
|
||||
defer (array_free(&import_decls));
|
||||
|
||||
Map<Scope *> file_scopes; // Key: String (fullpath)
|
||||
map_init(&file_scopes, heap_allocator());
|
||||
defer (map_destroy(&file_scopes));
|
||||
|
||||
// Map full filepaths to Scopes
|
||||
for_array(i, c->parser->files) {
|
||||
@@ -1176,7 +1204,7 @@ void check_parsed_files(Checker *c) {
|
||||
warning(id->token, "Multiple #import of the same file within this scope");
|
||||
}
|
||||
|
||||
if (id->import_name.string == ".") {
|
||||
if (str_eq(id->import_name.string, str_lit("."))) {
|
||||
// NOTE(bill): Add imported entities to this file's scope
|
||||
for_array(elem_index, scope->elements.entries) {
|
||||
Entity *e = scope->elements.entries[elem_index].value;
|
||||
@@ -1241,39 +1269,10 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
auto check_global_entity = [](Checker *c, EntityKind kind) {
|
||||
PROF_SCOPED("check_global_entity");
|
||||
for_array(i, c->info.entities.entries) {
|
||||
auto *entry = &c->info.entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
if (e->kind == kind) {
|
||||
DeclInfo *d = entry->value;
|
||||
|
||||
add_curr_ast_file(c, d->scope->file);
|
||||
|
||||
if (d->scope == e->scope) {
|
||||
if (kind != Entity_Procedure && e->token.string == "main") {
|
||||
if (e->scope->is_init) {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
} else if (e->scope->is_global && e->token.string == "main") {
|
||||
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||
continue;
|
||||
}
|
||||
|
||||
Scope *prev_scope = c->context.scope;
|
||||
c->context.scope = d->scope;
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
check_global_entity(c, Entity_TypeName);
|
||||
|
||||
init_preload_types(c);
|
||||
add_implicit_value(c, ImplicitValue_context, make_string("context"), make_string("__context"), t_context);
|
||||
add_implicit_value(c, ImplicitValue_context, str_lit("context"), str_lit("__context"), t_context);
|
||||
|
||||
check_global_entity(c, Entity_Constant);
|
||||
check_global_entity(c, Entity_Procedure);
|
||||
@@ -1299,8 +1298,8 @@ void check_parsed_files(Checker *c) {
|
||||
b32 bounds_check = (pi->tags & ProcTag_bounds_check) != 0;
|
||||
b32 no_bounds_check = (pi->tags & ProcTag_no_bounds_check) != 0;
|
||||
|
||||
auto prev_context = c->context;
|
||||
defer (c->context = prev_context);
|
||||
CheckerContext prev_context = c->context;
|
||||
|
||||
if (bounds_check) {
|
||||
c->context.stmt_state_flags |= StmtStateFlag_bounds_check;
|
||||
c->context.stmt_state_flags &= ~StmtStateFlag_no_bounds_check;
|
||||
@@ -1310,6 +1309,8 @@ void check_parsed_files(Checker *c) {
|
||||
}
|
||||
|
||||
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
|
||||
|
||||
c->context = prev_context;
|
||||
}
|
||||
|
||||
// Add untyped expression values
|
||||
@@ -1365,6 +1366,8 @@ void check_parsed_files(Checker *c) {
|
||||
// gb_printf("%td - %s\n", e->value, type_to_string(prev_type));
|
||||
// }
|
||||
|
||||
map_destroy(&file_scopes);
|
||||
array_free(&import_decls);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
|
||||
if (operand->mode == Addressing_Builtin) {
|
||||
gbString expr_str = expr_to_string(operand->expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
|
||||
// TODO(bill): is this a good enough error message?
|
||||
error(ast_node_token(operand->expr),
|
||||
@@ -25,6 +24,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
||||
LIT(context_name));
|
||||
|
||||
operand->mode = Addressing_Invalid;
|
||||
|
||||
gb_string_free(expr_str);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +65,6 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
@@ -102,6 +102,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
if (rhs_count > 0 && lhs_count != rhs_count) {
|
||||
error(lhs[0]->token, "Assignment count mismatch `%td` := `%td`", lhs_count, rhs_count);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,10 +131,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
check_proc_decl(c, e, d);
|
||||
return;
|
||||
}
|
||||
auto prev = c->context;
|
||||
CheckerContext prev = c->context;
|
||||
c->context.scope = d->scope;
|
||||
c->context.decl = d;
|
||||
defer (c->context = prev);
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_Constant:
|
||||
@@ -145,6 +146,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
||||
check_type_decl(c, e, d->type_expr, named_type, cycle_checker);
|
||||
break;
|
||||
}
|
||||
|
||||
c->context = prev;
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +168,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
||||
String str = token.string;
|
||||
Entity *found = NULL;
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (str != make_string("_")) {
|
||||
if (str_ne(str, str_lit("_"))) {
|
||||
found = current_scope_lookup_entity(c->context.scope, str);
|
||||
}
|
||||
if (found == NULL) {
|
||||
@@ -208,7 +211,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
||||
e->type = init_type;
|
||||
}
|
||||
|
||||
check_init_variables(c, entities, entity_count, vd->values, make_string("variable declaration"));
|
||||
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
|
||||
|
||||
for_array(i, vd->names) {
|
||||
if (entities[i] != NULL) {
|
||||
@@ -256,7 +259,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
e->type = operand->type;
|
||||
}
|
||||
|
||||
check_assignment(c, operand, e->type, make_string("constant declaration"));
|
||||
check_assignment(c, operand, e->type, str_lit("constant declaration"));
|
||||
if (operand->mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
@@ -311,7 +314,6 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
||||
if (cycle_checker == NULL) {
|
||||
cycle_checker = &local_cycle_checker;
|
||||
}
|
||||
defer (cycle_checker_destroy(&local_cycle_checker));
|
||||
|
||||
Type *bt = check_type(c, type_expr, named, cycle_checker_add(cycle_checker, e));
|
||||
named->Named.base = bt;
|
||||
@@ -319,6 +321,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
||||
if (named->Named.base == t_invalid) {
|
||||
gb_printf("check_type_decl: %s\n", type_to_string(named));
|
||||
}
|
||||
|
||||
cycle_checker_destroy(&local_cycle_checker);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,8 +372,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
|
||||
e->type = proc_type;
|
||||
ast_node(pd, ProcDecl, d->proc_decl);
|
||||
|
||||
check_open_scope(c, pd->type);
|
||||
defer (check_close_scope(c));
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
|
||||
b32 is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
@@ -378,16 +382,15 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
|
||||
if ((d->scope->is_file || d->scope->is_global) &&
|
||||
e->token.string == "main") {
|
||||
str_eq(e->token.string, str_lit("main"))) {
|
||||
if (proc_type != NULL) {
|
||||
auto *pt = &proc_type->Proc;
|
||||
if (pt->param_count != 0 ||
|
||||
pt->result_count) {
|
||||
gbString str = type_to_string(proc_type);
|
||||
defer (gb_string_free(str));
|
||||
|
||||
error(e->token,
|
||||
"Procedure type of `main` was expected to be `proc()`, got %s", str);
|
||||
gb_string_free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,6 +458,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
map_set(fp, key, e);
|
||||
}
|
||||
}
|
||||
|
||||
check_close_scope(c);
|
||||
}
|
||||
|
||||
void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) {
|
||||
@@ -482,7 +487,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
GB_ASSERT(entities == NULL || entities[0] == e);
|
||||
Operand operand = {};
|
||||
check_expr(c, &operand, init_expr);
|
||||
check_init_variable(c, e, &operand, make_string("variable declaration"));
|
||||
check_init_variable(c, e, &operand, str_lit("variable declaration"));
|
||||
}
|
||||
|
||||
if (type_expr != NULL) {
|
||||
@@ -493,7 +498,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
AstNodeArray inits;
|
||||
array_init(&inits, c->allocator, 1);
|
||||
array_add(&inits, init_expr);
|
||||
check_init_variables(c, entities, entity_count, inits, make_string("variable declaration"));
|
||||
check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
|
||||
}
|
||||
|
||||
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
||||
@@ -502,8 +507,6 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
||||
CheckerContext old_context = c->context;
|
||||
c->context.scope = decl->scope;
|
||||
c->context.decl = decl;
|
||||
defer (c->context = old_context);
|
||||
|
||||
|
||||
GB_ASSERT(type->kind == Type_Proc);
|
||||
if (type->Proc.param_count > 0) {
|
||||
@@ -552,6 +555,8 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
||||
|
||||
|
||||
check_scope_usage(c, c->context.scope);
|
||||
|
||||
c->context = old_context;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ Entity *make_entity_implicit_value(gbAllocator a, String name, Type *type, Impli
|
||||
|
||||
|
||||
Entity *make_entity_dummy_variable(gbAllocator a, Scope *file_scope, Token token) {
|
||||
token.string = make_string("_");
|
||||
token.string = str_lit("_");
|
||||
return make_entity_variable(a, file_scope, token, NULL);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,12 +18,11 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
struct Delay {
|
||||
typedef struct {
|
||||
Entity *e;
|
||||
DeclInfo *d;
|
||||
};
|
||||
} Delay;
|
||||
Array<Delay> delayed_const; array_init(&delayed_const, c->tmp_allocator, stmts.count);
|
||||
Array<Delay> delayed_type; array_init(&delayed_type, c->tmp_allocator, stmts.count);
|
||||
|
||||
@@ -95,6 +94,8 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
|
||||
}
|
||||
check_stmt(c, n, new_flags);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
b32 check_is_terminating_list(AstNodeArray stmts) {
|
||||
@@ -238,9 +239,9 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (node->kind == AstNode_Ident &&
|
||||
node->Ident.string == "_") {
|
||||
str_eq(node->Ident.string, str_lit("_"))) {
|
||||
add_entity_definition(&c->info, node, NULL);
|
||||
check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier"));
|
||||
check_assignment(c, op_a, NULL, str_lit("assignment to `_` identifier"));
|
||||
if (op_a->mode == Addressing_Invalid)
|
||||
return NULL;
|
||||
return op_a->type;
|
||||
@@ -282,7 +283,6 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
}
|
||||
|
||||
gbString str = expr_to_string(op_b.expr);
|
||||
defer (gb_string_free(str));
|
||||
switch (op_b.mode) {
|
||||
case Addressing_Value:
|
||||
error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
|
||||
@@ -291,13 +291,14 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||
error(ast_node_token(op_b.expr), "Cannot assign to `%s`", str);
|
||||
break;
|
||||
}
|
||||
|
||||
gb_string_free(str);
|
||||
} break;
|
||||
}
|
||||
|
||||
check_assignment(c, op_a, op_b.type, make_string("assignment"));
|
||||
if (op_a->mode == Addressing_Invalid)
|
||||
check_assignment(c, op_a, op_b.type, str_lit("assignment"));
|
||||
if (op_a->mode == Addressing_Invalid) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return op_a->type;
|
||||
}
|
||||
@@ -314,15 +315,13 @@ b32 check_valid_type_match_type(Type *type, b32 *is_union_ptr, b32 *is_any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void check_stmt_internal(Checker *c, AstNode *node, u32 flags);
|
||||
void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
u32 prev_stmt_state_flags = c->context.stmt_state_flags;
|
||||
defer (c->context.stmt_state_flags = prev_stmt_state_flags);
|
||||
|
||||
if (node->stmt_state_flags != 0) {
|
||||
u32 in = node->stmt_state_flags;
|
||||
u32 out = c->context.stmt_state_flags;
|
||||
defer (c->context.stmt_state_flags = out);
|
||||
|
||||
if (in & StmtStateFlag_bounds_check) {
|
||||
out |= StmtStateFlag_bounds_check;
|
||||
@@ -331,9 +330,16 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
out |= StmtStateFlag_no_bounds_check;
|
||||
out &= ~StmtStateFlag_bounds_check;
|
||||
}
|
||||
|
||||
c->context.stmt_state_flags = out;
|
||||
}
|
||||
|
||||
check_stmt_internal(c, node, flags);
|
||||
|
||||
c->context.stmt_state_flags = prev_stmt_state_flags;
|
||||
}
|
||||
|
||||
void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
u32 mod_flags = flags & (~Stmt_FallthroughAllowed);
|
||||
switch (node->kind) {
|
||||
case_ast_node(_, EmptyStmt, node); case_end;
|
||||
@@ -352,16 +358,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case Addressing_NoValue:
|
||||
return;
|
||||
default: {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
if (kind == Expr_Stmt) {
|
||||
return;
|
||||
}
|
||||
if (operand.expr->kind == AstNode_CallExpr) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
error(ast_node_token(node), "Expression is not used: `%s`", expr_str);
|
||||
gb_string_free(expr_str);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
@@ -403,7 +408,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
ast_node(bl, BasicLit, &basic_lit);
|
||||
*bl = ids->op;
|
||||
bl->kind = Token_Integer;
|
||||
bl->string = make_string("1");
|
||||
bl->string = str_lit("1");
|
||||
|
||||
AstNode binary_expr = {AstNode_BinaryExpr};
|
||||
ast_node(be, BinaryExpr, &binary_expr);
|
||||
@@ -425,7 +430,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
|
||||
// an extra allocation
|
||||
@@ -458,6 +462,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
if (lhs_count != rhs_count) {
|
||||
error(ast_node_token(as->lhs[0]), "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@@ -501,10 +507,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
PROF_SCOPED("check_stmt - IfStmt");
|
||||
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (is->init != NULL)
|
||||
if (is->init != NULL) {
|
||||
check_stmt(c, is->init, 0);
|
||||
}
|
||||
|
||||
Operand operand = {Addressing_Invalid};
|
||||
check_expr(c, &operand, is->cond);
|
||||
@@ -528,6 +534,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, ReturnStmt, node);
|
||||
@@ -558,7 +566,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
error(ast_node_token(node), "Expected %td return values, got 0", result_count);
|
||||
} else {
|
||||
check_init_variables(c, variables, result_count,
|
||||
rs->results, make_string("return statement"));
|
||||
rs->results, str_lit("return statement"));
|
||||
}
|
||||
} else if (rs->results.count > 0) {
|
||||
error(ast_node_token(rs->results[0]), "No return values expected");
|
||||
@@ -570,10 +578,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (fs->init != NULL)
|
||||
if (fs->init != NULL) {
|
||||
check_stmt(c, fs->init, 0);
|
||||
}
|
||||
if (fs->cond) {
|
||||
Operand operand = {Addressing_Invalid};
|
||||
check_expr(c, &operand, fs->cond);
|
||||
@@ -583,9 +591,12 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
"Non-boolean condition in `for` statement");
|
||||
}
|
||||
}
|
||||
if (fs->post != NULL)
|
||||
if (fs->post != NULL) {
|
||||
check_stmt(c, fs->post, 0);
|
||||
}
|
||||
check_stmt(c, fs->body, new_flags);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
@@ -595,14 +606,13 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
if (ms->init != NULL) {
|
||||
check_stmt(c, ms->init, 0);
|
||||
}
|
||||
if (ms->tag != NULL) {
|
||||
check_expr(c, &x, ms->tag);
|
||||
check_assignment(c, &x, NULL, make_string("match expression"));
|
||||
check_assignment(c, &x, NULL, str_lit("match expression"));
|
||||
} else {
|
||||
x.mode = Addressing_Constant;
|
||||
x.type = t_bool;
|
||||
@@ -610,7 +620,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Token token = {};
|
||||
token.pos = ast_node_token(ms->body).pos;
|
||||
token.string = make_string("true");
|
||||
token.string = str_lit("true");
|
||||
x.expr = make_ident(c->curr_ast_file, token);
|
||||
}
|
||||
|
||||
@@ -649,7 +659,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
if (stmt->kind != AstNode_CaseClause) {
|
||||
@@ -689,8 +699,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
auto *found = map_get(&seen, key);
|
||||
if (found != NULL) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
isize count = multi_map_count(&seen, key);
|
||||
TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
|
||||
|
||||
@@ -713,6 +721,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
|
||||
if (continue_outer) {
|
||||
continue;
|
||||
}
|
||||
@@ -730,6 +740,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
check_stmt_list(c, cc->stmts, ft_flags);
|
||||
check_close_scope(c);
|
||||
}
|
||||
|
||||
map_destroy(&seen);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
@@ -739,18 +753,17 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
mod_flags |= Stmt_BreakAllowed;
|
||||
check_open_scope(c, node);
|
||||
defer (check_close_scope(c));
|
||||
|
||||
b32 is_union_ptr = false;
|
||||
b32 is_any = false;
|
||||
|
||||
check_expr(c, &x, ms->tag);
|
||||
check_assignment(c, &x, NULL, make_string("type match expression"));
|
||||
check_assignment(c, &x, NULL, str_lit("type match expression"));
|
||||
if (!check_valid_type_match_type(x.type, &is_union_ptr, &is_any)) {
|
||||
gbString str = type_to_string(x.type);
|
||||
defer (gb_string_free(str));
|
||||
error(ast_node_token(x.expr),
|
||||
"Invalid type for this type match expression, got `%s`", str);
|
||||
gb_string_free(str);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -789,8 +802,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
Map<b32> seen = {};
|
||||
map_init(&seen, heap_allocator());
|
||||
defer (map_destroy(&seen));
|
||||
|
||||
|
||||
for_array(i, bs->stmts) {
|
||||
AstNode *stmt = bs->stmts[i];
|
||||
@@ -822,9 +833,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
if (!tag_type_found) {
|
||||
gbString type_str = type_to_string(y.type);
|
||||
defer (gb_string_free(type_str));
|
||||
error(ast_node_token(y.expr),
|
||||
"Unknown tag type, got `%s`", type_str);
|
||||
gb_string_free(type_str);
|
||||
continue;
|
||||
}
|
||||
case_type = y.type;
|
||||
@@ -868,6 +879,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
check_stmt_list(c, cc->stmts, mod_flags);
|
||||
check_close_scope(c);
|
||||
}
|
||||
map_destroy(&seen);
|
||||
|
||||
check_close_scope(c);
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -930,9 +944,6 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
return;
|
||||
}
|
||||
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
defer (gb_string_free(expr_str));
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName: {
|
||||
Type *t = base_type(e->type);
|
||||
@@ -941,7 +952,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.other_fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -951,7 +964,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -960,7 +975,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *f = t->Record.other_fields[i];
|
||||
Entity *found = scope_insert_entity(c->context.scope, f);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
f->using_parent = e;
|
||||
@@ -974,6 +991,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
Entity *decl = scope->elements.entries[i].value;
|
||||
Entity *found = scope_insert_entity(c->context.scope, decl);
|
||||
if (found != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token,
|
||||
"Namespace collision while `using` `%s` of: %.*s\n"
|
||||
"\tat %.*s(%td:%td)\n"
|
||||
@@ -982,6 +1000,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
LIT(found->token.pos.file), found->token.pos.line, found->token.pos.column,
|
||||
LIT(decl->token.pos.file), decl->token.pos.line, decl->token.pos.column
|
||||
);
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +1020,9 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
Entity *prev = scope_insert_entity(c->context.scope, uvar);
|
||||
if (prev != NULL) {
|
||||
gbString expr_str = expr_to_string(expr);
|
||||
error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(prev->token.string));
|
||||
gb_string_free(expr_str);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1106,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case_ast_node(pa, PushAllocator, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_allocator, make_string("argument to push_allocator"));
|
||||
check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
@@ -1093,7 +1114,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
case_ast_node(pa, PushContext, node);
|
||||
Operand op = {};
|
||||
check_expr(c, &op, pa->expr);
|
||||
check_assignment(c, &op, t_context, make_string("argument to push_context"));
|
||||
check_assignment(c, &op, t_context, str_lit("argument to push_context"));
|
||||
check_stmt(c, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
@@ -1128,7 +1149,5 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
||||
add_entity_and_decl_info(c, pd->name, e, d);
|
||||
check_entity_decl(c, e, d, NULL);
|
||||
case_end;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,7 +719,7 @@ b32 are_types_identical(Type *x, Type *y) {
|
||||
if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) {
|
||||
return false;
|
||||
}
|
||||
if (x->Record.fields[i]->token.string != y->Record.fields[i]->token.string) {
|
||||
if (str_ne(x->Record.fields[i]->token.string, y->Record.fields[i]->token.string)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -836,7 +836,7 @@ gb_global Entity *entity__slice_capacity = NULL;
|
||||
Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
|
||||
GB_ASSERT(type_ != NULL);
|
||||
|
||||
if (field_name == "_") {
|
||||
if (str_eq(field_name, str_lit("_"))) {
|
||||
return empty_selection;
|
||||
}
|
||||
|
||||
@@ -849,8 +849,8 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
if (type->kind == Type_Basic) {
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_any: {
|
||||
String type_info_str = make_string("type_info");
|
||||
String data_str = make_string("data");
|
||||
String type_info_str = str_lit("type_info");
|
||||
String data_str = str_lit("data");
|
||||
if (entity__any_type_info == NULL) {
|
||||
entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 0);
|
||||
}
|
||||
@@ -858,19 +858,19 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 1);
|
||||
}
|
||||
|
||||
if (field_name == type_info_str) {
|
||||
if (str_eq(field_name, type_info_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
sel.entity = entity__any_type_info;
|
||||
return sel;
|
||||
} else if (field_name == data_str) {
|
||||
} else if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
sel.entity = entity__any_data;
|
||||
return sel;
|
||||
}
|
||||
} break;
|
||||
case Basic_string: {
|
||||
String data_str = make_string("data");
|
||||
String count_str = make_string("count");
|
||||
String data_str = str_lit("data");
|
||||
String count_str = str_lit("count");
|
||||
if (entity__string_data == NULL) {
|
||||
entity__string_data = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, t_u8), false, 0);
|
||||
}
|
||||
@@ -879,11 +879,11 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
entity__string_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
|
||||
}
|
||||
|
||||
if (field_name == data_str) {
|
||||
if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
sel.entity = entity__string_data;
|
||||
return sel;
|
||||
} else if (field_name == count_str) {
|
||||
} else if (str_eq(field_name, count_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
sel.entity = entity__string_count;
|
||||
return sel;
|
||||
@@ -893,17 +893,17 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
|
||||
return sel;
|
||||
} else if (type->kind == Type_Array) {
|
||||
String count_str = make_string("count");
|
||||
String count_str = str_lit("count");
|
||||
// NOTE(bill): Underlying memory address cannot be changed
|
||||
if (field_name == count_str) {
|
||||
if (str_eq(field_name, count_str)) {
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Array.count));
|
||||
return sel;
|
||||
}
|
||||
} else if (type->kind == Type_Vector) {
|
||||
String count_str = make_string("count");
|
||||
String count_str = str_lit("count");
|
||||
// NOTE(bill): Vectors are not addressable
|
||||
if (field_name == count_str) {
|
||||
if (str_eq(field_name, count_str)) {
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_constant(a, NULL, make_token_ident(count_str), t_int, make_exact_value_integer(type->Vector.count));
|
||||
return sel;
|
||||
@@ -914,9 +914,9 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
switch (type->Vector.count) {
|
||||
#define _VECTOR_FIELD_CASE(_length, _name) \
|
||||
case (_length): \
|
||||
if (field_name == _name) { \
|
||||
if (str_eq(field_name, str_lit(_name))) { \
|
||||
selection_add_index(&sel, (_length)-1); \
|
||||
sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(make_string(_name)), type->Vector.elem, (_length)-1); \
|
||||
sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
|
||||
return sel; \
|
||||
} \
|
||||
/*fallthrough*/
|
||||
@@ -932,16 +932,16 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
}
|
||||
|
||||
} else if (type->kind == Type_Slice) {
|
||||
String data_str = make_string("data");
|
||||
String count_str = make_string("count");
|
||||
String capacity_str = make_string("capacity");
|
||||
String data_str = str_lit("data");
|
||||
String count_str = str_lit("count");
|
||||
String capacity_str = str_lit("capacity");
|
||||
|
||||
if (field_name == data_str) {
|
||||
if (str_eq(field_name, data_str)) {
|
||||
selection_add_index(&sel, 0);
|
||||
// HACK(bill): Memory leak
|
||||
sel.entity = make_entity_field(a, NULL, make_token_ident(data_str), make_type_pointer(a, type->Slice.elem), false, 0);
|
||||
return sel;
|
||||
} else if (field_name == count_str) {
|
||||
} else if (str_eq(field_name, count_str)) {
|
||||
selection_add_index(&sel, 1);
|
||||
if (entity__slice_count == NULL) {
|
||||
entity__slice_count = make_entity_field(a, NULL, make_token_ident(count_str), t_int, false, 1);
|
||||
@@ -949,7 +949,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
|
||||
sel.entity = entity__slice_count;
|
||||
return sel;
|
||||
} else if (field_name == capacity_str) {
|
||||
} else if (str_eq(field_name, capacity_str)) {
|
||||
selection_add_index(&sel, 2);
|
||||
if (entity__slice_capacity == NULL) {
|
||||
entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
|
||||
@@ -972,7 +972,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
GB_ASSERT(f->kind == Entity_TypeName);
|
||||
String str = f->token.string;
|
||||
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
sel.entity = f;
|
||||
selection_add_index(&sel, i);
|
||||
return sel;
|
||||
@@ -985,7 +985,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
GB_ASSERT(f->kind != Entity_Variable);
|
||||
String str = f->token.string;
|
||||
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
sel.entity = f;
|
||||
selection_add_index(&sel, i);
|
||||
return sel;
|
||||
@@ -993,13 +993,13 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
}
|
||||
|
||||
if (is_type_enum(type)) {
|
||||
if (field_name == "count") {
|
||||
if (str_eq(field_name, str_lit("count"))) {
|
||||
sel.entity = type->Record.enum_count;
|
||||
return sel;
|
||||
} else if (field_name == "min_value") {
|
||||
} else if (str_eq(field_name, str_lit("min_value"))) {
|
||||
sel.entity = type->Record.min_value;
|
||||
return sel;
|
||||
} else if (field_name == "max_value") {
|
||||
} else if (str_eq(field_name, str_lit("max_value"))) {
|
||||
sel.entity = type->Record.max_value;
|
||||
return sel;
|
||||
}
|
||||
@@ -1010,7 +1010,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
||||
Entity *f = type->Record.fields[i];
|
||||
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||
String str = f->token.string;
|
||||
if (field_name == str) {
|
||||
if (str_eq(field_name, str)) {
|
||||
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
||||
sel.entity = f;
|
||||
return sel;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#define GB_NO_DEFER
|
||||
#define GB_IMPLEMENTATION
|
||||
#include "gb/gb.h"
|
||||
|
||||
@@ -8,7 +9,7 @@ gbAllocator heap_allocator(void) {
|
||||
#include "string.cpp"
|
||||
#include "array.cpp"
|
||||
|
||||
gb_global String global_module_path = {};
|
||||
gb_global String global_module_path = {0};
|
||||
gb_global b32 global_module_path_set = false;
|
||||
|
||||
|
||||
@@ -19,7 +20,6 @@ String get_module_dir() {
|
||||
|
||||
Array<wchar_t> path_buf;
|
||||
array_init(&path_buf, heap_allocator(), 300);
|
||||
defer (array_free(&path_buf));
|
||||
array_resize(&path_buf, 300);
|
||||
|
||||
isize len = 0;
|
||||
@@ -35,7 +35,6 @@ String get_module_dir() {
|
||||
}
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
|
||||
@@ -52,40 +51,29 @@ String get_module_dir() {
|
||||
global_module_path = path;
|
||||
global_module_path_set = true;
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
|
||||
array_free(&path_buf);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
String path_to_fullpath(gbAllocator a, String s) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
String16 string16 = string_to_string16(string_buffer_allocator, s);
|
||||
String result = {0};
|
||||
|
||||
DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
|
||||
if (len == 0) {
|
||||
return make_string(NULL, 0);
|
||||
if (len != 0) {
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
GetFullPathNameW(string16.text, len, text, NULL);
|
||||
text[len] = 0;
|
||||
result = string16_to_string(a, make_string16(text, len));
|
||||
}
|
||||
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
|
||||
GetFullPathNameW(string16.text, len, text, NULL);
|
||||
text[len] = 0;
|
||||
|
||||
return string16_to_string(a, make_string16(text, len));
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
return result;
|
||||
}
|
||||
|
||||
struct BlockTimer {
|
||||
u64 start;
|
||||
u64 finish;
|
||||
char *msg;
|
||||
BlockTimer(char *msg) : msg(msg) {
|
||||
start = gb_utc_time_now();
|
||||
}
|
||||
~BlockTimer() {
|
||||
finish = gb_utc_time_now();
|
||||
gb_printf_err("%llu us\n", finish-start);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Hasing
|
||||
enum HashKeyKind {
|
||||
HashKey_Default,
|
||||
@@ -103,7 +91,7 @@ struct HashKey {
|
||||
};
|
||||
|
||||
gb_inline HashKey hashing_proc(void const *data, isize len) {
|
||||
HashKey h = {};
|
||||
HashKey h = {HashKey_Default};
|
||||
h.kind = HashKey_Default;
|
||||
// h.key = gb_murmur64(data, len);
|
||||
h.key = gb_fnv64a(data, len);
|
||||
@@ -118,7 +106,7 @@ gb_inline HashKey hash_string(String s) {
|
||||
}
|
||||
|
||||
gb_inline HashKey hash_pointer(void *ptr) {
|
||||
HashKey h = {};
|
||||
HashKey h = {HashKey_Default};
|
||||
h.key = cast(u64)cast(uintptr)ptr;
|
||||
h.ptr = ptr;
|
||||
h.kind = HashKey_Default;
|
||||
@@ -130,7 +118,7 @@ b32 hash_key_equal(HashKey a, HashKey b) {
|
||||
// NOTE(bill): If two string's hashes collide, compare the strings themselves
|
||||
if (a.kind == HashKey_String) {
|
||||
if (b.kind == HashKey_String) {
|
||||
return a.string == b.string;
|
||||
return str_eq(a.string, b.string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -364,7 +352,7 @@ gb_inline void map_grow(Map<T> *h) {
|
||||
template <typename T>
|
||||
void map_rehash(Map<T> *h, isize new_count) {
|
||||
isize i, j;
|
||||
Map<T> nh = {};
|
||||
Map<T> nh = {0};
|
||||
map_init(&nh, h->hashes.allocator);
|
||||
array_resize(&nh.hashes, new_count);
|
||||
array_reserve(&nh.entries, h->entries.count);
|
||||
|
||||
@@ -615,7 +615,7 @@ extern "C++" {
|
||||
//
|
||||
// NOTE: C++11 (and above) only!
|
||||
//
|
||||
#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L))
|
||||
#if !defined(GB_NO_DEFER) && defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L))
|
||||
extern "C++" {
|
||||
// NOTE(bill): Stupid fucking templates
|
||||
template <typename T> struct gbRemoveReference { typedef T Type; };
|
||||
|
||||
73
src/main.cpp
73
src/main.cpp
@@ -16,12 +16,13 @@
|
||||
// NOTE(bill): `name` is used in debugging and profiling modes
|
||||
i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
|
||||
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
|
||||
PROCESS_INFORMATION pi = {};
|
||||
char cmd_line[4096] = {};
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
char cmd_line[4096] = {0};
|
||||
isize cmd_len;
|
||||
va_list va;
|
||||
gbTempArenaMemory tmp;
|
||||
String16 cmd;
|
||||
i32 exit_code = 0;
|
||||
|
||||
start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
start_info.wShowWindow = SW_SHOW;
|
||||
@@ -35,57 +36,55 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
|
||||
// gb_printf("%.*s\n", cast(int)cmd_len, cmd_line);
|
||||
|
||||
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
cmd = string_to_string16(string_buffer_allocator, make_string(cast(u8 *)cmd_line, cmd_len-1));
|
||||
|
||||
if (CreateProcessW(NULL, cmd.text,
|
||||
NULL, NULL, true, 0, NULL, NULL,
|
||||
&start_info, &pi)) {
|
||||
DWORD exit_code = 0;
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
return cast(i32)exit_code;
|
||||
} else {
|
||||
// NOTE(bill): failed to create process
|
||||
gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line);
|
||||
return -1;
|
||||
exit_code = -1;
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
enum ArchKind {
|
||||
typedef enum {
|
||||
ArchKind_x64,
|
||||
ArchKind_x86,
|
||||
};
|
||||
} ArchKind;
|
||||
|
||||
struct ArchData {
|
||||
typedef struct {
|
||||
BaseTypeSizes sizes;
|
||||
String llc_flags;
|
||||
String link_flags;
|
||||
};
|
||||
} ArchData;
|
||||
|
||||
ArchData make_arch_data(ArchKind kind) {
|
||||
ArchData data = {};
|
||||
ArchData data = {0};
|
||||
|
||||
switch (kind) {
|
||||
case ArchKind_x64:
|
||||
default:
|
||||
data.sizes.word_size = 8;
|
||||
data.sizes.max_align = 16;
|
||||
data.llc_flags = make_string("-march=x86-64 ");
|
||||
data.link_flags = make_string("/machine:x64 ");
|
||||
data.llc_flags = str_lit("-march=x86-64 ");
|
||||
data.link_flags = str_lit("/machine:x64 ");
|
||||
break;
|
||||
|
||||
case ArchKind_x86:
|
||||
data.sizes.word_size = 4;
|
||||
data.sizes.max_align = 8;
|
||||
data.llc_flags = make_string("-march=x86 ");
|
||||
data.link_flags = make_string("/machine:x86 ");
|
||||
data.llc_flags = str_lit("-march=x86 ");
|
||||
data.link_flags = str_lit("/machine:x86 ");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -110,9 +109,9 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
prof_init();
|
||||
|
||||
Timings timings = {};
|
||||
timings_init(&timings, make_string("Total Time"), 128);
|
||||
defer (timings_destroy(&timings));
|
||||
Timings timings = {0};
|
||||
timings_init(&timings, str_lit("Total Time"), 128);
|
||||
// defer (timings_destroy(&timings));
|
||||
|
||||
#if 1
|
||||
init_string_buffer_memory();
|
||||
@@ -124,13 +123,13 @@ int main(int argc, char **argv) {
|
||||
|
||||
char *init_filename = NULL;
|
||||
b32 run_output = false;
|
||||
String arg1 = make_string(argv[1]);
|
||||
if (arg1 == "run") {
|
||||
String arg1 = make_string_c(argv[1]);
|
||||
if (str_eq(arg1, str_lit("run"))) {
|
||||
run_output = true;
|
||||
init_filename = argv[2];
|
||||
} else if (arg1 == "build") {
|
||||
} else if (str_eq(arg1, str_lit("build"))) {
|
||||
init_filename = argv[2];
|
||||
} else if (arg1 == "version") {
|
||||
} else if (str_eq(arg1, str_lit("version"))) {
|
||||
gb_printf("%s version %s", argv[0], VERSION_STRING);
|
||||
return 0;
|
||||
} else {
|
||||
@@ -140,7 +139,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// TODO(bill): prevent compiling without a linker
|
||||
|
||||
timings_start_section(&timings, make_string("parse files"));
|
||||
timings_start_section(&timings, str_lit("parse files"));
|
||||
|
||||
Parser parser = {0};
|
||||
if (!init_parser(&parser)) {
|
||||
@@ -154,9 +153,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
|
||||
#if 1
|
||||
timings_start_section(&timings, make_string("type check"));
|
||||
timings_start_section(&timings, str_lit("type check"));
|
||||
|
||||
Checker checker = {};
|
||||
Checker checker = {0};
|
||||
ArchData arch_data = make_arch_data(ArchKind_x64);
|
||||
|
||||
init_checker(&checker, &parser, arch_data.sizes);
|
||||
@@ -168,25 +167,25 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
#if 1
|
||||
|
||||
ssaGen ssa = {};
|
||||
ssaGen ssa = {0};
|
||||
if (!ssa_gen_init(&ssa, &checker)) {
|
||||
return 1;
|
||||
}
|
||||
// defer (ssa_gen_destroy(&ssa));
|
||||
|
||||
timings_start_section(&timings, make_string("ssa gen"));
|
||||
timings_start_section(&timings, str_lit("ssa gen"));
|
||||
ssa_gen_tree(&ssa);
|
||||
|
||||
timings_start_section(&timings, make_string("ssa opt"));
|
||||
timings_start_section(&timings, str_lit("ssa opt"));
|
||||
ssa_opt_tree(&ssa);
|
||||
|
||||
timings_start_section(&timings, make_string("ssa print"));
|
||||
timings_start_section(&timings, str_lit("ssa print"));
|
||||
ssa_print_llvm_ir(&ssa);
|
||||
|
||||
// prof_print_all();
|
||||
|
||||
#if 1
|
||||
timings_start_section(&timings, make_string("llvm-opt"));
|
||||
timings_start_section(&timings, str_lit("llvm-opt"));
|
||||
|
||||
char const *output_name = ssa.output_file.filename;
|
||||
isize base_name_len = gb_path_extension(output_name)-1 - output_name;
|
||||
@@ -213,7 +212,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
#if 1
|
||||
timings_start_section(&timings, make_string("llvm-llc"));
|
||||
timings_start_section(&timings, str_lit("llvm-llc"));
|
||||
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
||||
exit_code = win32_exec_command_line_app("llvm-llc",
|
||||
"%.*sbin/llc %.*s.bc -filetype=obj -O%d "
|
||||
@@ -228,11 +227,11 @@ int main(int argc, char **argv) {
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
timings_start_section(&timings, make_string("msvc-link"));
|
||||
timings_start_section(&timings, str_lit("msvc-link"));
|
||||
|
||||
gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib");
|
||||
// defer (gb_string_free(lib_str));
|
||||
char lib_str_buf[1024] = {};
|
||||
char lib_str_buf[1024] = {0};
|
||||
for_array(i, parser.foreign_libraries) {
|
||||
String lib = parser.foreign_libraries[i];
|
||||
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
|
||||
@@ -243,7 +242,7 @@ int main(int argc, char **argv) {
|
||||
exit_code = win32_exec_command_line_app("msvc-link",
|
||||
"link %.*s.obj -OUT:%.*s.exe %s "
|
||||
"/defaultlib:libcmt "
|
||||
"/nologo /incremental:no /opt:ref /subsystem:console /debug "
|
||||
"/nologo /incremental:no /opt:ref /subsystem:console "
|
||||
" %.*s "
|
||||
"",
|
||||
LIT(output), LIT(output),
|
||||
|
||||
100
src/parser.cpp
100
src/parser.cpp
@@ -1133,7 +1133,7 @@ AstNode *parse_identifier(AstFile *f) {
|
||||
if (token.kind == Token_Identifier) {
|
||||
next_token(f);
|
||||
} else {
|
||||
token.string = make_string("_");
|
||||
token.string = str_lit("_");
|
||||
expect_token(f, Token_Identifier);
|
||||
}
|
||||
return make_ident(f, token);
|
||||
@@ -1274,11 +1274,11 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
|
||||
String tag_name = te->name.string;
|
||||
|
||||
#define ELSE_IF_ADD_TAG(name) \
|
||||
else if (tag_name == #name) { \
|
||||
else if (str_eq(tag_name, str_lit(#name))) { \
|
||||
check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \
|
||||
}
|
||||
|
||||
if (tag_name == "foreign") {
|
||||
if (str_eq(tag_name, str_lit("foreign"))) {
|
||||
check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name);
|
||||
if (f->curr_token.kind == Token_String) {
|
||||
*foreign_name = f->curr_token.string;
|
||||
@@ -1289,7 +1289,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n
|
||||
|
||||
next_token(f);
|
||||
}
|
||||
} else if (tag_name == "link_name") {
|
||||
} else if (str_eq(tag_name, str_lit("link_name"))) {
|
||||
check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name);
|
||||
if (f->curr_token.kind == Token_String) {
|
||||
*link_name = f->curr_token.string;
|
||||
@@ -1372,7 +1372,7 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
case Token_Hash: {
|
||||
Token token = expect_token(f, Token_Hash);
|
||||
Token name = expect_token(f, Token_Identifier);
|
||||
if (name.string == "rune") {
|
||||
if (str_eq(name.string, str_lit("rune"))) {
|
||||
if (f->curr_token.kind == Token_String) {
|
||||
Token *s = &f->curr_token;
|
||||
|
||||
@@ -1384,19 +1384,19 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
expect_token(f, Token_String);
|
||||
}
|
||||
operand = parse_operand(f, lhs);
|
||||
} else if (name.string == "file") {
|
||||
} else if (str_eq(name.string, str_lit("file"))) {
|
||||
Token token = name;
|
||||
token.kind = Token_String;
|
||||
token.string = token.pos.file;
|
||||
return make_basic_lit(f, token);
|
||||
} else if (name.string == "line") {
|
||||
} else if (str_eq(name.string, str_lit("line"))) {
|
||||
Token token = name;
|
||||
token.kind = Token_Integer;
|
||||
char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20);
|
||||
gb_i64_to_str(token.pos.line, str, 10);
|
||||
token.string = make_string(str);
|
||||
token.string = make_string_c(str);
|
||||
return make_basic_lit(f, token);
|
||||
} else if (name.string == "run") {
|
||||
} else if (str_eq(name.string, str_lit("run"))) {
|
||||
AstNode *expr = parse_expr(f, false);
|
||||
operand = make_run_expr(f, token, name, expr);
|
||||
if (unparen_expr(expr)->kind != AstNode_CallExpr) {
|
||||
@@ -1415,7 +1415,6 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
AstNode *curr_proc = f->curr_proc;
|
||||
AstNode *type = parse_proc_type(f);
|
||||
f->curr_proc = type;
|
||||
defer (f->curr_proc = curr_proc);
|
||||
|
||||
u64 tags = 0;
|
||||
String foreign_name = {};
|
||||
@@ -1428,17 +1427,17 @@ AstNode *parse_operand(AstFile *f, b32 lhs) {
|
||||
syntax_error(f->curr_token, "#link_name cannot be applied to procedure literals");
|
||||
}
|
||||
|
||||
if (f->curr_token.kind != Token_OpenBrace) {
|
||||
return type;
|
||||
} else {
|
||||
if (f->curr_token.kind == Token_OpenBrace) {
|
||||
AstNode *body;
|
||||
|
||||
f->expr_level++;
|
||||
body = parse_body(f);
|
||||
f->expr_level--;
|
||||
|
||||
return make_proc_lit(f, type, body, tags);
|
||||
type = make_proc_lit(f, type, body, tags);
|
||||
}
|
||||
f->curr_proc = curr_proc;
|
||||
return type;
|
||||
}
|
||||
|
||||
default: {
|
||||
@@ -2087,12 +2086,12 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
||||
b32 is_ordered = false;
|
||||
while (allow_token(f, Token_Hash)) {
|
||||
Token tag = expect_token_after(f, Token_Identifier, "`#`");
|
||||
if (tag.string == "packed") {
|
||||
if (str_eq(tag.string, str_lit("packed"))) {
|
||||
if (is_packed) {
|
||||
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
|
||||
}
|
||||
is_packed = true;
|
||||
} else if (tag.string == "ordered") {
|
||||
} else if (str_eq(tag.string, str_lit("ordered"))) {
|
||||
if (is_ordered) {
|
||||
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
|
||||
}
|
||||
@@ -2264,7 +2263,6 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
|
||||
|
||||
AstNode *curr_proc = f->curr_proc;
|
||||
f->curr_proc = proc_type;
|
||||
defer (f->curr_proc = curr_proc);
|
||||
|
||||
if (f->curr_token.kind == Token_OpenBrace) {
|
||||
if ((tags & ProcTag_foreign) != 0) {
|
||||
@@ -2273,6 +2271,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
|
||||
body = parse_body(f);
|
||||
}
|
||||
|
||||
f->curr_proc = curr_proc;
|
||||
return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
|
||||
}
|
||||
|
||||
@@ -2285,7 +2284,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
|
||||
if (name->kind == AstNode_Ident) {
|
||||
String n = name->Ident.string;
|
||||
// NOTE(bill): Check for reserved identifiers
|
||||
if (n == "context") {
|
||||
if (str_eq(n, str_lit("context"))) {
|
||||
syntax_error(ast_node_token(name), "`context` is a reserved identifier");
|
||||
break;
|
||||
}
|
||||
@@ -2399,7 +2398,7 @@ AstNode *parse_if_stmt(AstFile *f) {
|
||||
if (allow_token(f, Token_Semicolon)) {
|
||||
cond = parse_expr(f, false);
|
||||
} else {
|
||||
cond = convert_stmt_to_expr(f, init, make_string("boolean expression"));
|
||||
cond = convert_stmt_to_expr(f, init, str_lit("boolean expression"));
|
||||
init = NULL;
|
||||
}
|
||||
}
|
||||
@@ -2489,7 +2488,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
||||
}
|
||||
body = parse_block_stmt(f);
|
||||
|
||||
cond = convert_stmt_to_expr(f, cond, make_string("boolean expression"));
|
||||
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
|
||||
|
||||
return make_for_stmt(f, token, init, cond, end, body);
|
||||
}
|
||||
@@ -2559,7 +2558,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
close = expect_token(f, Token_CloseBrace);
|
||||
body = make_block_stmt(f, list, open, close);
|
||||
|
||||
tag = convert_stmt_to_expr(f, tag, make_string("type match expression"));
|
||||
tag = convert_stmt_to_expr(f, tag, str_lit("type match expression"));
|
||||
return make_type_match_stmt(f, token, tag, var, body);
|
||||
} else {
|
||||
if (f->curr_token.kind != Token_OpenBrace) {
|
||||
@@ -2591,7 +2590,7 @@ AstNode *parse_match_stmt(AstFile *f) {
|
||||
|
||||
body = make_block_stmt(f, list, open, close);
|
||||
|
||||
tag = convert_stmt_to_expr(f, tag, make_string("match expression"));
|
||||
tag = convert_stmt_to_expr(f, tag, str_lit("match expression"));
|
||||
return make_match_stmt(f, token, init, tag, body);
|
||||
}
|
||||
}
|
||||
@@ -2747,14 +2746,14 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
case Token_Hash: {
|
||||
s = parse_tag_stmt(f, NULL);
|
||||
String tag = s->TagStmt.name.string;
|
||||
if (tag == "shared_global_scope") {
|
||||
if (str_eq(tag, str_lit("shared_global_scope"))) {
|
||||
if (f->curr_proc == NULL) {
|
||||
f->is_global_scope = true;
|
||||
return make_empty_stmt(f, f->curr_token);
|
||||
}
|
||||
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
|
||||
return make_bad_decl(f, token, f->curr_token);
|
||||
} else if (tag == "import") {
|
||||
} else if (str_eq(tag, str_lit("import"))) {
|
||||
// TODO(bill): better error messages
|
||||
Token import_name = {};
|
||||
Token file_path = expect_token_after(f, Token_String, "#import");
|
||||
@@ -2768,7 +2767,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
|
||||
}
|
||||
|
||||
if (import_name.string == "_") {
|
||||
if (str_eq(import_name.string, str_lit("_"))) {
|
||||
syntax_error(token, "Illegal import name: `_`");
|
||||
return make_bad_decl(f, token, f->curr_token);
|
||||
}
|
||||
@@ -2779,32 +2778,32 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
}
|
||||
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
} else if (tag == "load") {
|
||||
} else if (str_eq(tag, str_lit("load"))) {
|
||||
// TODO(bill): better error messages
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
Token import_name = file_path;
|
||||
import_name.string = make_string(".");
|
||||
import_name.string = str_lit(".");
|
||||
|
||||
if (f->curr_proc == NULL) {
|
||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
|
||||
}
|
||||
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
} else if (tag == "foreign_system_library") {
|
||||
} else if (str_eq(tag, str_lit("foreign_system_library"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
if (f->curr_proc == NULL) {
|
||||
return make_foreign_library(f, s->TagStmt.token, file_path, true);
|
||||
}
|
||||
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
} else if (tag == "foreign_library") {
|
||||
} else if (str_eq(tag, str_lit("foreign_library"))) {
|
||||
Token file_path = expect_token(f, Token_String);
|
||||
if (f->curr_proc == NULL) {
|
||||
return make_foreign_library(f, s->TagStmt.token, file_path, false);
|
||||
}
|
||||
syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope");
|
||||
return make_bad_decl(f, token, file_path);
|
||||
} else if (tag == "thread_local") {
|
||||
} else if (str_eq(tag, str_lit("thread_local"))) {
|
||||
AstNode *var_decl = parse_simple_stmt(f);
|
||||
if (var_decl->kind != AstNode_VarDecl) {
|
||||
syntax_error(token, "#thread_local may only be applied to variable declarations");
|
||||
@@ -2816,14 +2815,14 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
}
|
||||
var_decl->VarDecl.tags |= VarDeclTag_thread_local;
|
||||
return var_decl;
|
||||
} else if (tag == "bounds_check") {
|
||||
} else if (str_eq(tag, str_lit("bounds_check"))) {
|
||||
s = parse_stmt(f);
|
||||
s->stmt_state_flags |= StmtStateFlag_bounds_check;
|
||||
if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||
syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together");
|
||||
}
|
||||
return s;
|
||||
} else if (tag == "no_bounds_check") {
|
||||
} else if (str_eq(tag, str_lit("no_bounds_check"))) {
|
||||
s = parse_stmt(f);
|
||||
s->stmt_state_flags |= StmtStateFlag_no_bounds_check;
|
||||
if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) {
|
||||
@@ -2870,7 +2869,7 @@ AstNodeArray parse_stmt_list(AstFile *f) {
|
||||
|
||||
|
||||
ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
||||
if (!string_has_extension(fullpath, make_string("odin"))) {
|
||||
if (!string_has_extension(fullpath, str_lit("odin"))) {
|
||||
return ParseFile_WrongExtension;
|
||||
}
|
||||
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
||||
@@ -2951,11 +2950,10 @@ void destroy_parser(Parser *p) {
|
||||
// NOTE(bill): Returns true if it's added
|
||||
b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
||||
gb_mutex_lock(&p->mutex);
|
||||
defer (gb_mutex_unlock(&p->mutex));
|
||||
|
||||
for_array(i, p->imports) {
|
||||
String import = p->imports[i].path;
|
||||
if (import == path) {
|
||||
if (str_eq(import, path)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2965,52 +2963,59 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) {
|
||||
item.rel_path = rel_path;
|
||||
item.pos = pos;
|
||||
array_add(&p->imports, item);
|
||||
|
||||
gb_mutex_unlock(&p->mutex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
|
||||
String res = {};
|
||||
isize str_len = base_dir.len+path.len;
|
||||
|
||||
u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(heap_allocator(), str));
|
||||
|
||||
isize i = 0;
|
||||
gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len;
|
||||
gb_memmove(str+i, path.text, path.len);
|
||||
str[str_len] = '\0';
|
||||
return path_to_fullpath(a, make_string(str, str_len));
|
||||
res = path_to_fullpath(a, make_string(str, str_len));
|
||||
gb_free(heap_allocator(), str);
|
||||
return res;
|
||||
}
|
||||
|
||||
String get_fullpath_core(gbAllocator a, String path) {
|
||||
String module_dir = get_module_dir();
|
||||
String res = {};
|
||||
|
||||
char core[] = "core/";
|
||||
isize core_len = gb_size_of(core)-1;
|
||||
|
||||
isize str_len = module_dir.len + core_len + path.len;
|
||||
u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
|
||||
defer (gb_free(heap_allocator(), str));
|
||||
|
||||
gb_memmove(str, module_dir.text, module_dir.len);
|
||||
gb_memmove(str+module_dir.len, core, core_len);
|
||||
gb_memmove(str+module_dir.len+core_len, path.text, path.len);
|
||||
str[str_len] = '\0';
|
||||
|
||||
return path_to_fullpath(a, make_string(str, str_len));
|
||||
res = path_to_fullpath(a, make_string(str, str_len));
|
||||
gb_free(heap_allocator(), str);
|
||||
return res;
|
||||
}
|
||||
|
||||
// NOTE(bill): Returns true if it's added
|
||||
b32 try_add_foreign_library_path(Parser *p, String import_file) {
|
||||
gb_mutex_lock(&p->mutex);
|
||||
defer (gb_mutex_unlock(&p->mutex));
|
||||
|
||||
for_array(i, p->foreign_libraries) {
|
||||
String import = p->foreign_libraries[i];
|
||||
if (import == import_file) {
|
||||
if (str_eq(import, import_file)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
array_add(&p->foreign_libraries, import_file);
|
||||
gb_mutex_unlock(&p->mutex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3064,7 +3069,7 @@ String get_filepath_extension(String path) {
|
||||
|
||||
if (c == '.') {
|
||||
if (seen_slash) {
|
||||
return make_string("");
|
||||
return str_lit("");
|
||||
}
|
||||
|
||||
dot = i;
|
||||
@@ -3166,19 +3171,19 @@ void parse_file(Parser *p, AstFile *f) {
|
||||
|
||||
ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
char *fullpath_str = gb_path_get_full_name(heap_allocator(), init_filename);
|
||||
String init_fullpath = make_string(fullpath_str);
|
||||
String init_fullpath = make_string_c(fullpath_str);
|
||||
TokenPos init_pos = {};
|
||||
ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos};
|
||||
array_add(&p->imports, init_imported_file);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
{
|
||||
String s = get_fullpath_core(heap_allocator(), make_string("_preload.odin"));
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("_preload.odin"));
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
}
|
||||
{
|
||||
String s = get_fullpath_core(heap_allocator(), make_string("_soft_numbers.odin"));
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("_soft_numbers.odin"));
|
||||
ImportedFile runtime_file = {s, s, init_pos};
|
||||
array_add(&p->imports, runtime_file);
|
||||
}
|
||||
@@ -3196,7 +3201,6 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column);
|
||||
}
|
||||
gb_printf_err("Failed to parse file: %.*s\n\t", LIT(import_rel_path));
|
||||
defer (gb_printf_err("\n"));
|
||||
switch (err) {
|
||||
case ParseFile_WrongExtension:
|
||||
gb_printf_err("Invalid file extension: File must have the extension `.odin`");
|
||||
@@ -3217,16 +3221,16 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
|
||||
gb_printf_err("Invalid token found in file");
|
||||
break;
|
||||
}
|
||||
gb_printf_err("\n");
|
||||
return err;
|
||||
}
|
||||
parse_file(p, &file);
|
||||
|
||||
{
|
||||
gb_mutex_lock(&p->mutex);
|
||||
defer (gb_mutex_unlock(&p->mutex));
|
||||
|
||||
file.id = p->files.count;
|
||||
array_add(&p->files, file);
|
||||
gb_mutex_unlock(&p->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
148
src/ssa.cpp
148
src/ssa.cpp
@@ -1085,7 +1085,7 @@ ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) {
|
||||
}
|
||||
|
||||
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block);
|
||||
v->Block.label = make_string(label);
|
||||
v->Block.label = make_string_c(label);
|
||||
v->Block.node = node;
|
||||
v->Block.scope = scope;
|
||||
v->Block.parent = proc;
|
||||
@@ -1346,7 +1346,7 @@ ssaValue *ssa_emit_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize
|
||||
}
|
||||
|
||||
ssaValue *ssa_emit_global_call(ssaProcedure *proc, char *name_, ssaValue **args, isize arg_count) {
|
||||
String name = make_string(name_);
|
||||
String name = make_string_c(name_);
|
||||
ssaValue **found = map_get(&proc->module->members, hash_string(name));
|
||||
GB_ASSERT_MSG(found != NULL, "%.*s", LIT(name));
|
||||
ssaValue *gp = *found;
|
||||
@@ -1425,7 +1425,7 @@ void ssa_emit_if(ssaProcedure *proc, ssaValue *cond, ssaBlock *true_block, ssaBl
|
||||
}
|
||||
|
||||
void ssa_emit_startup_runtime(ssaProcedure *proc) {
|
||||
GB_ASSERT(proc->parent == NULL && proc->name == "main");
|
||||
GB_ASSERT(proc->parent == NULL && str_eq(proc->name, str_lit("main")));
|
||||
ssa_emit(proc, ssa_alloc_instr(proc, ssaInstr_StartupRuntime));
|
||||
}
|
||||
|
||||
@@ -1896,7 +1896,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return make_string("");
|
||||
return str_lit("");
|
||||
}
|
||||
|
||||
ssaValue *ssa_emit_bitcast(ssaProcedure *proc, ssaValue *data, Type *type) {
|
||||
@@ -2017,7 +2017,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
for (isize i = 0; i < dst->Record.field_count; i++) {
|
||||
Entity *f = dst->Record.fields[i];
|
||||
if (are_types_identical(f->type, src_type)) {
|
||||
ssa_emit_comment(proc, make_string("union - child to parent"));
|
||||
ssa_emit_comment(proc, str_lit("union - child to parent"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
ssaValue *parent = ssa_add_local_generated(proc, t);
|
||||
ssaValue *tag = ssa_make_const_int(allocator, i);
|
||||
@@ -2047,7 +2047,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
// NOTE(bill): It can be casted
|
||||
Selection sel = lookup_field(proc->module->allocator, sb, field_name, false);
|
||||
if (sel.entity != NULL) {
|
||||
ssa_emit_comment(proc, make_string("cast - polymorphism"));
|
||||
ssa_emit_comment(proc, str_lit("cast - polymorphism"));
|
||||
if (src_is_ptr) {
|
||||
value = ssa_emit_load(proc, value);
|
||||
}
|
||||
@@ -2230,7 +2230,6 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) {
|
||||
String field_name = check_down_cast_name(t, type_deref(ssa_type(value)));
|
||||
GB_ASSERT(field_name.len > 0);
|
||||
Selection sel = lookup_field(proc->module->allocator, t, field_name, false);
|
||||
Type *t_u8_ptr = make_type_pointer(allocator, t_u8);
|
||||
ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr);
|
||||
|
||||
i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel);
|
||||
@@ -2355,7 +2354,7 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
|
||||
}
|
||||
|
||||
ssaValue *ssa_type_info(ssaProcedure *proc, Type *type) {
|
||||
ssaValue **found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
|
||||
ssaValue **found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
ssaValue *type_info_data = *found;
|
||||
CheckerInfo *info = proc->module->info;
|
||||
@@ -2558,7 +2557,7 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) {
|
||||
ssa_emit_jump(proc, b);
|
||||
}
|
||||
proc->curr_block = b;
|
||||
ssa_emit_comment(proc, make_string("defer"));
|
||||
ssa_emit_comment(proc, str_lit("defer"));
|
||||
if (d.kind == ssaDefer_Node) {
|
||||
ssa_build_stmt(proc, d.stmt);
|
||||
} else if (d.kind == ssaDefer_Instr) {
|
||||
@@ -2700,19 +2699,19 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
return ssa_emit_logical_binary_expr(proc, expr);
|
||||
|
||||
case Token_as:
|
||||
ssa_emit_comment(proc, make_string("cast - as"));
|
||||
ssa_emit_comment(proc, str_lit("cast - as"));
|
||||
return ssa_emit_conv(proc, left, type);
|
||||
|
||||
case Token_transmute:
|
||||
ssa_emit_comment(proc, make_string("cast - transmute"));
|
||||
ssa_emit_comment(proc, str_lit("cast - transmute"));
|
||||
return ssa_emit_transmute(proc, left, type);
|
||||
|
||||
case Token_down_cast:
|
||||
ssa_emit_comment(proc, make_string("cast - down_cast"));
|
||||
ssa_emit_comment(proc, str_lit("cast - down_cast"));
|
||||
return ssa_emit_down_cast(proc, left, type);
|
||||
|
||||
case Token_union_cast:
|
||||
ssa_emit_comment(proc, make_string("cast - union_cast"));
|
||||
ssa_emit_comment(proc, str_lit("cast - union_cast"));
|
||||
return ssa_emit_union_cast(proc, left, type);
|
||||
|
||||
default:
|
||||
@@ -2764,7 +2763,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_new: {
|
||||
ssa_emit_comment(proc, make_string("new"));
|
||||
ssa_emit_comment(proc, str_lit("new"));
|
||||
// new :: proc(Type) -> ^Type
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
|
||||
@@ -2783,7 +2782,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_new_slice: {
|
||||
ssa_emit_comment(proc, make_string("new_slice"));
|
||||
ssa_emit_comment(proc, str_lit("new_slice"));
|
||||
// new_slice :: proc(Type, len: int[, cap: int]) -> ^Type
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
|
||||
@@ -2825,7 +2824,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_assert: {
|
||||
ssa_emit_comment(proc, make_string("assert"));
|
||||
ssa_emit_comment(proc, str_lit("assert"));
|
||||
ssaValue *cond = ssa_build_expr(proc, ce->args[0]);
|
||||
GB_ASSERT(is_type_boolean(ssa_type(cond)));
|
||||
|
||||
@@ -2840,11 +2839,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
Token token = ast_node_token(ce->args[0]);
|
||||
TokenPos pos = token.pos;
|
||||
gbString expr = expr_to_string(ce->args[0]);
|
||||
defer (gb_string_free(expr));
|
||||
isize expr_len = gb_string_length(expr);
|
||||
String expr_str = {};
|
||||
expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1);
|
||||
expr_str.len = expr_len;
|
||||
gb_string_free(expr);
|
||||
|
||||
|
||||
ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4);
|
||||
args[0] = ssa_make_const_string(proc->module->allocator, pos.file);
|
||||
@@ -2860,7 +2860,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_panic: {
|
||||
ssa_emit_comment(proc, make_string("panic"));
|
||||
ssa_emit_comment(proc, str_lit("panic"));
|
||||
ssaValue *msg = ssa_build_expr(proc, ce->args[0]);
|
||||
GB_ASSERT(is_type_string(ssa_type(msg)));
|
||||
|
||||
@@ -2879,7 +2879,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
|
||||
case BuiltinProc_copy: {
|
||||
ssa_emit_comment(proc, make_string("copy"));
|
||||
ssa_emit_comment(proc, str_lit("copy"));
|
||||
// copy :: proc(dst, src: []Type) -> int
|
||||
AstNode *dst_node = ce->args[0];
|
||||
AstNode *src_node = ce->args[1];
|
||||
@@ -2913,7 +2913,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
return len;
|
||||
} break;
|
||||
case BuiltinProc_append: {
|
||||
ssa_emit_comment(proc, make_string("append"));
|
||||
ssa_emit_comment(proc, str_lit("append"));
|
||||
// append :: proc(s: ^[]Type, item: Type) -> bool
|
||||
AstNode *sptr_node = ce->args[0];
|
||||
AstNode *item_node = ce->args[1];
|
||||
@@ -2970,7 +2970,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_swizzle: {
|
||||
ssa_emit_comment(proc, make_string("swizzle"));
|
||||
ssa_emit_comment(proc, str_lit("swizzle"));
|
||||
ssaValue *vector = ssa_build_expr(proc, ce->args[0]);
|
||||
isize index_count = ce->args.count-1;
|
||||
if (index_count == 0) {
|
||||
@@ -2993,14 +2993,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
#if 0
|
||||
case BuiltinProc_ptr_offset: {
|
||||
ssa_emit_comment(proc, make_string("ptr_offset"));
|
||||
ssa_emit_comment(proc, str_lit("ptr_offset"));
|
||||
ssaValue *ptr = ssa_build_expr(proc, ce->args[0]);
|
||||
ssaValue *offset = ssa_build_expr(proc, ce->args[1]);
|
||||
return ssa_emit_ptr_offset(proc, ptr, offset);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_ptr_sub: {
|
||||
ssa_emit_comment(proc, make_string("ptr_sub"));
|
||||
ssa_emit_comment(proc, str_lit("ptr_sub"));
|
||||
ssaValue *ptr_a = ssa_build_expr(proc, ce->args[0]);
|
||||
ssaValue *ptr_b = ssa_build_expr(proc, ce->args[1]);
|
||||
Type *ptr_type = base_type(ssa_type(ptr_a));
|
||||
@@ -3018,7 +3018,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
#endif
|
||||
|
||||
case BuiltinProc_slice_ptr: {
|
||||
ssa_emit_comment(proc, make_string("slice_ptr"));
|
||||
ssa_emit_comment(proc, str_lit("slice_ptr"));
|
||||
ssaValue *ptr = ssa_build_expr(proc, ce->args[0]);
|
||||
ssaValue *len = ssa_build_expr(proc, ce->args[1]);
|
||||
ssaValue *cap = len;
|
||||
@@ -3040,7 +3040,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_min: {
|
||||
ssa_emit_comment(proc, make_string("min"));
|
||||
ssa_emit_comment(proc, str_lit("min"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||
ssaValue *y = ssa_build_expr(proc, ce->args[1]);
|
||||
Type *t = base_type(ssa_type(x));
|
||||
@@ -3049,7 +3049,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_max: {
|
||||
ssa_emit_comment(proc, make_string("max"));
|
||||
ssa_emit_comment(proc, str_lit("max"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||
ssaValue *y = ssa_build_expr(proc, ce->args[1]);
|
||||
Type *t = base_type(ssa_type(x));
|
||||
@@ -3058,7 +3058,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_abs: {
|
||||
ssa_emit_comment(proc, make_string("abs"));
|
||||
ssa_emit_comment(proc, str_lit("abs"));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||
@@ -3099,7 +3099,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
} break;
|
||||
|
||||
case BuiltinProc_enum_to_string: {
|
||||
ssa_emit_comment(proc, make_string("enum_to_string"));
|
||||
ssa_emit_comment(proc, str_lit("enum_to_string"));
|
||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||
Type *t = ssa_type(x);
|
||||
ssaValue *ti = ssa_type_info(proc, t);
|
||||
@@ -3173,7 +3173,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
}
|
||||
|
||||
if (variadic && !vari_expand) {
|
||||
ssa_emit_comment(proc, make_string("variadic call argument generation"));
|
||||
ssa_emit_comment(proc, str_lit("variadic call argument generation"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
Type *slice_type = pt->variables[type->param_count-1]->type;
|
||||
Type *elem_type = base_type(slice_type)->Slice.elem;
|
||||
@@ -3301,7 +3301,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SelectorExpr, expr);
|
||||
ssa_emit_comment(proc, make_string("SelectorExpr"));
|
||||
ssa_emit_comment(proc, str_lit("SelectorExpr"));
|
||||
String selector = unparen_expr(se->selector)->Ident.string;
|
||||
Type *type = base_type(type_of_expr(proc->module->info, se->expr));
|
||||
|
||||
@@ -3335,7 +3335,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_ast_node(be, BinaryExpr, expr);
|
||||
switch (be->op.kind) {
|
||||
case Token_as: {
|
||||
ssa_emit_comment(proc, make_string("Cast - as"));
|
||||
ssa_emit_comment(proc, str_lit("Cast - as"));
|
||||
// NOTE(bill): Needed for dereference of pointer conversion
|
||||
Type *type = type_of_expr(proc->module->info, expr);
|
||||
ssaValue *v = ssa_add_local_generated(proc, type);
|
||||
@@ -3343,7 +3343,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
return ssa_make_addr(v, expr);
|
||||
}
|
||||
case Token_transmute: {
|
||||
ssa_emit_comment(proc, make_string("Cast - transmute"));
|
||||
ssa_emit_comment(proc, str_lit("Cast - transmute"));
|
||||
// NOTE(bill): Needed for dereference of pointer conversion
|
||||
Type *type = type_of_expr(proc->module->info, expr);
|
||||
ssaValue *v = ssa_add_local_generated(proc, type);
|
||||
@@ -3357,7 +3357,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(ie, IndexExpr, expr);
|
||||
ssa_emit_comment(proc, make_string("IndexExpr"));
|
||||
ssa_emit_comment(proc, str_lit("IndexExpr"));
|
||||
Type *t = base_type(type_of_expr(proc->module->info, ie->expr));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
|
||||
@@ -3459,7 +3459,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SliceExpr, expr);
|
||||
ssa_emit_comment(proc, make_string("SliceExpr"));
|
||||
ssa_emit_comment(proc, str_lit("SliceExpr"));
|
||||
gbAllocator a = proc->module->allocator;
|
||||
ssaValue *low = v_zero;
|
||||
ssaValue *high = NULL;
|
||||
@@ -3564,7 +3564,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(de, DemaybeExpr, expr);
|
||||
ssa_emit_comment(proc, make_string("DemaybeExpr"));
|
||||
ssa_emit_comment(proc, str_lit("DemaybeExpr"));
|
||||
ssaValue *maybe = ssa_build_expr(proc, de->expr);
|
||||
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
||||
GB_ASSERT(is_type_tuple(t));
|
||||
@@ -3584,7 +3584,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
|
||||
|
||||
case_ast_node(cl, CompoundLit, expr);
|
||||
ssa_emit_comment(proc, make_string("CompoundLit"));
|
||||
ssa_emit_comment(proc, str_lit("CompoundLit"));
|
||||
Type *type = type_of_expr(proc->module->info, expr);
|
||||
Type *bt = base_type(type);
|
||||
ssaValue *v = ssa_add_local_generated(proc, type);
|
||||
@@ -3700,7 +3700,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
Type *elem_type = bt->Slice.elem;
|
||||
Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type);
|
||||
Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type);
|
||||
Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int);
|
||||
ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr));
|
||||
GB_ASSERT(slice->kind == ssaValue_ConstantSlice);
|
||||
|
||||
@@ -3807,14 +3806,13 @@ void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) {
|
||||
}
|
||||
}
|
||||
|
||||
void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node);
|
||||
void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
|
||||
|
||||
if (node->stmt_state_flags != 0) {
|
||||
u32 in = node->stmt_state_flags;
|
||||
u32 out = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = out);
|
||||
|
||||
if (in & StmtStateFlag_bounds_check) {
|
||||
out |= StmtStateFlag_bounds_check;
|
||||
@@ -3823,9 +3821,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
out |= StmtStateFlag_no_bounds_check;
|
||||
out &= ~StmtStateFlag_bounds_check;
|
||||
}
|
||||
|
||||
proc->module->stmt_state_flags = out;
|
||||
}
|
||||
|
||||
ssa_build_stmt_internal(proc, node);
|
||||
|
||||
proc->module->stmt_state_flags = prev_stmt_state_flags;
|
||||
}
|
||||
|
||||
void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
|
||||
switch (node->kind) {
|
||||
case_ast_node(bs, EmptyStmt, node);
|
||||
case_end;
|
||||
@@ -3840,7 +3845,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
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 (vd->values.count == 0) { // declared and zero-initialized
|
||||
for_array(i, vd->names) {
|
||||
@@ -3889,6 +3893,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_addr_store(proc, lvals[i], v);
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
case_end;
|
||||
|
||||
case_ast_node(pd, ProcDecl, node);
|
||||
@@ -3985,7 +3991,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(ids, IncDecStmt, node);
|
||||
ssa_emit_comment(proc, make_string("IncDecStmt"));
|
||||
ssa_emit_comment(proc, str_lit("IncDecStmt"));
|
||||
TokenKind op = ids->op.kind;
|
||||
if (op == Token_Increment) {
|
||||
op = Token_Add;
|
||||
@@ -3999,11 +4005,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(as, AssignStmt, node);
|
||||
ssa_emit_comment(proc, make_string("AssignStmt"));
|
||||
ssa_emit_comment(proc, str_lit("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: {
|
||||
@@ -4073,6 +4078,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op);
|
||||
} break;
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
case_end;
|
||||
|
||||
case_ast_node(es, ExprStmt, node);
|
||||
@@ -4087,7 +4094,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(ds, DeferStmt, node);
|
||||
ssa_emit_comment(proc, make_string("DeferStmt"));
|
||||
ssa_emit_comment(proc, str_lit("DeferStmt"));
|
||||
isize scope_index = proc->scope_index;
|
||||
if (ds->stmt->kind == AstNode_BlockStmt) {
|
||||
scope_index--;
|
||||
@@ -4096,7 +4103,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(rs, ReturnStmt, node);
|
||||
ssa_emit_comment(proc, make_string("ReturnStmt"));
|
||||
ssa_emit_comment(proc, str_lit("ReturnStmt"));
|
||||
ssaValue *v = NULL;
|
||||
auto *return_type_tuple = &proc->type->Proc.results->Tuple;
|
||||
isize return_count = proc->type->Proc.result_count;
|
||||
@@ -4107,7 +4114,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type);
|
||||
} else {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
Array<ssaValue *> results;
|
||||
array_init(&results, proc->module->tmp_allocator, return_count);
|
||||
@@ -4137,13 +4143,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
v = ssa_emit_load(proc, v);
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
ssa_emit_return(proc, v);
|
||||
|
||||
case_end;
|
||||
|
||||
case_ast_node(is, IfStmt, node);
|
||||
ssa_emit_comment(proc, make_string("IfStmt"));
|
||||
ssa_emit_comment(proc, str_lit("IfStmt"));
|
||||
if (is->init != NULL) {
|
||||
ssaBlock *init = ssa_add_block(proc, node, "if.init");
|
||||
ssa_emit_jump(proc, init);
|
||||
@@ -4179,7 +4186,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(fs, ForStmt, node);
|
||||
ssa_emit_comment(proc, make_string("ForStmt"));
|
||||
ssa_emit_comment(proc, str_lit("ForStmt"));
|
||||
if (fs->init != NULL) {
|
||||
ssaBlock *init = ssa_add_block(proc, node, "for.init");
|
||||
ssa_emit_jump(proc, init);
|
||||
@@ -4227,7 +4234,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(ms, MatchStmt, node);
|
||||
ssa_emit_comment(proc, make_string("MatchStmt"));
|
||||
ssa_emit_comment(proc, str_lit("MatchStmt"));
|
||||
if (ms->init != NULL) {
|
||||
ssa_build_stmt(proc, ms->init);
|
||||
}
|
||||
@@ -4316,7 +4323,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
|
||||
case_ast_node(ms, TypeMatchStmt, node);
|
||||
ssa_emit_comment(proc, make_string("TypeMatchStmt"));
|
||||
ssa_emit_comment(proc, str_lit("TypeMatchStmt"));
|
||||
gbAllocator allocator = proc->module->allocator;
|
||||
|
||||
ssaValue *parent = ssa_build_expr(proc, ms->tag);
|
||||
@@ -4327,7 +4334,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssaValue *tag_index = NULL;
|
||||
ssaValue *union_data = NULL;
|
||||
if (is_union_ptr) {
|
||||
ssa_emit_comment(proc, make_string("get union's tag"));
|
||||
ssa_emit_comment(proc, str_lit("get union's tag"));
|
||||
tag_index = ssa_emit_load(proc, ssa_emit_union_tag_ptr(proc, parent));
|
||||
union_data = ssa_emit_conv(proc, parent, t_rawptr);
|
||||
}
|
||||
@@ -4454,9 +4461,9 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_emit_defer_stmts(proc, ssaDeferExit_Branch, block);
|
||||
}
|
||||
switch (bs->token.kind) {
|
||||
case Token_break: ssa_emit_comment(proc, make_string("break")); break;
|
||||
case Token_continue: ssa_emit_comment(proc, make_string("continue")); break;
|
||||
case Token_fallthrough: ssa_emit_comment(proc, make_string("fallthrough")); break;
|
||||
case Token_break: ssa_emit_comment(proc, str_lit("break")); break;
|
||||
case Token_continue: ssa_emit_comment(proc, str_lit("continue")); break;
|
||||
case Token_fallthrough: ssa_emit_comment(proc, str_lit("fallthrough")); break;
|
||||
}
|
||||
ssa_emit_jump(proc, block);
|
||||
ssa_emit_unreachable(proc);
|
||||
@@ -4465,9 +4472,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
|
||||
case_ast_node(pa, PushAllocator, node);
|
||||
ssa_emit_comment(proc, make_string("PushAllocator"));
|
||||
ssa_emit_comment(proc, str_lit("PushAllocator"));
|
||||
ssa_open_scope(proc);
|
||||
defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
|
||||
|
||||
ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
|
||||
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
||||
@@ -4480,13 +4486,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
|
||||
ssa_build_stmt(proc, pa->body);
|
||||
|
||||
ssa_close_scope(proc, ssaDeferExit_Default, NULL);
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(pa, PushContext, node);
|
||||
ssa_emit_comment(proc, make_string("PushContext"));
|
||||
ssa_emit_comment(proc, str_lit("PushContext"));
|
||||
ssa_open_scope(proc);
|
||||
defer (ssa_close_scope(proc, ssaDeferExit_Default, NULL));
|
||||
|
||||
ssaValue *context_ptr = ssa_find_implicit_value_backing(proc, ImplicitValue_context);
|
||||
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
||||
@@ -4497,6 +4503,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
|
||||
|
||||
ssa_build_stmt(proc, pa->body);
|
||||
|
||||
ssa_close_scope(proc, ssaDeferExit_Default, NULL);
|
||||
case_end;
|
||||
|
||||
|
||||
@@ -4573,7 +4581,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
|
||||
|
||||
void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) {
|
||||
if (parent == NULL) {
|
||||
if (proc->name == "main") {
|
||||
if (str_eq(proc->name, str_lit("main"))) {
|
||||
ssa_emit_startup_runtime(proc);
|
||||
}
|
||||
}
|
||||
@@ -4607,13 +4615,10 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
|
||||
|
||||
if (proc->body != NULL) {
|
||||
u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
|
||||
|
||||
if (proc->tags != 0) {
|
||||
u32 in = proc->tags;
|
||||
u32 out = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = out);
|
||||
|
||||
if (in & ProcTag_bounds_check) {
|
||||
out |= StmtStateFlag_bounds_check;
|
||||
out &= ~StmtStateFlag_no_bounds_check;
|
||||
@@ -4621,6 +4626,7 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
|
||||
out |= StmtStateFlag_no_bounds_check;
|
||||
out &= ~StmtStateFlag_bounds_check;
|
||||
}
|
||||
proc->module->stmt_state_flags = out;
|
||||
}
|
||||
|
||||
|
||||
@@ -4628,6 +4634,8 @@ void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
|
||||
ssa_insert_code_before_proc(proc, parent);
|
||||
ssa_build_stmt(proc, proc->body);
|
||||
ssa_end_procedure_body(proc);
|
||||
|
||||
proc->module->stmt_state_flags = prev_stmt_state_flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4674,7 +4682,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
|
||||
{
|
||||
// Add type info data
|
||||
{
|
||||
String name = make_string(SSA_TYPE_INFO_DATA_NAME);
|
||||
String name = str_lit(SSA_TYPE_INFO_DATA_NAME);
|
||||
isize count = c->info.type_info_map.entries.count;
|
||||
Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name), make_type_array(m->allocator, t_type_info, count));
|
||||
ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
|
||||
@@ -4706,7 +4714,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
|
||||
}
|
||||
}
|
||||
|
||||
String name = make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME);
|
||||
String name = str_lit(SSA_TYPE_INFO_DATA_MEMBER_NAME);
|
||||
Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name),
|
||||
make_type_array(m->allocator, t_type_info_member, count));
|
||||
ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
|
||||
@@ -4718,7 +4726,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
|
||||
{
|
||||
ssaDebugInfo *di = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_CompileUnit);
|
||||
di->CompileUnit.file = m->info->files.entries[0].value; // Zeroth is the init file
|
||||
di->CompileUnit.producer = make_string("odin");
|
||||
di->CompileUnit.producer = str_lit("odin");
|
||||
|
||||
map_set(&m->debug_info, hash_pointer(m), di);
|
||||
}
|
||||
@@ -4830,7 +4838,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
if (e->kind == Entity_Variable) {
|
||||
global_variable_max_count++;
|
||||
} else if (e->kind == Entity_Procedure) {
|
||||
if (e->scope->is_init && name == "main") {
|
||||
if (e->scope->is_init && str_eq(name, str_lit("main"))) {
|
||||
entry_point = e;
|
||||
}
|
||||
}
|
||||
@@ -4965,7 +4973,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
|
||||
{ // Startup Runtime
|
||||
// Cleanup(bill): probably better way of doing code insertion
|
||||
String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
|
||||
String name = str_lit(SSA_STARTUP_RUNTIME_PROC_NAME);
|
||||
Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
|
||||
NULL, 0,
|
||||
NULL, 0, false);
|
||||
@@ -5016,11 +5024,11 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
ssaValue *type_info_member_data = NULL;
|
||||
|
||||
ssaValue **found = NULL;
|
||||
found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
|
||||
found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
type_info_data = *found;
|
||||
|
||||
found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
|
||||
found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
type_info_member_data = *found;
|
||||
|
||||
@@ -5421,6 +5429,6 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
|
||||
|
||||
|
||||
// m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
|
||||
// m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,6 @@ void ssa_opt_blocks(ssaProcedure *proc) {
|
||||
}
|
||||
void ssa_opt_build_referrers(ssaProcedure *proc) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
Array<ssaValue *> ops = {}; // NOTE(bill): Act as a buffer
|
||||
array_init(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
|
||||
@@ -296,6 +295,8 @@ void ssa_opt_build_referrers(ssaProcedure *proc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +371,6 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
|
||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
isize n = proc->blocks.count;
|
||||
ssaBlock **buf = gb_alloc_array(proc->module->tmp_allocator, ssaBlock *, 5*n);
|
||||
@@ -450,6 +450,8 @@ void ssa_opt_build_dom_tree(ssaProcedure *proc) {
|
||||
}
|
||||
|
||||
ssa_opt_number_dom_tree(root, 0, 0);
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
void ssa_opt_mem2reg(ssaProcedure *proc) {
|
||||
|
||||
@@ -90,7 +90,6 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
|
||||
isize buf_len = name.len + extra + 2;
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
|
||||
|
||||
@@ -117,6 +116,8 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
|
||||
}
|
||||
|
||||
ssa_file_write(f, buf, j);
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +129,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) {
|
||||
|
||||
void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope) {
|
||||
ssa_fprintf(f, "@");
|
||||
if (!global_scope && name != make_string("main")) {
|
||||
if (!global_scope && str_ne(name, str_lit("main"))) {
|
||||
ssa_fprintf(f, ".");
|
||||
}
|
||||
ssa_print_escape_string(f, name, true);
|
||||
@@ -482,7 +483,6 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
||||
ssa_fprintf(f, ">");
|
||||
} else if (is_type_struct(type)) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
ast_node(cl, CompoundLit, value.value_compound);
|
||||
|
||||
@@ -543,6 +543,8 @@ void ssa_print_exact_value(ssaFileBuffer *f, ssaModule *m, ExactValue value, Typ
|
||||
if (type->Record.struct_is_packed) {
|
||||
ssa_fprintf(f, ">");
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} else {
|
||||
ssa_fprintf(f, "zeroinitializer");
|
||||
}
|
||||
@@ -638,7 +640,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
||||
switch (instr->kind) {
|
||||
case ssaInstr_StartupRuntime: {
|
||||
ssa_fprintf(f, "call void ");
|
||||
ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), false);
|
||||
ssa_print_encoded_global(f, str_lit(SSA_STARTUP_RUNTIME_PROC_NAME), false);
|
||||
ssa_fprintf(f, "()\n");
|
||||
} break;
|
||||
|
||||
@@ -889,7 +891,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
||||
}
|
||||
|
||||
ssa_fprintf(f, " ");
|
||||
ssa_print_encoded_global(f, make_string(runtime_proc), false);
|
||||
ssa_print_encoded_global(f, make_string_c(runtime_proc), false);
|
||||
ssa_fprintf(f, "(");
|
||||
ssa_print_type(f, m, type);
|
||||
ssa_fprintf(f, " ");
|
||||
@@ -1090,7 +1092,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
||||
case ssaInstr_BoundsCheck: {
|
||||
auto *bc = &instr->BoundsCheck;
|
||||
ssa_fprintf(f, "call void ");
|
||||
ssa_print_encoded_global(f, make_string("__bounds_check_error"), false);
|
||||
ssa_print_encoded_global(f, str_lit("__bounds_check_error"), false);
|
||||
ssa_fprintf(f, "(");
|
||||
ssa_print_compound_element(f, m, make_exact_value_string(bc->pos.file), t_string);
|
||||
ssa_fprintf(f, ", ");
|
||||
@@ -1121,9 +1123,9 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
||||
auto *bc = &instr->SliceBoundsCheck;
|
||||
ssa_fprintf(f, "call void ");
|
||||
if (bc->is_substring) {
|
||||
ssa_print_encoded_global(f, make_string("__substring_expr_error"), false);
|
||||
ssa_print_encoded_global(f, str_lit("__substring_expr_error"), false);
|
||||
} else {
|
||||
ssa_print_encoded_global(f, make_string("__slice_expr_error"), false);
|
||||
ssa_print_encoded_global(f, str_lit("__slice_expr_error"), false);
|
||||
}
|
||||
|
||||
ssa_fprintf(f, "(");
|
||||
@@ -1273,21 +1275,19 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
||||
ssaModule *m = &ssa->module;
|
||||
ssaFileBuffer buf = {}, *f = &buf;
|
||||
ssa_file_buffer_init(f, &ssa->output_file);
|
||||
defer (ssa_file_buffer_destroy(f));
|
||||
|
||||
|
||||
if (m->layout.len > 0) {
|
||||
ssa_fprintf(f, "target datalayout = \"%.*s\"\n", LIT(m->layout));
|
||||
}
|
||||
|
||||
ssa_print_encoded_local(f, make_string("..string"));
|
||||
ssa_print_encoded_local(f, str_lit("..string"));
|
||||
ssa_fprintf(f, " = type {i8*, ");
|
||||
ssa_print_type(f, m, t_int);
|
||||
ssa_fprintf(f, "} ; Basic_string\n");
|
||||
ssa_print_encoded_local(f, make_string("..rawptr"));
|
||||
ssa_print_encoded_local(f, str_lit("..rawptr"));
|
||||
ssa_fprintf(f, " = type i8* ; Basic_rawptr\n");
|
||||
|
||||
ssa_print_encoded_local(f, make_string("..any"));
|
||||
ssa_print_encoded_local(f, str_lit("..any"));
|
||||
ssa_fprintf(f, " = type {");
|
||||
ssa_print_type(f, m, t_type_info_ptr);
|
||||
ssa_fprintf(f, ", ");
|
||||
@@ -1379,7 +1379,6 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
||||
auto *entry = &m->debug_info.entries[di_index];
|
||||
ssaDebugInfo *di = entry->value;
|
||||
ssa_fprintf(f, "!%d = ", di->id);
|
||||
defer (ssa_fprintf(f, "\n"));
|
||||
|
||||
switch (di->kind) {
|
||||
case ssaDebugInfo_CompileUnit: {
|
||||
@@ -1430,6 +1429,10 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
||||
ssa_fprintf(f, "}");
|
||||
break;
|
||||
}
|
||||
|
||||
ssa_fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
ssa_file_buffer_destroy(f);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
gb_global gbArena string_buffer_arena = {};
|
||||
gb_global gbAllocator string_buffer_allocator = {};
|
||||
gb_global gbArena string_buffer_arena = {0};
|
||||
gb_global gbAllocator string_buffer_allocator = {0};
|
||||
|
||||
void init_string_buffer_memory(void) {
|
||||
// NOTE(bill): This should be enough memory for file systems
|
||||
@@ -42,14 +42,12 @@ gb_inline String16 make_string16(wchar_t *text, isize len) {
|
||||
}
|
||||
|
||||
|
||||
gb_inline String make_string(char *text) {
|
||||
gb_inline String make_string_c(char *text) {
|
||||
return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
gb_inline String make_string(char const (&text)[N]) {
|
||||
return make_string(cast(u8 *)cast(void *)text, N-1);
|
||||
}
|
||||
#define str_lit(c_str) make_string(cast(u8 *)c_str, gb_size_of(c_str)-1)
|
||||
|
||||
|
||||
gb_inline b32 are_strings_equal(String a, String b) {
|
||||
if (a.len == b.len) {
|
||||
@@ -58,7 +56,7 @@ gb_inline b32 are_strings_equal(String a, String b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gb_inline b32 are_strings_equal_ignore_case(String a, String b) {
|
||||
gb_inline b32 str_eq_ignore_case(String a, String b) {
|
||||
if (a.len == b.len) {
|
||||
for (isize i = 0; i < a.len; i++) {
|
||||
char x = cast(char)a.text[i];
|
||||
@@ -115,18 +113,24 @@ GB_COMPARE_PROC(string_cmp_proc) {
|
||||
}
|
||||
|
||||
|
||||
gb_inline bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
|
||||
gb_inline bool operator !=(String a, String b) { return !operator==(a, b); }
|
||||
gb_inline bool operator < (String a, String b) { return string_compare(a, b) < 0; }
|
||||
gb_inline bool operator > (String a, String b) { return string_compare(a, b) > 0; }
|
||||
gb_inline bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
|
||||
gb_inline bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
|
||||
// gb_inline bool operator ==(String a, String b) { return are_strings_equal(a, b) != 0; }
|
||||
// gb_inline bool operator !=(String a, String b) { return !operator==(a, b); }
|
||||
// gb_inline bool operator < (String a, String b) { return string_compare(a, b) < 0; }
|
||||
// gb_inline bool operator > (String a, String b) { return string_compare(a, b) > 0; }
|
||||
// gb_inline bool operator <=(String a, String b) { return string_compare(a, b) <= 0; }
|
||||
// gb_inline bool operator >=(String a, String b) { return string_compare(a, b) >= 0; }
|
||||
|
||||
template <size_t N> gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); }
|
||||
template <size_t N> gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); }
|
||||
template <size_t N> gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; }
|
||||
template <size_t N> gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; }
|
||||
// template <size_t N> gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); }
|
||||
// template <size_t N> gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); }
|
||||
// template <size_t N> gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; }
|
||||
// template <size_t N> gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; }
|
||||
|
||||
gb_inline bool str_eq(String a, String b) { return are_strings_equal(a, b) != 0; }
|
||||
gb_inline bool str_ne(String a, String b) { return !str_eq(a, b); }
|
||||
gb_inline bool str_lt(String a, String b) { return string_compare(a, b) < 0; }
|
||||
gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0; }
|
||||
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
|
||||
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
|
||||
|
||||
|
||||
|
||||
@@ -385,12 +389,12 @@ i32 unquote_string(gbAllocator a, String *s_) {
|
||||
}
|
||||
|
||||
|
||||
u8 rune_temp[4] = {};
|
||||
u8 rune_temp[4] = {0};
|
||||
isize buf_len = 3*s.len / 2;
|
||||
u8 *buf = gb_alloc_array(a, u8, buf_len);
|
||||
isize offset = 0;
|
||||
while (s.len > 0) {
|
||||
String tail_string = {};
|
||||
String tail_string = {0};
|
||||
Rune r = 0;
|
||||
b32 multiple_bytes = false;
|
||||
b32 success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
|
||||
|
||||
@@ -180,7 +180,6 @@ void init_global_error_collector(void) {
|
||||
|
||||
void warning(Token token, char *fmt, ...) {
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
defer (gb_mutex_unlock(&global_error_collector.mutex));
|
||||
|
||||
global_error_collector.warning_count++;
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
@@ -195,11 +194,12 @@ void warning(Token token, char *fmt, ...) {
|
||||
gb_bprintf_va(fmt, va));
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
}
|
||||
|
||||
void error(Token token, char *fmt, ...) {
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
defer (gb_mutex_unlock(&global_error_collector.mutex));
|
||||
|
||||
global_error_collector.count++;
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
@@ -214,11 +214,12 @@ void error(Token token, char *fmt, ...) {
|
||||
gb_bprintf_va(fmt, va));
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
}
|
||||
|
||||
void syntax_error(Token token, char *fmt, ...) {
|
||||
gb_mutex_lock(&global_error_collector.mutex);
|
||||
defer (gb_mutex_unlock(&global_error_collector.mutex));
|
||||
|
||||
global_error_collector.count++;
|
||||
// NOTE(bill): Duplicate error, skip it
|
||||
@@ -233,6 +234,8 @@ void syntax_error(Token token, char *fmt, ...) {
|
||||
gb_bprintf_va(fmt, va));
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
gb_mutex_unlock(&global_error_collector.mutex);
|
||||
}
|
||||
|
||||
|
||||
@@ -349,13 +352,12 @@ void advance_to_next_rune(Tokenizer *t) {
|
||||
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
||||
PROF_PROC();
|
||||
|
||||
TokenizerInitError err = TokenizerInit_None;
|
||||
|
||||
char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1);
|
||||
memcpy(c_str, fullpath.text, fullpath.len);
|
||||
c_str[fullpath.len] = '\0';
|
||||
|
||||
defer (gb_free(heap_allocator(), c_str));
|
||||
|
||||
|
||||
// TODO(bill): Memory map rather than copy contents
|
||||
gbFileContents fc = gb_file_read_contents(heap_allocator(), true, c_str);
|
||||
gb_zero_item(t);
|
||||
@@ -363,9 +365,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
||||
t->start = cast(u8 *)fc.data;
|
||||
t->line = t->read_curr = t->curr = t->start;
|
||||
t->end = t->start + fc.size;
|
||||
|
||||
t->fullpath = fullpath;
|
||||
|
||||
t->line_count = 1;
|
||||
|
||||
advance_to_next_rune(t);
|
||||
@@ -374,28 +374,25 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
||||
}
|
||||
|
||||
array_init(&t->allocated_strings, heap_allocator());
|
||||
} else {
|
||||
gbFile f = {};
|
||||
gbFileError file_err = gb_file_open(&f, c_str);
|
||||
|
||||
return TokenizerInit_None;
|
||||
switch (file_err) {
|
||||
case gbFileError_Invalid: err = TokenizerInit_Invalid; break;
|
||||
case gbFileError_NotExists: err = TokenizerInit_NotExists; break;
|
||||
case gbFileError_Permission: err = TokenizerInit_Permission; break;
|
||||
}
|
||||
|
||||
if (err == TokenizerInit_None && gb_file_size(&f) == 0) {
|
||||
err = TokenizerInit_Empty;
|
||||
}
|
||||
|
||||
gb_file_close(&f);
|
||||
}
|
||||
|
||||
gbFile f = {};
|
||||
gbFileError err = gb_file_open(&f, c_str);
|
||||
defer (gb_file_close(&f));
|
||||
|
||||
switch (err) {
|
||||
case gbFileError_Invalid:
|
||||
return TokenizerInit_Invalid;
|
||||
case gbFileError_NotExists:
|
||||
return TokenizerInit_NotExists;
|
||||
case gbFileError_Permission:
|
||||
return TokenizerInit_Permission;
|
||||
}
|
||||
|
||||
if (gb_file_size(&f) == 0) {
|
||||
return TokenizerInit_Empty;
|
||||
}
|
||||
|
||||
return TokenizerInit_None;
|
||||
gb_free(heap_allocator(), c_str);
|
||||
return err;
|
||||
}
|
||||
|
||||
gb_inline void destroy_tokenizer(Tokenizer *t) {
|
||||
@@ -634,17 +631,17 @@ Token tokenizer_get_token(Tokenizer *t) {
|
||||
|
||||
// NOTE(bill): All keywords are > 1
|
||||
if (token.string.len > 1) {
|
||||
if (token.string == token_strings[Token_as]) {
|
||||
if (str_eq(token.string, token_strings[Token_as])) {
|
||||
token.kind = Token_as;
|
||||
} else if (token.string == token_strings[Token_transmute]) {
|
||||
} else if (str_eq(token.string, token_strings[Token_transmute])) {
|
||||
token.kind = Token_transmute;
|
||||
} else if (token.string == token_strings[Token_down_cast]) {
|
||||
} else if (str_eq(token.string, token_strings[Token_down_cast])) {
|
||||
token.kind = Token_down_cast;
|
||||
} else if (token.string == token_strings[Token_union_cast]) {
|
||||
} else if (str_eq(token.string, token_strings[Token_union_cast])) {
|
||||
token.kind = Token_union_cast;
|
||||
} else {
|
||||
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
|
||||
if (token.string == token_strings[k]) {
|
||||
if (str_eq(token.string, token_strings[k])) {
|
||||
token.kind = cast(TokenKind)k;
|
||||
break;
|
||||
}
|
||||
|
||||
356
src/vm.cpp
356
src/vm.cpp
@@ -1,356 +0,0 @@
|
||||
#if 0
|
||||
// TODO(bill): COMPLETELY REWORK THIS ENTIRE INTERPRETER
|
||||
#include "dyncall/include/dyncall.h"
|
||||
|
||||
struct vmInterpreter;
|
||||
|
||||
/*
|
||||
Types:
|
||||
boolean
|
||||
integer
|
||||
float
|
||||
pointer
|
||||
string
|
||||
any
|
||||
array
|
||||
vector
|
||||
slice
|
||||
maybe
|
||||
struct
|
||||
union
|
||||
raw_union
|
||||
enum
|
||||
tuple
|
||||
proc
|
||||
*/
|
||||
|
||||
struct vmProcedure {
|
||||
Type * type;
|
||||
String name;
|
||||
b32 is_external;
|
||||
};
|
||||
|
||||
struct vmValue {
|
||||
void *data;
|
||||
i32 id;
|
||||
Type *type;
|
||||
union {
|
||||
i64 v_int;
|
||||
f32 v_f32;
|
||||
f64 v_f64;
|
||||
vmProcedure * v_proc;
|
||||
};
|
||||
};
|
||||
|
||||
Array<vmValue> vm_empty_args = {};
|
||||
|
||||
struct vmFrame {
|
||||
vmInterpreter *i;
|
||||
vmFrame * caller;
|
||||
ssaProcedure * proc;
|
||||
ssaBlock * block;
|
||||
ssaBlock * prev_block;
|
||||
isize instr_index; // For the current block
|
||||
|
||||
Array<void *> env; // Index == instr id
|
||||
vmValue result;
|
||||
};
|
||||
|
||||
struct vmInterpreter {
|
||||
ssaModule * module;
|
||||
BaseTypeSizes sizes;
|
||||
gbArena stack_arena;
|
||||
gbAllocator stack_allocator;
|
||||
gbAllocator heap_allocator;
|
||||
|
||||
Array<vmFrame> frame_stack;
|
||||
Map<vmValue> globals;
|
||||
};
|
||||
|
||||
enum vmContinuation {
|
||||
vmContinuation_Next,
|
||||
vmContinuation_Return,
|
||||
vmContinuation_Branch,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
i64 vm_size_of(vmInterpreter *i, Type *type) {
|
||||
return type_size_of(i->sizes, i->heap_allocator, type);
|
||||
}
|
||||
i64 vm_align_of(vmInterpreter *i, Type *type) {
|
||||
return type_align_of(i->sizes, i->heap_allocator, type);
|
||||
}
|
||||
i64 vm_offset_of(vmInterpreter *i, Type *type, i64 index) {
|
||||
return type_offset_of(i->sizes, i->heap_allocator, type, index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Array<vmValue> vm_prepare_call(vmFrame *f, ssaInstr *instr, vmValue *proc) {
|
||||
GB_ASSERT(instr->kind == ssaInstr_Call);
|
||||
|
||||
*proc = vm_get_value(f, instr->Call.value);
|
||||
|
||||
Array<vmValue> args = {};
|
||||
array_init_count(&args, f->i->stack_allocator, instr->Call.arg_count);
|
||||
|
||||
for (isize i = 0; i < instr->Call.arg_count; i++) {
|
||||
args[i] = vm_get_value(f, instr->Call.args[i]);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
vmContinuation vm_visit_instr(vmFrame *f, ssaValue *value) {
|
||||
ssaInstr *instr = &value->Instr;
|
||||
#if 1
|
||||
if (instr->kind != ssaInstr_Comment) {
|
||||
gb_printf("instr: %.*s\n", LIT(ssa_instr_strings[instr->kind]));
|
||||
}
|
||||
#endif
|
||||
switch (instr->kind) {
|
||||
case ssaInstr_StartupRuntime: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Comment: break;
|
||||
|
||||
case ssaInstr_Local: {
|
||||
Type *type = ssa_type(value);
|
||||
GB_ASSERT(is_type_pointer(type));
|
||||
i64 size = gb_max(1, vm_size_of(f->i, type));
|
||||
i64 align = gb_max(1, vm_align_of(f->i, type));
|
||||
void *mem = gb_alloc_align(f->i->stack_allocator, size, align);
|
||||
|
||||
array_add(&f->locals, mem);
|
||||
} break;
|
||||
|
||||
case ssaInstr_ZeroInit: {
|
||||
Type *pt = ssa_type(instr->ZeroInit.address);
|
||||
GB_ASSERT(is_type_pointer(pt));
|
||||
vmValue addr = vm_get_value(f, instr->ZeroInit.address);
|
||||
GB_ASSERT(are_types_identical(addr.type, ptr));
|
||||
i64 size = vm_size_of(vm, type_deref(pt));
|
||||
gb_zero(addr.v_ptr, size);
|
||||
} break;
|
||||
|
||||
case ssaInstr_Store: {
|
||||
ssaValue *addr = instr->Store.Address;
|
||||
ssaValue *value = instr->Store.Value;
|
||||
} break;
|
||||
|
||||
case ssaInstr_Load: {
|
||||
ssaValue *addr = instr->Load.Address;
|
||||
} break;
|
||||
|
||||
case ssaInstr_ArrayElementPtr: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_StructElementPtr: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_PtrOffset: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Phi:
|
||||
for_array(i, f->block->preds) {
|
||||
ssaBlock *pred = f->block->preds[i];
|
||||
if (f->prev_block == pred) {
|
||||
vmValue edge = vm_get_value(f, instr->Phi.edges[i]);
|
||||
// vm_set_value(f, value, edge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ssaInstr_ArrayExtractValue: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_StructExtractValue: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Jump:
|
||||
f->prev_block = f->block;
|
||||
f->block = instr->Jump.block;
|
||||
return vmContinuation_Branch;
|
||||
|
||||
case ssaInstr_If:
|
||||
f->prev_block = f->block;
|
||||
if (vm_get_value(f, instr->If.cond).v_int != 0) {
|
||||
f->block = instr->If.true_block;
|
||||
} else {
|
||||
f->block = instr->If.false_block;
|
||||
}
|
||||
return vmContinuation_Branch;
|
||||
|
||||
case ssaInstr_Return:
|
||||
if (instr->Return.value != NULL) {
|
||||
Type *type = base_type(ssa_type(instr->Return.value));
|
||||
GB_ASSERT(is_type_tuple(type));
|
||||
f->result = vm_get_value(f, instr->Return.value);
|
||||
if (type->Tuple.variable_count == 1) {
|
||||
f->result.type = type->Tuple.variables[0]->type;
|
||||
}
|
||||
}
|
||||
f->block = NULL;
|
||||
return vmContinuation_Return;
|
||||
|
||||
case ssaInstr_Conv: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Unreachable: {
|
||||
GB_PANIC("Unreachable");
|
||||
} break;
|
||||
|
||||
case ssaInstr_BinaryOp: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Call: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_Select: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorExtractElement: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorInsertElement: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorShuffle: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_BoundsCheck: {
|
||||
|
||||
} break;
|
||||
|
||||
case ssaInstr_SliceBoundsCheck: {
|
||||
|
||||
} break;
|
||||
|
||||
default: {
|
||||
GB_PANIC("<unknown instr> %d\n", instr->kind);
|
||||
} break;
|
||||
}
|
||||
|
||||
return vmContinuation_Next;
|
||||
}
|
||||
|
||||
|
||||
void vm_run_frame(vmFrame *f) {
|
||||
for (;;) {
|
||||
for_array(i, f->block->instrs) {
|
||||
ssaValue *v = f->block->instrs[i];
|
||||
GB_ASSERT(v->kind == ssaValue_Instr);
|
||||
switch (vm_visit_instr(f, v)) {
|
||||
case vmContinuation_Return:
|
||||
return;
|
||||
case vmContinuation_Next:
|
||||
// Do nothing
|
||||
break;
|
||||
case vmContinuation_Branch:
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
end:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
ssaProcedure *vm_lookup_proc(vmInterpreter *i, String name) {
|
||||
ssaValue **found = map_get(&i->module->members, hash_string(name));
|
||||
if (found == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ssaValue *v = *found;
|
||||
if (v->kind != ssaValue_Proc) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &v->Proc;
|
||||
}
|
||||
|
||||
vmValue vm_ext(vmFrame *caller, Array<vmValue> args) {
|
||||
GB_PANIC("TODO(bill): vm_ext");
|
||||
vmValue v = {};
|
||||
return v;
|
||||
}
|
||||
|
||||
vmValue vm_call(vmInterpreter *i, vmFrame *caller, ssaProcedure *proc, Array<vmValue> args) {
|
||||
if (proc == NULL) {
|
||||
GB_PANIC("Call to NULL procedure");
|
||||
}
|
||||
|
||||
gb_printf("Call: %.*s", LIT(proc->name));
|
||||
|
||||
vmFrame f = {};
|
||||
f.i = i;
|
||||
f.caller = caller;
|
||||
f.proc = proc;
|
||||
if (proc->body == NULL) {
|
||||
return vm_ext(&f, args);
|
||||
}
|
||||
f.block = proc->blocks[0];
|
||||
|
||||
map_init_with_reserve(&f.env, i->heap_allocator, 1.5*proc->instr_count);
|
||||
defer (map_destroy(&f.env));
|
||||
|
||||
array_init_count(&f.locals, i->heap_allocator, proc->local_count);
|
||||
defer (array_free(&f.locals));
|
||||
|
||||
for_array(i, proc->params) {
|
||||
map_set(&f.env, hash_pointer(proc->params[i]), args[i]);
|
||||
}
|
||||
|
||||
while (f.block != NULL) {
|
||||
vm_run_frame(&f);
|
||||
}
|
||||
|
||||
return f.result;
|
||||
}
|
||||
|
||||
i32 vm_interpret(ssaModule *m) {
|
||||
i32 exit_code = 2;
|
||||
|
||||
vmInterpreter i = {};
|
||||
|
||||
i.module = m;
|
||||
i.sizes = m->sizes;
|
||||
|
||||
gb_arena_init_from_allocator(&i.stack_arena, heap_allocator(), gb_megabytes(64));
|
||||
defer (gb_arena_free(&i.stack_arena));
|
||||
|
||||
i.stack_allocator = gb_arena_allocator(&i.stack_arena);
|
||||
i.heap_allocator = heap_allocator();
|
||||
|
||||
ssaProcedure *main_proc = vm_lookup_proc(&i, make_string("main"));
|
||||
if (main_proc != NULL) {
|
||||
vm_call(&i, NULL, main_proc, vm_empty_args);
|
||||
exit_code = 0;
|
||||
} else {
|
||||
gb_printf_err("No main procedure.");
|
||||
exit_code = 1;
|
||||
}
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user