diff --git a/build.bat b/build.bat index 065057a63..873ed2fa0 100644 --- a/build.bat +++ b/build.bat @@ -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 diff --git a/misc/shell.bat b/misc/shell.bat index e3c7f3f40..5d9271622 100644 --- a/misc/shell.bat +++ b/misc/shell.bat @@ -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 diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index f8c35bcc3..9e6330325 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -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 import_decls; array_init(&import_decls, heap_allocator()); - defer (array_free(&import_decls)); Map 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); } diff --git a/src/checker/decl.cpp b/src/checker/decl.cpp index 63cd6e3ce..37a832b9a 100644 --- a/src/checker/decl.cpp +++ b/src/checker/decl.cpp @@ -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; } diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index 44c32bece..4c0e86ab8 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -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); } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 1b2353ac5..55011467b 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -181,12 +181,9 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n if (type != NULL) { if (!check_is_assignable_to(c, operand, type, is_argument)) { - gbString type_string = type_to_string(type); - gbString op_type_string = type_to_string(operand->type); - gbString expr_str = expr_to_string(operand->expr); - defer (gb_string_free(type_string)); - defer (gb_string_free(op_type_string)); - defer (gb_string_free(expr_str)); + gbString type_str = type_to_string(type); + gbString op_type_str = type_to_string(operand->type); + gbString expr_str = expr_to_string(operand->expr); if (operand->mode == Addressing_Builtin) { // TODO(bill): is this a good enough error message? @@ -199,11 +196,15 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n error(ast_node_token(operand->expr), "Cannot assign value `%s` of type `%s` to `%s` in %.*s", expr_str, - op_type_string, - type_string, + op_type_str, + type_str, LIT(context_name)); } operand->mode = Addressing_Invalid; + + gb_string_free(expr_str); + gb_string_free(op_type_str); + gb_string_free(type_str); return; } } @@ -215,7 +216,6 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map t = base_type(type_deref(t)); gbString str = expr_to_string(node); - defer (gb_string_free(str)); if (t->kind == Type_Record) { for (isize i = 0; i < t->Record.field_count; i++) { @@ -238,6 +238,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map } } + gb_string_free(str); } void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr); @@ -249,11 +250,9 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, PROF_PROC(); gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); Map entity_map = {}; map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(field_count+other_field_count)); - // defer (map_destroy(&entity_map)); isize other_field_index = 0; Entity *using_index_expr = NULL; @@ -303,7 +302,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, AstNode *name = cd->names[i]; Entity *e = entities[i]; Token name_token = name->Ident; - if (name_token.string == "_") { + if (str_eq(name_token.string, str_lit("_"))) { other_fields[other_field_index++] = e; } else { HashKey key = hash_string(name_token.string); @@ -325,7 +324,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, Delay delay = {e, td->type}; array_add(&delayed_type, delay); - if (name_token.string == "_") { + if (str_eq(name_token.string, str_lit("_"))) { other_fields[other_field_index++] = e; } else { HashKey key = hash_string(name_token.string); @@ -370,7 +369,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, type->Named.type_name = e; add_entity(c, c->context.scope, name, e); - if (name_token.string == "_") { + if (str_eq(name_token.string, str_lit("_"))) { error(name_token, "`_` cannot be used a union subtype"); continue; } @@ -410,7 +409,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index); e->identifier = name; - if (name_token.string == "_") { + if (str_eq(name_token.string, str_lit("_"))) { fields[field_index++] = e; } else { HashKey key = hash_string(name_token.string); @@ -461,6 +460,8 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, } } } + + gb_temp_arena_memory_end(tmp); } @@ -523,7 +524,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, st->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("struct")); + check_fields(c, node, st->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("struct")); struct_type->Record.struct_is_packed = st->is_packed; @@ -589,7 +590,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("union")); + check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("union")); union_type->Record.fields = fields; union_type->Record.field_count = field_count; @@ -626,7 +627,7 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count); Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count); - check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, make_string("raw union")); + check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("raw union")); union_type->Record.fields = fields; union_type->Record.field_count = field_count; @@ -663,12 +664,6 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod ast_node(et, EnumType, node); - gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); - - Map entity_map = {}; - map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count)); - // defer (map_destroy(&entity_map)); Type *base_type = t_int; if (et->base_type != NULL) { @@ -694,6 +689,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod if (named_type != NULL) { constant_type = named_type; } + + + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); + + Map entity_map = {}; + map_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count)); + Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));; for_array(i, et->fields) { @@ -702,15 +704,15 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod ast_node(f, FieldValue, field); Token name_token = f->field->Ident; - if (name_token.string == "count") { + if (str_eq(name_token.string, str_lit("count"))) { error(name_token, "`count` is a reserved identifier for enumerations"); fields[field_index++] = blank_entity; continue; - } else if (name_token.string == "min_value") { + } else if (str_eq(name_token.string, str_lit("min_value"))) { error(name_token, "`min_value` is a reserved identifier for enumerations"); fields[field_index++] = blank_entity; continue; - } else if (name_token.string == "max_value") { + } else if (str_eq(name_token.string, str_lit("max_value"))) { error(name_token, "`max_value` is a reserved identifier for enumerations"); fields[field_index++] = blank_entity; continue; @@ -724,7 +726,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod o.mode = Addressing_Invalid; } if (o.mode != Addressing_Invalid) { - check_assignment(c, &o, constant_type, make_string("enumeration")); + check_assignment(c, &o, constant_type, str_lit("enumeration")); } if (o.mode != Addressing_Invalid) { iota = o.value; @@ -766,11 +768,13 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod enum_type->Record.other_field_count = field_index; enum_type->Record.enum_count = make_entity_constant(c->allocator, NULL, - make_token_ident(make_string("count")), t_int, make_exact_value_integer(enum_type->Record.other_field_count)); + make_token_ident(str_lit("count")), t_int, make_exact_value_integer(enum_type->Record.other_field_count)); enum_type->Record.min_value = make_entity_constant(c->allocator, NULL, - make_token_ident(make_string("min_value")), constant_type, make_exact_value_integer(min_value)); + make_token_ident(str_lit("min_value")), constant_type, make_exact_value_integer(min_value)); enum_type->Record.max_value = make_entity_constant(c->allocator, NULL, - make_token_ident(make_string("max_value")), constant_type, make_exact_value_integer(max_value)); + make_token_ident(str_lit("max_value")), constant_type, make_exact_value_integer(max_value)); + + gb_temp_arena_memory_end(tmp); } Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) { @@ -852,7 +856,7 @@ Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) { AstNode *item = results[i]; Type *type = check_type(c, item); Token token = ast_node_token(item); - token.string = make_string(""); // NOTE(bill): results are not named + token.string = str_lit(""); // NOTE(bill): results are not named // TODO(bill): Should I have named results? Entity *param = make_entity_param(c->allocator, scope, token, type, false); // NOTE(bill): No need to record @@ -898,7 +902,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl o->expr = n; Entity *e = scope_lookup_entity(c->context.scope, n->Ident.string); if (e == NULL) { - if (n->Ident.string == "_") { + if (str_eq(n->Ident.string, str_lit("_"))) { error(n->Ident, "`_` cannot be used as a value type"); } else { error(n->Ident, "Undeclared name: %.*s", LIT(n->Ident.string)); @@ -1041,7 +1045,6 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c ExactValue null_value = {ExactValue_Invalid}; Type *type = NULL; gbString err_str = NULL; - defer (gb_string_free(err_str)); switch (e->kind) { case_ast_node(i, Ident, e); @@ -1202,6 +1205,8 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c type = t_invalid; end: + gb_string_free(err_str); + if (type == NULL) { type = t_invalid; } @@ -1210,6 +1215,8 @@ end: GB_ASSERT(is_type_typed(type)); add_type_and_value(&c->info, e, Addressing_Type, type, null_value); + + return type; } @@ -1218,13 +1225,13 @@ b32 check_unary_op(Checker *c, Operand *o, Token op) { // TODO(bill): Handle errors correctly Type *type = base_type(base_vector_type(o->type)); gbString str = NULL; - defer (gb_string_free(str)); switch (op.kind) { case Token_Add: case Token_Sub: if (!is_type_numeric(type)) { str = expr_to_string(o->expr); error(op, "Operator `%.*s` is not allowed with `%s`", LIT(op.string), str); + gb_string_free(str); } break; @@ -1238,6 +1245,7 @@ b32 check_unary_op(Checker *c, Operand *o, Token op) { if (!is_type_boolean(type)) { str = expr_to_string(o->expr); error(op, "Operator `%.*s` is only allowed on boolean expression", LIT(op.string)); + gb_string_free(str); } break; @@ -1264,8 +1272,8 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) { } if (base_type(type) == t_rawptr) { gbString str = type_to_string(type); - defer (gb_string_free(str)); error(ast_node_token(o->expr), "Invalid pointer type for pointer arithmetic: `%s`", str); + gb_string_free(str); return false; } break; @@ -1415,8 +1423,6 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { if (!check_value_is_expressible(c, o->value, type, &o->value)) { gbString a = expr_to_string(o->expr); gbString b = type_to_string(type); - defer (gb_string_free(a)); - defer (gb_string_free(b)); if (is_type_numeric(o->type) && is_type_numeric(type)) { if (!is_type_integer(o->type) && is_type_integer(type)) { error(ast_node_token(o->expr), "`%s` truncated to `%s`", a, b); @@ -1427,6 +1433,8 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) { error(ast_node_token(o->expr), "Cannot convert `%s` to `%s`", a, b); } + gb_string_free(b); + gb_string_free(a); o->mode = Addressing_Invalid; } } @@ -1467,8 +1475,8 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { check_is_vector_elem(c, o->expr)) { ast_node(ue, UnaryExpr, node); gbString str = expr_to_string(ue->expr); - defer (gb_string_free(str)); error(op, "Cannot take the pointer address of `%s`", str); + gb_string_free(str); o->mode = Addressing_Invalid; return; } @@ -1487,8 +1495,8 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { if (!is_value || is_type_untyped(t)) { ast_node(ue, UnaryExpr, node); gbString str = expr_to_string(ue->expr); - defer (gb_string_free(str)); error(op, "Cannot convert `%s` to a maybe", str); + gb_string_free(str); o->mode = Addressing_Invalid; return; } @@ -1508,9 +1516,9 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) { if (type->kind != Type_Basic) { gbString xt = type_to_string(o->type); gbString err_str = expr_to_string(node); - defer (gb_string_free(xt)); - defer (gb_string_free(err_str)); error(op, "Invalid type, `%s`, for constant unary expression `%s`", xt, err_str); + gb_string_free(err_str); + gb_string_free(xt); o->mode = Addressing_Invalid; return; } @@ -1538,12 +1546,8 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { PROF_PROC(); gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); gbString err_str = NULL; - defer (if (err_str != NULL) { - gb_string_free(err_str); - }); if (check_is_assignable_to(c, x, y->type) || check_is_assignable_to(c, y, x->type)) { @@ -1573,40 +1577,45 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { if (!defined) { gbString type_string = type_to_string(err_type); - defer (gb_string_free(type_string)); err_str = gb_string_make(c->tmp_allocator, gb_bprintf("operator `%.*s` not defined for type `%s`", LIT(op.string), type_string)); + gb_string_free(type_string); } } else { gbString xt = type_to_string(x->type); gbString yt = type_to_string(y->type); - defer(gb_string_free(xt)); - defer(gb_string_free(yt)); err_str = gb_string_make(c->tmp_allocator, gb_bprintf("mismatched types `%s` and `%s`", xt, yt)); + gb_string_free(yt); + gb_string_free(xt); } if (err_str != NULL) { error(ast_node_token(x->expr), "Cannot compare expression, %s", err_str); x->type = t_untyped_bool; - return; - } - - if (x->mode == Addressing_Constant && - y->mode == Addressing_Constant) { - x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value)); } else { - x->mode = Addressing_Value; + if (x->mode == Addressing_Constant && + y->mode == Addressing_Constant) { + x->value = make_exact_value_bool(compare_exact_values(op, x->value, y->value)); + } else { + x->mode = Addressing_Value; - update_expr_type(c, x->expr, default_type(x->type), true); - update_expr_type(c, y->expr, default_type(y->type), true); + update_expr_type(c, x->expr, default_type(x->type), true); + update_expr_type(c, y->expr, default_type(y->type), true); + } + + if (is_type_vector(base_type(y->type))) { + x->type = make_type_vector(c->allocator, t_bool, base_type(y->type)->Vector.count); + } else { + x->type = t_untyped_bool; + } } - if (is_type_vector(base_type(y->type))) { - x->type = make_type_vector(c->allocator, t_bool, base_type(y->type)->Vector.count); - } else { - x->type = t_untyped_bool; - } + if (err_str != NULL) { + gb_string_free(err_str); + }; + + gb_temp_arena_memory_end(tmp); } void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { @@ -1623,9 +1632,9 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { b32 x_is_untyped = is_type_untyped(x->type); if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) { gbString err_str = expr_to_string(x->expr); - defer (gb_string_free(err_str)); error(ast_node_token(node), "Shifted operand `%s` must be an integer", err_str); + gb_string_free(err_str); x->mode = Addressing_Invalid; return; } @@ -1640,9 +1649,9 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { } } else { gbString err_str = expr_to_string(y->expr); - defer (gb_string_free(err_str)); error(ast_node_token(node), "Shift amount `%s` must be an unsigned integer", err_str); + gb_string_free(err_str); x->mode = Addressing_Invalid; return; } @@ -1653,9 +1662,9 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { ExactValue y_val = exact_value_to_integer(y->value); if (y_val.kind != ExactValue_Integer) { gbString err_str = expr_to_string(y->expr); - defer (gb_string_free(err_str)); error(ast_node_token(node), "Shift amount `%s` must be an unsigned integer", err_str); + gb_string_free(err_str); x->mode = Addressing_Invalid; return; } @@ -1663,9 +1672,9 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { u64 amount = cast(u64)y_val.value_integer; if (amount > 1074) { gbString err_str = expr_to_string(y->expr); - defer (gb_string_free(err_str)); error(ast_node_token(node), "Shift amount too large: `%s`", err_str); + gb_string_free(err_str); x->mode = Addressing_Invalid; return; } @@ -1696,9 +1705,9 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) { if (y->mode == Addressing_Constant && y->value.value_integer < 0) { gbString err_str = expr_to_string(y->expr); - defer (gb_string_free(err_str)); error(ast_node_token(node), "Shift amount cannot be negative: `%s`", err_str); + gb_string_free(err_str); } x->mode = Addressing_Value; @@ -1814,8 +1823,8 @@ Operand check_ptr_addition(Checker *c, TokenKind op, Operand *ptr, Operand *offs if (base_type(ptr->type) == t_rawptr) { gbString str = type_to_string(ptr->type); - defer (gb_string_free(str)); error(ast_node_token(node), "Invalid pointer type for pointer arithmetic: `%s`", str); + gb_string_free(str); operand.mode = Addressing_Invalid; return operand; } @@ -1843,9 +1852,6 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { GB_ASSERT(node->kind == AstNode_BinaryExpr); Operand y_ = {}, *y = &y_; - gbString err_str = NULL; - defer (gb_string_free(err_str)); - ast_node(be, BinaryExpr, node); @@ -1877,10 +1883,10 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { gbString expr_str = expr_to_string(x->expr); gbString to_type = type_to_string(type); gbString from_type = type_to_string(x->type); - defer (gb_string_free(expr_str)); - defer (gb_string_free(to_type)); - defer (gb_string_free(from_type)); error(ast_node_token(x->expr), "Cannot cast `%s` as `%s` from `%s`", expr_str, to_type, from_type); + gb_string_free(from_type); + gb_string_free(to_type); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; @@ -1905,16 +1911,16 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (x->mode == Addressing_Constant) { gbString expr_str = expr_to_string(x->expr); - defer (gb_string_free(expr_str)); error(ast_node_token(x->expr), "Cannot transmute constant expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } if (is_type_untyped(x->type)) { gbString expr_str = expr_to_string(x->expr); - defer (gb_string_free(expr_str)); error(ast_node_token(x->expr), "Cannot transmute untyped expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -1924,9 +1930,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (srcz != dstz) { gbString expr_str = expr_to_string(x->expr); gbString type_str = type_to_string(type); - defer (gb_string_free(expr_str)); - defer (gb_string_free(type_str)); error(ast_node_token(x->expr), "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz); + gb_string_free(type_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -1943,24 +1949,24 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (x->mode == Addressing_Constant) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Cannot `down_cast` a constant expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } if (is_type_untyped(x->type)) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Cannot `down_cast` an untyped expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } if (!(is_type_pointer(x->type) && is_type_pointer(type))) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Can only `down_cast` pointers: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -1972,16 +1978,16 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (!(is_type_struct(bsrc) || is_type_raw_union(bsrc))) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Can only `down_cast` pointer from structs or unions: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Can only `down_cast` pointer to structs or unions: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -1989,8 +1995,8 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { String param_name = check_down_cast_name(dst, src); if (param_name.len == 0) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Illegal `down_cast`: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -2007,16 +2013,16 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (x->mode == Addressing_Constant) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Cannot `union_cast` a constant expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } if (is_type_untyped(x->type)) { gbString expr_str = expr_to_string(node); - defer (gb_string_free(expr_str)); error(ast_node_token(node), "Cannot `union_cast` an untyped expression: `%s`", expr_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } @@ -2031,9 +2037,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (src_is_ptr != dst_is_ptr) { gbString src_type_str = type_to_string(x->type); gbString dst_type_str = type_to_string(type); - defer (gb_string_free(src_type_str)); - defer (gb_string_free(dst_type_str)); error(ast_node_token(node), "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str); + gb_string_free(dst_type_str); + gb_string_free(src_type_str); x->mode = Addressing_Invalid; return; } @@ -2056,15 +2062,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (!ok) { gbString expr_str = expr_to_string(node); gbString dst_type_str = type_to_string(type); - defer (gb_string_free(expr_str)); - defer (gb_string_free(dst_type_str)); error(ast_node_token(node), "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str); + gb_string_free(dst_type_str); + gb_string_free(expr_str); x->mode = Addressing_Invalid; return; } Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); - Token tok = make_token_ident(make_string("")); + Token tok = make_token_ident(str_lit("")); variables[0] = make_entity_param(c->allocator, NULL, tok, type, false); variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false); @@ -2103,9 +2109,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (op.kind == Token_Sub) { gbString lhs = expr_to_string(x->expr); gbString rhs = expr_to_string(y->expr); - defer (gb_string_free(lhs)); - defer (gb_string_free(rhs)); error(ast_node_token(node), "Invalid pointer arithmetic, did you mean `%s %.*s %s`?", rhs, LIT(op.string), lhs); + gb_string_free(rhs); + gb_string_free(lhs); x->mode = Addressing_Invalid; return; } @@ -2135,10 +2141,11 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { y->type != t_invalid) { gbString xt = type_to_string(x->type); gbString yt = type_to_string(y->type); - defer (gb_string_free(xt)); - defer (gb_string_free(yt)); - err_str = expr_to_string(x->expr); - error(op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", err_str, xt, yt); + gbString expr_str = expr_to_string(x->expr); + error(op, "Mismatched types in binary expression `%s` : `%s` vs `%s`", expr_str, xt, yt); + gb_string_free(expr_str); + gb_string_free(yt); + gb_string_free(xt); } x->mode = Addressing_Invalid; return; @@ -2194,9 +2201,10 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) { if (type->kind != Type_Basic) { gbString xt = type_to_string(x->type); - defer (gb_string_free(xt)); - err_str = expr_to_string(node); + gbString err_str = expr_to_string(node); error(op, "Invalid type, `%s`, for constant binary expression `%s`", xt, err_str); + gb_string_free(err_str); + gb_string_free(xt); x->mode = Addressing_Invalid; return; } @@ -2260,9 +2268,9 @@ void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) { if (old.is_lhs && !is_type_integer(type)) { gbString expr_str = expr_to_string(e); gbString type_str = type_to_string(type); - defer (gb_string_free(expr_str)); - defer (gb_string_free(type_str)); error(ast_node_token(e), "Shifted operand %s must be an integer, got %s", expr_str, type_str); + gb_string_free(type_str); + gb_string_free(expr_str); return; } @@ -2281,12 +2289,10 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { gbString expr_str = expr_to_string(operand->expr); gbString type_str = type_to_string(target_type); char *extra_text = ""; - defer (gb_string_free(expr_str)); - defer (gb_string_free(type_str)); if (operand->mode == Addressing_Constant) { if (operand->value.value_integer == 0) { - if (make_string(expr_str) != "nil") { // HACK NOTE(bill): Just in case + if (str_ne(make_string_c(expr_str), str_lit("nil"))) { // HACK NOTE(bill): Just in case // NOTE(bill): Doesn't matter what the type is as it's still zero in the union extra_text = " - Did you want `nil`?"; } @@ -2294,6 +2300,8 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { } error(ast_node_token(operand->expr), "Cannot convert `%s` to `%s`%s", expr_str, type_str, extra_text); + gb_string_free(type_str); + gb_string_free(expr_str); operand->mode = Addressing_Invalid; } @@ -2482,8 +2490,8 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { if (is_not_exported) { gbString sel_str = expr_to_string(selector); - defer (gb_string_free(sel_str)); error(ast_node_token(op_expr), "`%s` is not exported by `%.*s`", sel_str, LIT(name)); + gb_string_free(sel_str); // NOTE(bill): Not really an error so don't goto error } @@ -2506,10 +2514,10 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { gbString op_str = expr_to_string(op_expr); gbString type_str = type_to_string(operand->type); gbString sel_str = expr_to_string(selector); - defer (gb_string_free(op_str)); - defer (gb_string_free(type_str)); - defer (gb_string_free(sel_str)); error(ast_node_token(op_expr), "`%s` (`%s`) has no field `%s`", op_str, type_str, sel_str); + gb_string_free(sel_str); + gb_string_free(type_str); + gb_string_free(op_str); goto error; } @@ -2517,10 +2525,10 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) { gbString op_str = expr_to_string(op_expr); gbString type_str = type_to_string(operand->type); gbString sel_str = expr_to_string(selector); - defer (gb_string_free(op_str)); - defer (gb_string_free(type_str)); - defer (gb_string_free(sel_str)); error(ast_node_token(op_expr), "Cannot access non-constant field `%s` from `%s`", sel_str, op_str); + gb_string_free(sel_str); + gb_string_free(type_str); + gb_string_free(op_str); goto error; } @@ -2640,10 +2648,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (!is_type_integer(op.type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Length for `new_slice` must be an integer, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -2654,10 +2662,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (!is_type_integer(op.type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Capacity for `new_slice` must be an integer, got `%s`", type_str); + gb_string_free(type_str); return false; } if (ce->args.count > 3) { @@ -2687,7 +2695,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_size_of_val: // size_of_val :: proc(val: Type) -> untyped int - check_assignment(c, operand, NULL, make_string("argument of `size_of_val`")); + check_assignment(c, operand, NULL, str_lit("argument of `size_of_val`")); if (operand->mode == Addressing_Invalid) { return false; } @@ -2711,7 +2719,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_align_of_val: // align_of_val :: proc(val: Type) -> untyped int - check_assignment(c, operand, NULL, make_string("argument of `align_of_val`")); + check_assignment(c, operand, NULL, str_lit("argument of `align_of_val`")); if (operand->mode == Addressing_Invalid) { return false; } @@ -2747,16 +2755,16 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type); if (sel.entity == NULL) { gbString type_str = type_to_string(bt); - defer (gb_string_free(type_str)); error(ast_node_token(ce->args[0]), "`%s` has no field named `%.*s`", type_str, LIT(arg->string)); + gb_string_free(type_str); return false; } if (sel.indirect) { gbString type_str = type_to_string(bt); - defer (gb_string_free(type_str)); error(ast_node_token(ce->args[0]), "Field `%.*s` is embedded via a pointer in `%s`", LIT(arg->string), type_str); + gb_string_free(type_str); return false; } @@ -2802,9 +2810,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (sel.indirect) { gbString type_str = type_to_string(type); - defer (gb_string_free(type_str)); error(ast_node_token(ce->args[0]), "Field `%.*s` is embedded via a pointer in `%s`", LIT(i->string), type_str); + gb_string_free(type_str); return false; } @@ -2817,7 +2825,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProc_type_of_val: // type_of_val :: proc(val: Type) -> type(Type) - check_assignment(c, operand, NULL, make_string("argument of `type_of_val`")); + check_assignment(c, operand, NULL, str_lit("argument of `type_of_val`")); if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) { return false; } @@ -2844,7 +2852,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) // type_info_of_val :: proc(val: Type) -> ^Type_Info AstNode *expr = ce->args[0]; - check_assignment(c, operand, NULL, make_string("argument of `type_info_of_val`")); + check_assignment(c, operand, NULL, str_lit("argument of `type_info_of_val`")); if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin) return false; add_type_info_type(c, operand->type); @@ -2860,16 +2868,14 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) { gbString str = expr_to_string(ce->args[0]); - defer (gb_string_free(str)); - error(ast_node_token(call), - "`%s` is not a constant boolean", str); + error(ast_node_token(call), "`%s` is not a constant boolean", str); + gb_string_free(str); return false; } if (!operand->value.value_bool) { gbString str = expr_to_string(ce->args[0]); - defer (gb_string_free(str)); - error(ast_node_token(call), - "Compile time assertion: `%s`", str); + error(ast_node_token(call), "Compile time assertion: `%s`", str); + gb_string_free(str); } break; @@ -2878,9 +2884,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (!is_type_boolean(operand->type)) { gbString str = expr_to_string(ce->args[0]); - defer (gb_string_free(str)); - error(ast_node_token(call), - "`%s` is not a boolean", str); + error(ast_node_token(call), "`%s` is not a boolean", str); + gb_string_free(str); return false; } @@ -2892,9 +2897,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (!is_type_string(operand->type)) { gbString str = expr_to_string(ce->args[0]); - defer (gb_string_free(str)); - error(ast_node_token(call), - "`%s` is not a string", str); + error(ast_node_token(call), "`%s` is not a string", str); + gb_string_free(str); return false; } @@ -2906,16 +2910,18 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *dest_type = NULL, *src_type = NULL; Type *d = base_type(operand->type); - if (d->kind == Type_Slice) + if (d->kind == Type_Slice) { dest_type = d->Slice.elem; - + } Operand op = {}; check_expr(c, &op, ce->args[1]); - if (op.mode == Addressing_Invalid) + if (op.mode == Addressing_Invalid) { return false; + } Type *s = base_type(op.type); - if (s->kind == Type_Slice) + if (s->kind == Type_Slice) { src_type = s->Slice.elem; + } if (dest_type == NULL || src_type == NULL) { error(ast_node_token(call), "`copy` only expects slices as arguments"); @@ -2927,13 +2933,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) gbString s_arg = expr_to_string(ce->args[1]); gbString d_str = type_to_string(dest_type); gbString s_str = type_to_string(src_type); - defer (gb_string_free(d_arg)); - defer (gb_string_free(s_arg)); - defer (gb_string_free(d_str)); - defer (gb_string_free(s_str)); error(ast_node_token(call), "Arguments to `copy`, %s, %s, have different elem types: %s vs %s", d_arg, s_arg, d_str, s_str); + gb_string_free(s_str); + gb_string_free(d_str); + gb_string_free(s_arg); + gb_string_free(d_arg); return false; } @@ -2948,8 +2954,9 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Operand op = {}; check_expr(c, &op, ce->args[1]); - if (op.mode == Addressing_Invalid) + if (op.mode == Addressing_Invalid) { return false; + } y_type = base_type(op.type); if (!(is_type_pointer(x_type) && is_type_slice(x_type->Pointer.elem))) { @@ -2963,13 +2970,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) gbString s_arg = expr_to_string(ce->args[1]); gbString d_str = type_to_string(elem_type); gbString s_str = type_to_string(y_type); - defer (gb_string_free(d_arg)); - defer (gb_string_free(s_arg)); - defer (gb_string_free(d_str)); - defer (gb_string_free(s_str)); error(ast_node_token(call), "Arguments to `append`, %s, %s, have different element types: %s vs %s", d_arg, s_arg, d_str, s_str); + gb_string_free(s_str); + gb_string_free(d_str); + gb_string_free(s_arg); + gb_string_free(d_arg); return false; } @@ -2982,22 +2989,25 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *vector_type = base_type(operand->type); if (!is_type_vector(vector_type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "You can only `swizzle` a vector, got `%s`", type_str); + gb_string_free(type_str); return false; } isize max_count = vector_type->Vector.count; isize arg_count = 0; for_array(i, ce->args) { - if (i == 0) continue; + if (i == 0) { + continue; + } AstNode *arg = ce->args[i]; Operand op = {}; check_expr(c, &op, arg); - if (op.mode == Addressing_Invalid) + if (op.mode == Addressing_Invalid) { return false; + } Type *arg_type = base_type(op.type); if (!is_type_integer(arg_type) || op.mode != Addressing_Constant) { error(ast_node_token(op.expr), "Indices to `swizzle` must be constant integers"); @@ -3138,10 +3148,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *ptr_type = base_type(operand->type); if (!is_type_pointer(ptr_type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a pointer to `slice_ptr`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3163,10 +3173,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; if (!is_type_integer(op.type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Length for `slice_ptr` must be an integer, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3176,10 +3186,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) return false; if (!is_type_integer(op.type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Capacity for `slice_ptr` must be an integer, got `%s`", type_str); + gb_string_free(type_str); return false; } if (ce->args.count > 3) { @@ -3198,10 +3208,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = base_type(operand->type); if (!is_type_comparable(type) || !is_type_numeric(type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a comparable numeric type to `min`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3214,10 +3224,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (!is_type_comparable(b.type) || !is_type_numeric(type)) { gbString type_str = type_to_string(b.type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a comparable numeric type to `min`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3251,11 +3261,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (!are_types_identical(operand->type, b.type)) { gbString type_a = type_to_string(a.type); gbString type_b = type_to_string(b.type); - defer (gb_string_free(type_a)); - defer (gb_string_free(type_b)); error(ast_node_token(call), "Mismatched types to `min`, `%s` vs `%s`", type_a, type_b); + gb_string_free(type_b); + gb_string_free(type_a); return false; } } @@ -3267,10 +3277,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = base_type(operand->type); if (!is_type_comparable(type) || !is_type_numeric(type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a comparable numeric type to `max`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3283,10 +3293,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (!is_type_comparable(b.type) || !is_type_numeric(type)) { gbString type_str = type_to_string(b.type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a comparable numeric type to `max`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3320,11 +3330,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) if (!are_types_identical(operand->type, b.type)) { gbString type_a = type_to_string(a.type); gbString type_b = type_to_string(b.type); - defer (gb_string_free(type_a)); - defer (gb_string_free(type_b)); error(ast_node_token(call), "Mismatched types to `max`, `%s` vs `%s`", type_a, type_b); + gb_string_free(type_b); + gb_string_free(type_a); return false; } } @@ -3336,10 +3346,10 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = base_type(operand->type); if (!is_type_numeric(type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); error(ast_node_token(call), "Expected a numeric type to `abs`, got `%s`", type_str); + gb_string_free(type_str); return false; } @@ -3366,7 +3376,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) Type *type = base_type(operand->type); if (!is_type_enum(type)) { gbString type_str = type_to_string(operand->type); - defer (gb_string_free(type_str)); + gb_string_free(type_str); error(ast_node_token(call), "Expected an enum to `enum_to_string`, got `%s`", type_str); @@ -3374,7 +3384,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } if (operand->mode == Addressing_Constant) { - ExactValue value = make_exact_value_string(make_string("")); + ExactValue value = make_exact_value_string(str_lit("")); if (operand->value.kind == ExactValue_Integer) { i64 index = operand->value.value_integer; for (isize i = 0; i < type->Record.other_field_count; i++) { @@ -3435,7 +3445,6 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode } gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); Array operands; array_init(&operands, c->tmp_allocator, 2*param_count); @@ -3451,7 +3460,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode error(ast_node_token(ce->args[i]), "`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count); operand->mode = Addressing_Invalid; - return; + goto end; } for (isize j = 0; j < tuple->variable_count; j++) { o.type = tuple->variables[j]->type; @@ -3473,10 +3482,10 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode } gbString proc_str = expr_to_string(ce->proc); - defer (gb_string_free(proc_str)); error(ast_node_token(call), err_fmt, proc_str, param_count); + gb_string_free(proc_str); operand->mode = Addressing_Invalid; - return; + goto end; } GB_ASSERT(proc_type->Proc.params != NULL); @@ -3488,7 +3497,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode if (variadic) { o = operands[operand_index]; } - check_assignment(c, &o, arg_type, make_string("argument"), true); + check_assignment(c, &o, arg_type, str_lit("argument"), true); } if (variadic) { @@ -3508,9 +3517,11 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode break; } } - check_assignment(c, &o, t, make_string("argument"), true); + check_assignment(c, &o, t, str_lit("argument"), true); } } +end: + gb_temp_arena_memory_end(tmp); } @@ -3566,8 +3577,8 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) { if (proc_type == NULL || proc_type->kind != Type_Proc) { AstNode *e = operand->expr; gbString str = expr_to_string(e); - defer (gb_string_free(str)); error(ast_node_token(e), "Cannot call a non-procedure: `%s`", str); + gb_string_free(str); operand->mode = Addressing_Invalid; operand->expr = call; @@ -3612,8 +3623,8 @@ void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) { } if (err_str != NULL) { gbString str = expr_to_string(e); - defer (gb_string_free(str)); error(ast_node_token(e), "`%s` %s", str, err_str); + gb_string_free(str); o->mode = Addressing_Invalid; } } @@ -3653,17 +3664,18 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint case_ast_node(pl, ProcLit, node); check_open_scope(c, pl->type); - defer (check_close_scope(c)); c->context.decl = make_declaration_info(c->allocator, c->context.scope); Type *proc_type = check_type(c, pl->type); if (proc_type != NULL) { check_proc_body(c, empty_token, c->context.decl, proc_type, pl->body); o->mode = Addressing_Value; o->type = proc_type; + check_close_scope(c); } else { gbString str = expr_to_string(node); error(ast_node_token(node), "Invalid procedure literal `%s`", str); gb_string_free(str); + check_close_scope(c); goto error; } case_end; @@ -3722,9 +3734,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint ast_node(fv, FieldValue, elem); if (fv->field->kind != AstNode_Ident) { gbString expr_str = expr_to_string(fv->field); - defer (gb_string_free(expr_str)); error(ast_node_token(elem), "Invalid field name `%s` in structure literal", expr_str); + gb_string_free(expr_str); continue; } String name = fv->field->Ident.string; @@ -3762,7 +3774,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } - check_assignment(c, o, field->type, make_string("structure literal")); + check_assignment(c, o, field->type, str_lit("structure literal")); } } else { for_array(index, cl->elems) { @@ -3787,7 +3799,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint is_constant = o->mode == Addressing_Constant; } - check_assignment(c, o, field->type, make_string("structure literal")); + check_assignment(c, o, field->type, str_lit("structure literal")); } if (cl->elems.count < field_count) { error(cl->close, "Too few values in structure literal, expected %td, got %td", field_count, cl->elems.count); @@ -3805,13 +3817,13 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint String context_name = {}; if (t->kind == Type_Slice) { elem_type = t->Slice.elem; - context_name = make_string("slice literal"); + context_name = str_lit("slice literal"); } else if (t->kind == Type_Vector) { elem_type = t->Vector.elem; - context_name = make_string("vector literal"); + context_name = str_lit("vector literal"); } else { elem_type = t->Array.elem; - context_name = make_string("array literal"); + context_name = str_lit("array literal"); } @@ -4136,7 +4148,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint if (t->kind == Type_Maybe) { Entity **variables = gb_alloc_array(c->allocator, Entity *, 2); Type *elem = t->Maybe.elem; - Token tok = make_token_ident(make_string("")); + Token tok = make_token_ident(str_lit("")); variables[0] = make_entity_param(c->allocator, NULL, tok, elem, false); variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false); @@ -4208,8 +4220,6 @@ ExprKind check_expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) void check_multi_expr(Checker *c, Operand *o, AstNode *e) { gbString err_str = NULL; - defer (gb_string_free(err_str)); - check_expr_base(c, o, e); switch (o->mode) { default: @@ -4224,6 +4234,7 @@ void check_multi_expr(Checker *c, Operand *o, AstNode *e) { error(ast_node_token(e), "`%s` is not an expression", err_str); break; } + gb_string_free(err_str); o->mode = Addressing_Invalid; } @@ -4251,10 +4262,10 @@ void check_expr_or_type(Checker *c, Operand *o, AstNode *e) { check_not_tuple(c, o); if (o->mode == Addressing_NoValue) { gbString str = expr_to_string(o->expr); - defer (gb_string_free(str)); error(ast_node_token(o->expr), "`%s` used as value or type", str); o->mode = Addressing_Invalid; + gb_string_free(str); } } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index ecfc48cdd..b5db09efc 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -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 delayed_const; array_init(&delayed_const, c->tmp_allocator, stmts.count); Array 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 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 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; - - } } diff --git a/src/checker/types.cpp b/src/checker/types.cpp index 965798be9..c10b8e6f1 100644 --- a/src/checker/types.cpp +++ b/src/checker/types.cpp @@ -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; diff --git a/src/common.cpp b/src/common.cpp index e07ea362a..ee4ca9817 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -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 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 *h) { template void map_rehash(Map *h, isize new_count) { isize i, j; - Map nh = {}; + Map nh = {0}; map_init(&nh, h->hashes.allocator); array_resize(&nh.hashes, new_count); array_reserve(&nh.entries, h->entries.count); diff --git a/src/gb/gb.h b/src/gb/gb.h index 6c6cc4037..1094c11b4 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -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 struct gbRemoveReference { typedef T Type; }; diff --git a/src/main.cpp b/src/main.cpp index 6fea6d583..a7a95a555 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,12 +16,13 @@ // NOTE(bill): `name` is used in debugging and profiling modes i32 win32_exec_command_line_app(char *name, char *fmt, ...) { STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; - PROCESS_INFORMATION pi = {}; - char cmd_line[4096] = {}; + PROCESS_INFORMATION pi = {0}; + char cmd_line[4096] = {0}; isize cmd_len; va_list va; gbTempArenaMemory tmp; String16 cmd; + i32 exit_code = 0; start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_SHOW; @@ -35,57 +36,55 @@ i32 win32_exec_command_line_app(char *name, char *fmt, ...) { // gb_printf("%.*s\n", cast(int)cmd_len, cmd_line); tmp = gb_temp_arena_memory_begin(&string_buffer_arena); - defer (gb_temp_arena_memory_end(tmp)); cmd = string_to_string16(string_buffer_allocator, make_string(cast(u8 *)cmd_line, cmd_len-1)); if (CreateProcessW(NULL, cmd.text, NULL, NULL, true, 0, NULL, NULL, &start_info, &pi)) { - DWORD exit_code = 0; - WaitForSingleObject(pi.hProcess, INFINITE); - GetExitCodeProcess(pi.hProcess, &exit_code); + GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - - return cast(i32)exit_code; } else { // NOTE(bill): failed to create process gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line); - return -1; + exit_code = -1; } + + gb_temp_arena_memory_end(tmp); + return exit_code; } -enum ArchKind { +typedef enum { ArchKind_x64, ArchKind_x86, -}; +} ArchKind; -struct ArchData { +typedef struct { BaseTypeSizes sizes; String llc_flags; String link_flags; -}; +} ArchData; ArchData make_arch_data(ArchKind kind) { - ArchData data = {}; + ArchData data = {0}; switch (kind) { case ArchKind_x64: default: data.sizes.word_size = 8; data.sizes.max_align = 16; - data.llc_flags = make_string("-march=x86-64 "); - data.link_flags = make_string("/machine:x64 "); + data.llc_flags = str_lit("-march=x86-64 "); + data.link_flags = str_lit("/machine:x64 "); break; case ArchKind_x86: data.sizes.word_size = 4; data.sizes.max_align = 8; - data.llc_flags = make_string("-march=x86 "); - data.link_flags = make_string("/machine:x86 "); + data.llc_flags = str_lit("-march=x86 "); + data.link_flags = str_lit("/machine:x86 "); break; } @@ -110,9 +109,9 @@ int main(int argc, char **argv) { } prof_init(); - Timings timings = {}; - timings_init(&timings, make_string("Total Time"), 128); - defer (timings_destroy(&timings)); + Timings timings = {0}; + timings_init(&timings, str_lit("Total Time"), 128); + // defer (timings_destroy(&timings)); #if 1 init_string_buffer_memory(); @@ -124,13 +123,13 @@ int main(int argc, char **argv) { char *init_filename = NULL; b32 run_output = false; - String arg1 = make_string(argv[1]); - if (arg1 == "run") { + String arg1 = make_string_c(argv[1]); + if (str_eq(arg1, str_lit("run"))) { run_output = true; init_filename = argv[2]; - } else if (arg1 == "build") { + } else if (str_eq(arg1, str_lit("build"))) { init_filename = argv[2]; - } else if (arg1 == "version") { + } else if (str_eq(arg1, str_lit("version"))) { gb_printf("%s version %s", argv[0], VERSION_STRING); return 0; } else { @@ -140,7 +139,7 @@ int main(int argc, char **argv) { // TODO(bill): prevent compiling without a linker - timings_start_section(&timings, make_string("parse files")); + timings_start_section(&timings, str_lit("parse files")); Parser parser = {0}; if (!init_parser(&parser)) { @@ -154,9 +153,9 @@ int main(int argc, char **argv) { #if 1 - timings_start_section(&timings, make_string("type check")); + timings_start_section(&timings, str_lit("type check")); - Checker checker = {}; + Checker checker = {0}; ArchData arch_data = make_arch_data(ArchKind_x64); init_checker(&checker, &parser, arch_data.sizes); @@ -168,25 +167,25 @@ int main(int argc, char **argv) { #endif #if 1 - ssaGen ssa = {}; + ssaGen ssa = {0}; if (!ssa_gen_init(&ssa, &checker)) { return 1; } // defer (ssa_gen_destroy(&ssa)); - timings_start_section(&timings, make_string("ssa gen")); + timings_start_section(&timings, str_lit("ssa gen")); ssa_gen_tree(&ssa); - timings_start_section(&timings, make_string("ssa opt")); + timings_start_section(&timings, str_lit("ssa opt")); ssa_opt_tree(&ssa); - timings_start_section(&timings, make_string("ssa print")); + timings_start_section(&timings, str_lit("ssa print")); ssa_print_llvm_ir(&ssa); // prof_print_all(); #if 1 - timings_start_section(&timings, make_string("llvm-opt")); + timings_start_section(&timings, str_lit("llvm-opt")); char const *output_name = ssa.output_file.filename; isize base_name_len = gb_path_extension(output_name)-1 - output_name; @@ -213,7 +212,7 @@ int main(int argc, char **argv) { } #if 1 - timings_start_section(&timings, make_string("llvm-llc")); + timings_start_section(&timings, str_lit("llvm-llc")); // For more arguments: http://llvm.org/docs/CommandGuide/llc.html exit_code = win32_exec_command_line_app("llvm-llc", "%.*sbin/llc %.*s.bc -filetype=obj -O%d " @@ -228,11 +227,11 @@ int main(int argc, char **argv) { return exit_code; } - timings_start_section(&timings, make_string("msvc-link")); + timings_start_section(&timings, str_lit("msvc-link")); gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib"); // defer (gb_string_free(lib_str)); - char lib_str_buf[1024] = {}; + char lib_str_buf[1024] = {0}; for_array(i, parser.foreign_libraries) { String lib = parser.foreign_libraries[i]; isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf), @@ -243,7 +242,7 @@ int main(int argc, char **argv) { exit_code = win32_exec_command_line_app("msvc-link", "link %.*s.obj -OUT:%.*s.exe %s " "/defaultlib:libcmt " - "/nologo /incremental:no /opt:ref /subsystem:console /debug " + "/nologo /incremental:no /opt:ref /subsystem:console " " %.*s " "", LIT(output), LIT(output), diff --git a/src/parser.cpp b/src/parser.cpp index d263fa1dd..ae6043204 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1133,7 +1133,7 @@ AstNode *parse_identifier(AstFile *f) { if (token.kind == Token_Identifier) { next_token(f); } else { - token.string = make_string("_"); + token.string = str_lit("_"); expect_token(f, Token_Identifier); } return make_ident(f, token); @@ -1274,11 +1274,11 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n String tag_name = te->name.string; #define ELSE_IF_ADD_TAG(name) \ - else if (tag_name == #name) { \ + else if (str_eq(tag_name, str_lit(#name))) { \ check_proc_add_tag(f, tag_expr, tags, ProcTag_##name, tag_name); \ } - if (tag_name == "foreign") { + if (str_eq(tag_name, str_lit("foreign"))) { check_proc_add_tag(f, tag_expr, tags, ProcTag_foreign, tag_name); if (f->curr_token.kind == Token_String) { *foreign_name = f->curr_token.string; @@ -1289,7 +1289,7 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name, String *link_n next_token(f); } - } else if (tag_name == "link_name") { + } else if (str_eq(tag_name, str_lit("link_name"))) { check_proc_add_tag(f, tag_expr, tags, ProcTag_link_name, tag_name); if (f->curr_token.kind == Token_String) { *link_name = f->curr_token.string; @@ -1372,7 +1372,7 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { case Token_Hash: { Token token = expect_token(f, Token_Hash); Token name = expect_token(f, Token_Identifier); - if (name.string == "rune") { + if (str_eq(name.string, str_lit("rune"))) { if (f->curr_token.kind == Token_String) { Token *s = &f->curr_token; @@ -1384,19 +1384,19 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { expect_token(f, Token_String); } operand = parse_operand(f, lhs); - } else if (name.string == "file") { + } else if (str_eq(name.string, str_lit("file"))) { Token token = name; token.kind = Token_String; token.string = token.pos.file; return make_basic_lit(f, token); - } else if (name.string == "line") { + } else if (str_eq(name.string, str_lit("line"))) { Token token = name; token.kind = Token_Integer; char *str = gb_alloc_array(gb_arena_allocator(&f->arena), char, 20); gb_i64_to_str(token.pos.line, str, 10); - token.string = make_string(str); + token.string = make_string_c(str); return make_basic_lit(f, token); - } else if (name.string == "run") { + } else if (str_eq(name.string, str_lit("run"))) { AstNode *expr = parse_expr(f, false); operand = make_run_expr(f, token, name, expr); if (unparen_expr(expr)->kind != AstNode_CallExpr) { @@ -1415,7 +1415,6 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { AstNode *curr_proc = f->curr_proc; AstNode *type = parse_proc_type(f); f->curr_proc = type; - defer (f->curr_proc = curr_proc); u64 tags = 0; String foreign_name = {}; @@ -1428,17 +1427,17 @@ AstNode *parse_operand(AstFile *f, b32 lhs) { syntax_error(f->curr_token, "#link_name cannot be applied to procedure literals"); } - if (f->curr_token.kind != Token_OpenBrace) { - return type; - } else { + if (f->curr_token.kind == Token_OpenBrace) { AstNode *body; f->expr_level++; body = parse_body(f); f->expr_level--; - return make_proc_lit(f, type, body, tags); + type = make_proc_lit(f, type, body, tags); } + f->curr_proc = curr_proc; + return type; } default: { @@ -2087,12 +2086,12 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) { b32 is_ordered = false; while (allow_token(f, Token_Hash)) { Token tag = expect_token_after(f, Token_Identifier, "`#`"); - if (tag.string == "packed") { + if (str_eq(tag.string, str_lit("packed"))) { if (is_packed) { syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); } is_packed = true; - } else if (tag.string == "ordered") { + } else if (str_eq(tag.string, str_lit("ordered"))) { if (is_ordered) { syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); } @@ -2264,7 +2263,6 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { AstNode *curr_proc = f->curr_proc; f->curr_proc = proc_type; - defer (f->curr_proc = curr_proc); if (f->curr_token.kind == Token_OpenBrace) { if ((tags & ProcTag_foreign) != 0) { @@ -2273,6 +2271,7 @@ AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) { body = parse_body(f); } + f->curr_proc = curr_proc; return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name); } @@ -2285,7 +2284,7 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) { if (name->kind == AstNode_Ident) { String n = name->Ident.string; // NOTE(bill): Check for reserved identifiers - if (n == "context") { + if (str_eq(n, str_lit("context"))) { syntax_error(ast_node_token(name), "`context` is a reserved identifier"); break; } @@ -2399,7 +2398,7 @@ AstNode *parse_if_stmt(AstFile *f) { if (allow_token(f, Token_Semicolon)) { cond = parse_expr(f, false); } else { - cond = convert_stmt_to_expr(f, init, make_string("boolean expression")); + cond = convert_stmt_to_expr(f, init, str_lit("boolean expression")); init = NULL; } } @@ -2489,7 +2488,7 @@ AstNode *parse_for_stmt(AstFile *f) { } body = parse_block_stmt(f); - cond = convert_stmt_to_expr(f, cond, make_string("boolean expression")); + cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression")); return make_for_stmt(f, token, init, cond, end, body); } @@ -2559,7 +2558,7 @@ AstNode *parse_match_stmt(AstFile *f) { close = expect_token(f, Token_CloseBrace); body = make_block_stmt(f, list, open, close); - tag = convert_stmt_to_expr(f, tag, make_string("type match expression")); + tag = convert_stmt_to_expr(f, tag, str_lit("type match expression")); return make_type_match_stmt(f, token, tag, var, body); } else { if (f->curr_token.kind != Token_OpenBrace) { @@ -2591,7 +2590,7 @@ AstNode *parse_match_stmt(AstFile *f) { body = make_block_stmt(f, list, open, close); - tag = convert_stmt_to_expr(f, tag, make_string("match expression")); + tag = convert_stmt_to_expr(f, tag, str_lit("match expression")); return make_match_stmt(f, token, init, tag, body); } } @@ -2747,14 +2746,14 @@ AstNode *parse_stmt(AstFile *f) { case Token_Hash: { s = parse_tag_stmt(f, NULL); String tag = s->TagStmt.name.string; - if (tag == "shared_global_scope") { + if (str_eq(tag, str_lit("shared_global_scope"))) { if (f->curr_proc == NULL) { f->is_global_scope = true; return make_empty_stmt(f, f->curr_token); } syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope"); return make_bad_decl(f, token, f->curr_token); - } else if (tag == "import") { + } else if (str_eq(tag, str_lit("import"))) { // TODO(bill): better error messages Token import_name = {}; Token file_path = expect_token_after(f, Token_String, "#import"); @@ -2768,7 +2767,7 @@ AstNode *parse_stmt(AstFile *f) { import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration"); } - if (import_name.string == "_") { + if (str_eq(import_name.string, str_lit("_"))) { syntax_error(token, "Illegal import name: `_`"); return make_bad_decl(f, token, f->curr_token); } @@ -2779,32 +2778,32 @@ AstNode *parse_stmt(AstFile *f) { } syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope"); return make_bad_decl(f, token, file_path); - } else if (tag == "load") { + } else if (str_eq(tag, str_lit("load"))) { // TODO(bill): better error messages Token file_path = expect_token(f, Token_String); Token import_name = file_path; - import_name.string = make_string("."); + import_name.string = str_lit("."); if (f->curr_proc == NULL) { return make_import_decl(f, s->TagStmt.token, file_path, import_name, true); } syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope"); return make_bad_decl(f, token, file_path); - } else if (tag == "foreign_system_library") { + } else if (str_eq(tag, str_lit("foreign_system_library"))) { Token file_path = expect_token(f, Token_String); if (f->curr_proc == NULL) { return make_foreign_library(f, s->TagStmt.token, file_path, true); } syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope"); return make_bad_decl(f, token, file_path); - } else if (tag == "foreign_library") { + } else if (str_eq(tag, str_lit("foreign_library"))) { Token file_path = expect_token(f, Token_String); if (f->curr_proc == NULL) { return make_foreign_library(f, s->TagStmt.token, file_path, false); } syntax_error(token, "You cannot use #foreign_library within a procedure. This must be done at the file scope"); return make_bad_decl(f, token, file_path); - } else if (tag == "thread_local") { + } else if (str_eq(tag, str_lit("thread_local"))) { AstNode *var_decl = parse_simple_stmt(f); if (var_decl->kind != AstNode_VarDecl) { syntax_error(token, "#thread_local may only be applied to variable declarations"); @@ -2816,14 +2815,14 @@ AstNode *parse_stmt(AstFile *f) { } var_decl->VarDecl.tags |= VarDeclTag_thread_local; return var_decl; - } else if (tag == "bounds_check") { + } else if (str_eq(tag, str_lit("bounds_check"))) { s = parse_stmt(f); s->stmt_state_flags |= StmtStateFlag_bounds_check; if ((s->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) { syntax_error(token, "#bounds_check and #no_bounds_check cannot be applied together"); } return s; - } else if (tag == "no_bounds_check") { + } else if (str_eq(tag, str_lit("no_bounds_check"))) { s = parse_stmt(f); s->stmt_state_flags |= StmtStateFlag_no_bounds_check; if ((s->stmt_state_flags & StmtStateFlag_bounds_check) != 0) { @@ -2870,7 +2869,7 @@ AstNodeArray parse_stmt_list(AstFile *f) { ParseFileError init_ast_file(AstFile *f, String fullpath) { - if (!string_has_extension(fullpath, make_string("odin"))) { + if (!string_has_extension(fullpath, str_lit("odin"))) { return ParseFile_WrongExtension; } TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath); @@ -2951,11 +2950,10 @@ void destroy_parser(Parser *p) { // NOTE(bill): Returns true if it's added b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) { gb_mutex_lock(&p->mutex); - defer (gb_mutex_unlock(&p->mutex)); for_array(i, p->imports) { String import = p->imports[i].path; - if (import == path) { + if (str_eq(import, path)) { return false; } } @@ -2965,52 +2963,59 @@ b32 try_add_import_path(Parser *p, String path, String rel_path, TokenPos pos) { item.rel_path = rel_path; item.pos = pos; array_add(&p->imports, item); + + gb_mutex_unlock(&p->mutex); + return true; } String get_fullpath_relative(gbAllocator a, String base_dir, String path) { + String res = {}; isize str_len = base_dir.len+path.len; u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1); - defer (gb_free(heap_allocator(), str)); isize i = 0; gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len; gb_memmove(str+i, path.text, path.len); str[str_len] = '\0'; - return path_to_fullpath(a, make_string(str, str_len)); + res = path_to_fullpath(a, make_string(str, str_len)); + gb_free(heap_allocator(), str); + return res; } String get_fullpath_core(gbAllocator a, String path) { String module_dir = get_module_dir(); + String res = {}; char core[] = "core/"; isize core_len = gb_size_of(core)-1; isize str_len = module_dir.len + core_len + path.len; u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1); - defer (gb_free(heap_allocator(), str)); gb_memmove(str, module_dir.text, module_dir.len); gb_memmove(str+module_dir.len, core, core_len); gb_memmove(str+module_dir.len+core_len, path.text, path.len); str[str_len] = '\0'; - return path_to_fullpath(a, make_string(str, str_len)); + res = path_to_fullpath(a, make_string(str, str_len)); + gb_free(heap_allocator(), str); + return res; } // NOTE(bill): Returns true if it's added b32 try_add_foreign_library_path(Parser *p, String import_file) { gb_mutex_lock(&p->mutex); - defer (gb_mutex_unlock(&p->mutex)); for_array(i, p->foreign_libraries) { String import = p->foreign_libraries[i]; - if (import == import_file) { + if (str_eq(import, import_file)) { return false; } } array_add(&p->foreign_libraries, import_file); + gb_mutex_unlock(&p->mutex); return true; } @@ -3064,7 +3069,7 @@ String get_filepath_extension(String path) { if (c == '.') { if (seen_slash) { - return make_string(""); + return str_lit(""); } dot = i; @@ -3166,19 +3171,19 @@ void parse_file(Parser *p, AstFile *f) { ParseFileError parse_files(Parser *p, char *init_filename) { char *fullpath_str = gb_path_get_full_name(heap_allocator(), init_filename); - String init_fullpath = make_string(fullpath_str); + String init_fullpath = make_string_c(fullpath_str); TokenPos init_pos = {}; ImportedFile init_imported_file = {init_fullpath, init_fullpath, init_pos}; array_add(&p->imports, init_imported_file); p->init_fullpath = init_fullpath; { - String s = get_fullpath_core(heap_allocator(), make_string("_preload.odin")); + String s = get_fullpath_core(heap_allocator(), str_lit("_preload.odin")); ImportedFile runtime_file = {s, s, init_pos}; array_add(&p->imports, runtime_file); } { - String s = get_fullpath_core(heap_allocator(), make_string("_soft_numbers.odin")); + String s = get_fullpath_core(heap_allocator(), str_lit("_soft_numbers.odin")); ImportedFile runtime_file = {s, s, init_pos}; array_add(&p->imports, runtime_file); } @@ -3196,7 +3201,6 @@ ParseFileError parse_files(Parser *p, char *init_filename) { gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column); } gb_printf_err("Failed to parse file: %.*s\n\t", LIT(import_rel_path)); - defer (gb_printf_err("\n")); switch (err) { case ParseFile_WrongExtension: gb_printf_err("Invalid file extension: File must have the extension `.odin`"); @@ -3217,16 +3221,16 @@ ParseFileError parse_files(Parser *p, char *init_filename) { gb_printf_err("Invalid token found in file"); break; } + gb_printf_err("\n"); return err; } parse_file(p, &file); { gb_mutex_lock(&p->mutex); - defer (gb_mutex_unlock(&p->mutex)); - file.id = p->files.count; array_add(&p->files, file); + gb_mutex_unlock(&p->mutex); } } diff --git a/src/ssa.cpp b/src/ssa.cpp index 0563f0022..76ec843a8 100644 --- a/src/ssa.cpp +++ b/src/ssa.cpp @@ -1085,7 +1085,7 @@ ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) { } ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block); - v->Block.label = make_string(label); + v->Block.label = make_string_c(label); v->Block.node = node; v->Block.scope = scope; v->Block.parent = proc; @@ -1346,7 +1346,7 @@ ssaValue *ssa_emit_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize } ssaValue *ssa_emit_global_call(ssaProcedure *proc, char *name_, ssaValue **args, isize arg_count) { - String name = make_string(name_); + String name = make_string_c(name_); ssaValue **found = map_get(&proc->module->members, hash_string(name)); GB_ASSERT_MSG(found != NULL, "%.*s", LIT(name)); ssaValue *gp = *found; @@ -1425,7 +1425,7 @@ void ssa_emit_if(ssaProcedure *proc, ssaValue *cond, ssaBlock *true_block, ssaBl } void ssa_emit_startup_runtime(ssaProcedure *proc) { - GB_ASSERT(proc->parent == NULL && proc->name == "main"); + GB_ASSERT(proc->parent == NULL && str_eq(proc->name, str_lit("main"))); ssa_emit(proc, ssa_alloc_instr(proc, ssaInstr_StartupRuntime)); } @@ -1896,7 +1896,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { } } } - return make_string(""); + return str_lit(""); } ssaValue *ssa_emit_bitcast(ssaProcedure *proc, ssaValue *data, Type *type) { @@ -2017,7 +2017,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { for (isize i = 0; i < dst->Record.field_count; i++) { Entity *f = dst->Record.fields[i]; if (are_types_identical(f->type, src_type)) { - ssa_emit_comment(proc, make_string("union - child to parent")); + ssa_emit_comment(proc, str_lit("union - child to parent")); gbAllocator allocator = proc->module->allocator; ssaValue *parent = ssa_add_local_generated(proc, t); ssaValue *tag = ssa_make_const_int(allocator, i); @@ -2047,7 +2047,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) { // NOTE(bill): It can be casted Selection sel = lookup_field(proc->module->allocator, sb, field_name, false); if (sel.entity != NULL) { - ssa_emit_comment(proc, make_string("cast - polymorphism")); + ssa_emit_comment(proc, str_lit("cast - polymorphism")); if (src_is_ptr) { value = ssa_emit_load(proc, value); } @@ -2230,7 +2230,6 @@ ssaValue *ssa_emit_down_cast(ssaProcedure *proc, ssaValue *value, Type *t) { String field_name = check_down_cast_name(t, type_deref(ssa_type(value))); GB_ASSERT(field_name.len > 0); Selection sel = lookup_field(proc->module->allocator, t, field_name, false); - Type *t_u8_ptr = make_type_pointer(allocator, t_u8); ssaValue *bytes = ssa_emit_conv(proc, value, t_u8_ptr); i64 offset_ = type_offset_of_from_selection(proc->module->sizes, allocator, type_deref(t), sel); @@ -2355,7 +2354,7 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) { } ssaValue *ssa_type_info(ssaProcedure *proc, Type *type) { - ssaValue **found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME))); + ssaValue **found = map_get(&proc->module->members, hash_string(str_lit(SSA_TYPE_INFO_DATA_NAME))); GB_ASSERT(found != NULL); ssaValue *type_info_data = *found; CheckerInfo *info = proc->module->info; @@ -2558,7 +2557,7 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) { ssa_emit_jump(proc, b); } proc->curr_block = b; - ssa_emit_comment(proc, make_string("defer")); + ssa_emit_comment(proc, str_lit("defer")); if (d.kind == ssaDefer_Node) { ssa_build_stmt(proc, d.stmt); } else if (d.kind == ssaDefer_Instr) { @@ -2700,19 +2699,19 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue return ssa_emit_logical_binary_expr(proc, expr); case Token_as: - ssa_emit_comment(proc, make_string("cast - as")); + ssa_emit_comment(proc, str_lit("cast - as")); return ssa_emit_conv(proc, left, type); case Token_transmute: - ssa_emit_comment(proc, make_string("cast - transmute")); + ssa_emit_comment(proc, str_lit("cast - transmute")); return ssa_emit_transmute(proc, left, type); case Token_down_cast: - ssa_emit_comment(proc, make_string("cast - down_cast")); + ssa_emit_comment(proc, str_lit("cast - down_cast")); return ssa_emit_down_cast(proc, left, type); case Token_union_cast: - ssa_emit_comment(proc, make_string("cast - union_cast")); + ssa_emit_comment(proc, str_lit("cast - union_cast")); return ssa_emit_union_cast(proc, left, type); default: @@ -2764,7 +2763,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_new: { - ssa_emit_comment(proc, make_string("new")); + ssa_emit_comment(proc, str_lit("new")); // new :: proc(Type) -> ^Type gbAllocator allocator = proc->module->allocator; @@ -2783,7 +2782,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_new_slice: { - ssa_emit_comment(proc, make_string("new_slice")); + ssa_emit_comment(proc, str_lit("new_slice")); // new_slice :: proc(Type, len: int[, cap: int]) -> ^Type gbAllocator allocator = proc->module->allocator; @@ -2825,7 +2824,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_assert: { - ssa_emit_comment(proc, make_string("assert")); + ssa_emit_comment(proc, str_lit("assert")); ssaValue *cond = ssa_build_expr(proc, ce->args[0]); GB_ASSERT(is_type_boolean(ssa_type(cond))); @@ -2840,11 +2839,12 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue Token token = ast_node_token(ce->args[0]); TokenPos pos = token.pos; gbString expr = expr_to_string(ce->args[0]); - defer (gb_string_free(expr)); isize expr_len = gb_string_length(expr); String expr_str = {}; expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1); expr_str.len = expr_len; + gb_string_free(expr); + ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 4); args[0] = ssa_make_const_string(proc->module->allocator, pos.file); @@ -2860,7 +2860,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_panic: { - ssa_emit_comment(proc, make_string("panic")); + ssa_emit_comment(proc, str_lit("panic")); ssaValue *msg = ssa_build_expr(proc, ce->args[0]); GB_ASSERT(is_type_string(ssa_type(msg))); @@ -2879,7 +2879,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue case BuiltinProc_copy: { - ssa_emit_comment(proc, make_string("copy")); + ssa_emit_comment(proc, str_lit("copy")); // copy :: proc(dst, src: []Type) -> int AstNode *dst_node = ce->args[0]; AstNode *src_node = ce->args[1]; @@ -2913,7 +2913,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue return len; } break; case BuiltinProc_append: { - ssa_emit_comment(proc, make_string("append")); + ssa_emit_comment(proc, str_lit("append")); // append :: proc(s: ^[]Type, item: Type) -> bool AstNode *sptr_node = ce->args[0]; AstNode *item_node = ce->args[1]; @@ -2970,7 +2970,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_swizzle: { - ssa_emit_comment(proc, make_string("swizzle")); + ssa_emit_comment(proc, str_lit("swizzle")); ssaValue *vector = ssa_build_expr(proc, ce->args[0]); isize index_count = ce->args.count-1; if (index_count == 0) { @@ -2993,14 +2993,14 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue #if 0 case BuiltinProc_ptr_offset: { - ssa_emit_comment(proc, make_string("ptr_offset")); + ssa_emit_comment(proc, str_lit("ptr_offset")); ssaValue *ptr = ssa_build_expr(proc, ce->args[0]); ssaValue *offset = ssa_build_expr(proc, ce->args[1]); return ssa_emit_ptr_offset(proc, ptr, offset); } break; case BuiltinProc_ptr_sub: { - ssa_emit_comment(proc, make_string("ptr_sub")); + ssa_emit_comment(proc, str_lit("ptr_sub")); ssaValue *ptr_a = ssa_build_expr(proc, ce->args[0]); ssaValue *ptr_b = ssa_build_expr(proc, ce->args[1]); Type *ptr_type = base_type(ssa_type(ptr_a)); @@ -3018,7 +3018,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue #endif case BuiltinProc_slice_ptr: { - ssa_emit_comment(proc, make_string("slice_ptr")); + ssa_emit_comment(proc, str_lit("slice_ptr")); ssaValue *ptr = ssa_build_expr(proc, ce->args[0]); ssaValue *len = ssa_build_expr(proc, ce->args[1]); ssaValue *cap = len; @@ -3040,7 +3040,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_min: { - ssa_emit_comment(proc, make_string("min")); + ssa_emit_comment(proc, str_lit("min")); ssaValue *x = ssa_build_expr(proc, ce->args[0]); ssaValue *y = ssa_build_expr(proc, ce->args[1]); Type *t = base_type(ssa_type(x)); @@ -3049,7 +3049,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_max: { - ssa_emit_comment(proc, make_string("max")); + ssa_emit_comment(proc, str_lit("max")); ssaValue *x = ssa_build_expr(proc, ce->args[0]); ssaValue *y = ssa_build_expr(proc, ce->args[1]); Type *t = base_type(ssa_type(x)); @@ -3058,7 +3058,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_abs: { - ssa_emit_comment(proc, make_string("abs")); + ssa_emit_comment(proc, str_lit("abs")); gbAllocator a = proc->module->allocator; ssaValue *x = ssa_build_expr(proc, ce->args[0]); @@ -3099,7 +3099,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } break; case BuiltinProc_enum_to_string: { - ssa_emit_comment(proc, make_string("enum_to_string")); + ssa_emit_comment(proc, str_lit("enum_to_string")); ssaValue *x = ssa_build_expr(proc, ce->args[0]); Type *t = ssa_type(x); ssaValue *ti = ssa_type_info(proc, t); @@ -3173,7 +3173,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue } if (variadic && !vari_expand) { - ssa_emit_comment(proc, make_string("variadic call argument generation")); + ssa_emit_comment(proc, str_lit("variadic call argument generation")); gbAllocator allocator = proc->module->allocator; Type *slice_type = pt->variables[type->param_count-1]->type; Type *elem_type = base_type(slice_type)->Slice.elem; @@ -3301,7 +3301,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; case_ast_node(se, SelectorExpr, expr); - ssa_emit_comment(proc, make_string("SelectorExpr")); + ssa_emit_comment(proc, str_lit("SelectorExpr")); String selector = unparen_expr(se->selector)->Ident.string; Type *type = base_type(type_of_expr(proc->module->info, se->expr)); @@ -3335,7 +3335,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_ast_node(be, BinaryExpr, expr); switch (be->op.kind) { case Token_as: { - ssa_emit_comment(proc, make_string("Cast - as")); + ssa_emit_comment(proc, str_lit("Cast - as")); // NOTE(bill): Needed for dereference of pointer conversion Type *type = type_of_expr(proc->module->info, expr); ssaValue *v = ssa_add_local_generated(proc, type); @@ -3343,7 +3343,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { return ssa_make_addr(v, expr); } case Token_transmute: { - ssa_emit_comment(proc, make_string("Cast - transmute")); + ssa_emit_comment(proc, str_lit("Cast - transmute")); // NOTE(bill): Needed for dereference of pointer conversion Type *type = type_of_expr(proc->module->info, expr); ssaValue *v = ssa_add_local_generated(proc, type); @@ -3357,7 +3357,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; case_ast_node(ie, IndexExpr, expr); - ssa_emit_comment(proc, make_string("IndexExpr")); + ssa_emit_comment(proc, str_lit("IndexExpr")); Type *t = base_type(type_of_expr(proc->module->info, ie->expr)); gbAllocator a = proc->module->allocator; @@ -3459,7 +3459,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; case_ast_node(se, SliceExpr, expr); - ssa_emit_comment(proc, make_string("SliceExpr")); + ssa_emit_comment(proc, str_lit("SliceExpr")); gbAllocator a = proc->module->allocator; ssaValue *low = v_zero; ssaValue *high = NULL; @@ -3564,7 +3564,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_end; case_ast_node(de, DemaybeExpr, expr); - ssa_emit_comment(proc, make_string("DemaybeExpr")); + ssa_emit_comment(proc, str_lit("DemaybeExpr")); ssaValue *maybe = ssa_build_expr(proc, de->expr); Type *t = default_type(type_of_expr(proc->module->info, expr)); GB_ASSERT(is_type_tuple(t)); @@ -3584,7 +3584,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { case_ast_node(cl, CompoundLit, expr); - ssa_emit_comment(proc, make_string("CompoundLit")); + ssa_emit_comment(proc, str_lit("CompoundLit")); Type *type = type_of_expr(proc->module->info, expr); Type *bt = base_type(type); ssaValue *v = ssa_add_local_generated(proc, type); @@ -3700,7 +3700,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { Type *elem_type = bt->Slice.elem; Type *elem_ptr_type = make_type_pointer(proc->module->allocator, elem_type); Type *elem_ptr_ptr_type = make_type_pointer(proc->module->allocator, elem_ptr_type); - Type *t_int_ptr = make_type_pointer(proc->module->allocator, t_int); ssaValue *slice = ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)); GB_ASSERT(slice->kind == ssaValue_ConstantSlice); @@ -3807,14 +3806,13 @@ void ssa_build_stmt_list(ssaProcedure *proc, AstNodeArray stmts) { } } +void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node); void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { u32 prev_stmt_state_flags = proc->module->stmt_state_flags; - defer (proc->module->stmt_state_flags = prev_stmt_state_flags); if (node->stmt_state_flags != 0) { u32 in = node->stmt_state_flags; u32 out = proc->module->stmt_state_flags; - defer (proc->module->stmt_state_flags = out); if (in & StmtStateFlag_bounds_check) { out |= StmtStateFlag_bounds_check; @@ -3823,9 +3821,16 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { out |= StmtStateFlag_no_bounds_check; out &= ~StmtStateFlag_bounds_check; } + + proc->module->stmt_state_flags = out; } + ssa_build_stmt_internal(proc, node); + proc->module->stmt_state_flags = prev_stmt_state_flags; +} + +void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) { switch (node->kind) { case_ast_node(bs, EmptyStmt, node); case_end; @@ -3840,7 +3845,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(vd, VarDecl, node); ssaModule *m = proc->module; gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); if (vd->values.count == 0) { // declared and zero-initialized for_array(i, vd->names) { @@ -3889,6 +3893,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_addr_store(proc, lvals[i], v); } } + + gb_temp_arena_memory_end(tmp); case_end; case_ast_node(pd, ProcDecl, node); @@ -3985,7 +3991,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(ids, IncDecStmt, node); - ssa_emit_comment(proc, make_string("IncDecStmt")); + ssa_emit_comment(proc, str_lit("IncDecStmt")); TokenKind op = ids->op.kind; if (op == Token_Increment) { op = Token_Add; @@ -3999,11 +4005,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(as, AssignStmt, node); - ssa_emit_comment(proc, make_string("AssignStmt")); + ssa_emit_comment(proc, str_lit("AssignStmt")); ssaModule *m = proc->module; gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); switch (as->op.kind) { case Token_Eq: { @@ -4073,6 +4078,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_build_assign_op(proc, lhs, value, cast(TokenKind)op); } break; } + + gb_temp_arena_memory_end(tmp); case_end; case_ast_node(es, ExprStmt, node); @@ -4087,7 +4094,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(ds, DeferStmt, node); - ssa_emit_comment(proc, make_string("DeferStmt")); + ssa_emit_comment(proc, str_lit("DeferStmt")); isize scope_index = proc->scope_index; if (ds->stmt->kind == AstNode_BlockStmt) { scope_index--; @@ -4096,7 +4103,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_end; case_ast_node(rs, ReturnStmt, node); - ssa_emit_comment(proc, make_string("ReturnStmt")); + ssa_emit_comment(proc, str_lit("ReturnStmt")); ssaValue *v = NULL; auto *return_type_tuple = &proc->type->Proc.results->Tuple; isize return_count = proc->type->Proc.result_count; @@ -4107,7 +4114,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type); } else { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena); - defer (gb_temp_arena_memory_end(tmp)); Array 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"); } diff --git a/src/ssa_opt.cpp b/src/ssa_opt.cpp index 0fb4bd873..2b572be84 100644 --- a/src/ssa_opt.cpp +++ b/src/ssa_opt.cpp @@ -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 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) { diff --git a/src/ssa_print.cpp b/src/ssa_print.cpp index 2f074008d..28df7e42c 100644 --- a/src/ssa_print.cpp +++ b/src/ssa_print.cpp @@ -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); } diff --git a/src/string.cpp b/src/string.cpp index d62a0e900..552ba2a4b 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -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 -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 gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); } -template gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); } -template gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; } -template gb_inline bool operator !=(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) != b; } +// template gb_inline bool operator ==(String a, char const (&b)[N]) { return a == make_string(cast(u8 *)b, N-1); } +// template gb_inline bool operator !=(String a, char const (&b)[N]) { return a != make_string(cast(u8 *)b, N-1); } +// template gb_inline bool operator ==(char const (&a)[N], String b) { return make_string(cast(u8 *)a, N-1) == b; } +// template 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); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index d0f14990a..42c2b7b69 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -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; } diff --git a/src/vm.cpp b/src/vm.cpp deleted file mode 100644 index db9941553..000000000 --- a/src/vm.cpp +++ /dev/null @@ -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 vm_empty_args = {}; - -struct vmFrame { - vmInterpreter *i; - vmFrame * caller; - ssaProcedure * proc; - ssaBlock * block; - ssaBlock * prev_block; - isize instr_index; // For the current block - - Array env; // Index == instr id - vmValue result; -}; - -struct vmInterpreter { - ssaModule * module; - BaseTypeSizes sizes; - gbArena stack_arena; - gbAllocator stack_allocator; - gbAllocator heap_allocator; - - Array frame_stack; - Map 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 vm_prepare_call(vmFrame *f, ssaInstr *instr, vmValue *proc) { - GB_ASSERT(instr->kind == ssaInstr_Call); - - *proc = vm_get_value(f, instr->Call.value); - - Array 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(" %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 args) { - GB_PANIC("TODO(bill): vm_ext"); - vmValue v = {}; - return v; -} - -vmValue vm_call(vmInterpreter *i, vmFrame *caller, ssaProcedure *proc, Array 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