Remove: string overloads; defer

This commit is contained in:
Ginger Bill
2016-11-22 20:29:46 +00:00
parent 36ad9dae43
commit 3517f96668
18 changed files with 613 additions and 926 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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; };

View File

@@ -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),

View File

@@ -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);
}
}

View File

@@ -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");
}

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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