diff --git a/code/demo.odin b/code/demo.odin index a302c39c8..282adcb67 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,25 +1,3 @@ -#import "fmt.odin" -#import "os.odin" -#import "mem.odin" - - main :: proc() { - y :: proc() -> (int, int) { - return x() - } - x :: proc() -> (int, int) { - return 1, 2 - } - fmt.println(y()) - - arena: mem.Arena - mem.init_arena_from_context(^arena, 1000) - defer mem.free_arena(^arena) - - push_allocator mem.arena_allocator(^arena) { - x := new(int) - x^ = 1337 - fmt.println(x^) - } } diff --git a/core/mem.odin b/core/mem.odin index 9ae08e830..413814653 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -27,6 +27,24 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr { } +AllocationHeader :: struct { + size: int +} +allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) { + header.size = size + ptr := ptr_offset(header, 1) as ^int + + for i := 0; ptr as rawptr < data; i++ { + ptr_offset(ptr, i)^ = -1 + } +} +allocation_header :: proc(data: rawptr) -> ^AllocationHeader { + p := data as ^int + for ptr_offset(p, -1)^ == -1 { + p = ptr_offset(p, -1) + } + return ptr_offset(p as ^AllocationHeader, -1) +} diff --git a/core/os.odin b/core/os.odin index c26213ce4..ddff334d8 100644 --- a/core/os.odin +++ b/core/os.odin @@ -103,3 +103,15 @@ read_entire_file :: proc(name: string) -> (string, bool) { return data as string, true } + + + +heap_alloc :: proc(size: int) -> rawptr { + return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size) +} +heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { + return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size) +} +heap_free :: proc(ptr: rawptr) { + win32.HeapFree(win32.GetProcessHeap(), 0, ptr) +} diff --git a/core/runtime.odin b/core/runtime.odin index 03fbb5ee7..b9881b982 100644 --- a/core/runtime.odin +++ b/core/runtime.odin @@ -2,6 +2,7 @@ #import "os.odin" #import "fmt.odin" +#import "mem.odin" // IMPORTANT NOTE(bill): Do not change the order of any of this data // The compiler relies upon this _exact_ order @@ -97,16 +98,6 @@ byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64" fmuladd32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32" fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64" -heap_alloc :: proc(len: int) -> rawptr { - c_malloc :: proc(len: int) -> rawptr #foreign "malloc" - return c_malloc(len) -} - -heap_free :: proc(ptr: rawptr) { - c_free :: proc(ptr: rawptr) #foreign "free" - c_free(ptr) -} - current_thread_id :: proc() -> int { GetCurrentThreadId :: proc() -> u32 #foreign #dll_import return GetCurrentThreadId() as int @@ -251,14 +242,26 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode, using Allocator.Mode match mode { case ALLOC: - return heap_alloc(size) - case RESIZE: - return default_resize_align(old_memory, old_size, size, alignment) + total_size := size + alignment + size_of(mem.AllocationHeader) + ptr := os.heap_alloc(total_size) + header := ptr as ^mem.AllocationHeader + ptr = mem.align_forward(ptr_offset(header, 1), alignment) + mem.allocation_header_fill(header, ptr, size) + memory_zero(ptr, size) + return ptr case FREE: - heap_free(old_memory) + os.heap_free(mem.allocation_header(old_memory)) return null case FREE_ALL: // NOTE(bill): Does nothing + case RESIZE: + total_size := size + alignment + size_of(mem.AllocationHeader) + ptr := os.heap_resize(mem.allocation_header(old_memory), total_size) + header := ptr as ^mem.AllocationHeader + ptr = mem.align_forward(ptr_offset(header, 1), alignment) + mem.allocation_header_fill(header, ptr, size) + memory_zero(ptr, size) + return ptr } return null diff --git a/core/win32.odin b/core/win32.odin index e5301edd4..893da6a2b 100644 --- a/core/win32.odin +++ b/core/win32.odin @@ -162,8 +162,9 @@ OPEN_ALWAYS :: 4 TRUNCATE_EXISTING :: 5 -HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import -HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import +HeapAlloc :: proc(h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import +HeapReAlloc :: proc(h: HANDLE, flags: u32, memory: rawptr, bytes: int) -> rawptr #foreign #dll_import +HeapFree :: proc(h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import GetProcessHeap :: proc() -> HANDLE #foreign #dll_import diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index e94482c34..9f669e7c1 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -624,9 +624,13 @@ void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity) { GB_ASSERT(identifier != NULL); - GB_ASSERT(identifier->kind == AstNode_Ident); - HashKey key = hash_pointer(identifier); - map_set(&i->definitions, key, entity); + if (identifier->kind == AstNode_Ident) { + GB_ASSERT(identifier->kind == AstNode_Ident); + HashKey key = hash_pointer(identifier); + map_set(&i->definitions, key, entity); + } else { + // NOTE(bill): Error should handled elsewhere + } } b32 add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) { @@ -1139,10 +1143,11 @@ void check_parsed_files(Checker *c) { add_curr_ast_file(c, d->scope->file); - Scope *prev_scope = c->context.scope; - c->context.scope = d->scope; - GB_ASSERT(d->scope == e->scope); - check_entity_decl(c, e, d, NULL); + if (d->scope == e->scope) { + Scope *prev_scope = c->context.scope; + c->context.scope = d->scope; + check_entity_decl(c, e, d, NULL); + } } } }; @@ -1178,6 +1183,7 @@ void check_parsed_files(Checker *c) { } #endif +#if 0 gb_for_array(i, c->parser->files) { AstFile *f = &c->parser->files[i]; Scope *scope = f->scope; @@ -1192,6 +1198,7 @@ void check_parsed_files(Checker *c) { } } } +#endif } diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index dea0e2e0f..1ff39b7e1 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -53,6 +53,7 @@ struct Entity { struct { } TypeName; struct { + b32 used; } Procedure; struct { BuiltinProcId id; diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index f6670eb4d..429b5e6ba 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -806,22 +806,6 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl error(n->Ident, "`_` cannot be used as a value type"); } else { auto *entries = c->context.scope->elements.entries; - // gb_for_array(i, entries) { - // Entity *elem = entries[i].value; - // if (i > 0) { - // gb_printf(", "); - // } - // gb_printf("%.*s", LIT(elem->token.string)); - // } - // for (Scope *s = c->context.scope; s != NULL; s = s->parent) { - // Entity *elem = s->elements.entries[0].value; - // if (elem == NULL) continue; - // gb_printf("%.*s\n", LIT(elem->token.pos.file)); - // } - // gb_printf("\n"); - - - // Entity *e = scope_lookup_entity(c->context.scope, n->Ident.string); error(n->Ident, "Undeclared name: %.*s", LIT(n->Ident.string)); } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index c6d206dbf..2f31a6b77 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -9,7 +9,6 @@ enum StmtFlag : u32 { void check_stmt(Checker *c, AstNode *node, u32 flags); void check_proc_decl(Checker *c, Entity *e, DeclInfo *d); -void check_const_decl_node(Checker *c, AstNode *node); void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) { // TODO(bill): Allow declaration (expect variable) in any order @@ -474,7 +473,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle named->Named.base = base_type; named->Named.base = get_base_type(named->Named.base); if (named->Named.base == t_invalid) { - // gb_printf("check_type_decl: %s\n", type_to_string(named)); + gb_printf("check_type_decl: %s\n", type_to_string(named)); } } @@ -719,18 +718,11 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc } } - // c->context.decl = d; - // Scope *prev = c->context.scope; - // c->context.scope = d->scope; - // defer (c->context.scope = prev); - if (e->kind == Entity_Procedure) { check_proc_decl(c, e, d); return; } - - switch (e->kind) { case Entity_Constant: { Scope *prev = c->context.scope; @@ -758,15 +750,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc c->context.scope = d->scope; defer (c->context.scope = prev); - CycleChecker local_cycle_checker = {}; - if (cycle_checker == NULL) { - cycle_checker = &local_cycle_checker; - } check_type_decl(c, e, d->type_expr, named_type, cycle_checker); - - if (local_cycle_checker.path != NULL) { - gb_array_free(local_cycle_checker.path); - } } break; } } @@ -782,8 +766,8 @@ void check_var_decl_node(Checker *c, AstNode *node) { gb_for_array(i, vd->names) { AstNode *name = vd->names[i]; Entity *entity = NULL; - Token token = name->Ident; if (name->kind == AstNode_Ident) { + Token token = name->Ident; String str = token.string; Entity *found = NULL; // NOTE(bill): Ignore assignments to `_` @@ -803,10 +787,11 @@ void check_var_decl_node(Checker *c, AstNode *node) { entity = found; } } else { - error(token, "A variable declaration must be an identifier"); + error(ast_node_token(name), "A variable declaration must be an identifier"); + } + if (entity == NULL) { + entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name)); } - if (entity == NULL) - entity = make_entity_dummy_variable(c->allocator, c->global_scope, token); entities[entity_index++] = entity; } @@ -841,46 +826,6 @@ void check_var_decl_node(Checker *c, AstNode *node) { } -void check_const_decl_node(Checker *c, AstNode *node) { - ast_node(vd, ConstDecl, node); - isize entity_count = gb_array_count(vd->names); - isize entity_index = 0; - Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count); - - gb_for_array(i, vd->values) { - AstNode *name = vd->names[i]; - AstNode *value = vd->values[i]; - - GB_ASSERT(name->kind == AstNode_Ident); - ExactValue v = {ExactValue_Invalid}; - String str = name->Ident.string; - Entity *found = current_scope_lookup_entity(c->context.scope, str); - if (found == NULL) { - Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v); - entities[entity_index++] = e; - check_const_decl(c, e, vd->type, value); - } else { - entities[entity_index++] = found; - } - } - - isize lhs_count = gb_array_count(vd->names); - isize rhs_count = gb_array_count(vd->values); - - // TODO(bill): Better error messages or is this good enough? - if (rhs_count == 0 && vd->type == NULL) { - error(ast_node_token(node), "Missing type or initial expression"); - } else if (lhs_count < rhs_count) { - error(ast_node_token(node), "Extra initial expression"); - } - - gb_for_array(i, vd->names) { - add_entity(c, c->context.scope, vd->names[i], entities[i]); - } -} - - - void check_stmt(Checker *c, AstNode *node, u32 flags) { u32 mod_flags = flags & (~Stmt_FallthroughAllowed); diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index c1f9e7c64..c9d8b6129 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -103,6 +103,7 @@ struct ssaDefer { ssaBlock *block; union { AstNode *stmt; + // NOTE(bill): `instr` will be copied every time to create a new one ssaValue *instr; }; }; @@ -387,7 +388,7 @@ ssaDefer ssa_add_defer_instr(ssaProcedure *proc, isize scope_index, ssaValue *in ssaDefer d = {ssaDefer_Instr}; d.scope_index = proc->scope_index; d.block = proc->curr_block; - d.instr = cast(ssaValue *)gb_alloc_copy(proc->module->allocator, instr, gb_size_of(ssaValue)); + d.instr = instr; // NOTE(bill): It will make a copy everytime it is called gb_array_append(proc->defer_stmts, d); return d; } @@ -903,12 +904,15 @@ ssaValue *ssa_emit_comment(ssaProcedure *p, String text) { ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) { ssaBlock *b = proc->decl_block; // all variables must be in the first block ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized); + ssaValue *zero = ssa_make_instr_zero_init(proc, instr); instr->Instr.parent = b; + zero ->Instr.parent = b; gb_array_append(b->instrs, instr); + gb_array_append(b->instrs, zero); - if (zero_initialized) { + // if (zero_initialized) { ssa_emit_zero_init(proc, instr); - } + // } return instr; } @@ -1008,7 +1012,9 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) { if (d.kind == ssaDefer_Node) { ssa_build_stmt(proc, d.stmt); } else if (d.kind == ssaDefer_Instr) { - ssa_emit(proc, d.instr); + // NOTE(bill): Need to make a new copy + ssaValue *instr = cast(ssaValue *)gb_alloc_copy(proc->module->allocator, d.instr, gb_size_of(ssaValue)); + ssa_emit(proc, instr); } } @@ -3182,8 +3188,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { case_ast_node(pd, ProcDecl, node); if (pd->body != NULL) { + auto *info = proc->module->info; + + Entity **found = map_get(&info->definitions, hash_pointer(pd->name)); + GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); + Entity *e = *found; + // NOTE(bill): Generate a new name - // parent$name-guid + // parent.name-guid String original_name = pd->name->Ident.string; String pd_name = original_name; if (pd->link_name.len > 0) { @@ -3193,12 +3205,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { isize name_len = proc->name.len + 1 + pd_name.len + 1 + 10 + 1; u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len); i32 guid = cast(i32)gb_array_count(proc->children); - name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s-%d", LIT(proc->name), LIT(pd_name), guid); + name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s-%d", LIT(proc->name), LIT(pd_name), guid); String name = make_string(name_text, name_len-1); - Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name)); - GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); - Entity *e = *found; + ssaValue *value = ssa_make_value_procedure(proc->module->allocator, proc->module, e, e->type, pd->type, pd->body, name); @@ -3209,15 +3219,19 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_array_append(proc->children, &value->Proc); gb_array_append(proc->module->procs, value); } else { + auto *info = proc->module->info; + + Entity **found = map_get(&info->definitions, hash_pointer(pd->name)); + GB_ASSERT_MSG(found != NULL, "Unable to find: %.*s", LIT(pd->name->Ident.string)); + Entity *e = *found; + // FFI - Foreign function interace String original_name = pd->name->Ident.string; String name = original_name; if (pd->foreign_name.len > 0) { name = pd->foreign_name; } - auto *info = proc->module->info; - Entity *e = *map_get(&info->definitions, hash_pointer(pd->name)); Entity *f = *map_get(&info->foreign_procs, hash_string(name)); ssaValue *value = ssa_make_value_procedure(proc->module->allocator, proc->module, e, e->type, pd->type, pd->body, name); diff --git a/src/main.cpp b/src/main.cpp index 2c8c26668..602812854 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -91,14 +91,14 @@ ArchData make_arch_data(ArchKind kind) { 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 /defaultlib:libcmt "); + data.link_flags = make_string("/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 /defaultlib:libcmt "); + data.link_flags = make_string("/machine:x86 "); break; } @@ -215,14 +215,14 @@ int main(int argc, char **argv) { " %.*s.lib", LIT(lib)); lib_str = gb_string_appendc(lib_str, lib_str_buf); } - char *linker_flags = - "/nologo /incremental:no /opt:ref /subsystem:console"; - exit_code = win32_exec_command_line_app( - "link %.*s.obj -OUT:%.*s.exe %s %.*s %s" + "link %.*s.obj -OUT:%.*s.exe %s " + "/defaultlib:libcmt " + "/nologo /incremental:no /opt:ref /subsystem:console " + "%.*s " "", LIT(output), LIT(output), - lib_str, LIT(arch_data.link_flags), linker_flags); + lib_str, LIT(arch_data.link_flags)); if (exit_code != 0) { return exit_code; }