diff --git a/code/demo.odin b/code/demo.odin index 7e4e5eed7..a302c39c8 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -4,17 +4,15 @@ main :: proc() { - x :: proc() -> (int, int) { - return 1, 2 - } 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) diff --git a/core/runtime.odin b/core/runtime.odin index 03e7ab203..03fbb5ee7 100644 --- a/core/runtime.odin +++ b/core/runtime.odin @@ -175,13 +175,12 @@ Context :: struct #ordered { DEFAULT_ALIGNMENT :: align_of({4}f32) -current_context :: proc() -> ^Context { - return ^__context +current_context :: proc() -> Context { // Copy of context + return __context } __check_context :: proc() { - c := current_context() - assert(c != null) + c := ^__context if c.allocator.procedure == null { c.allocator = __default_allocator() @@ -202,12 +201,14 @@ alloc_align :: proc(size, alignment: int) -> rawptr #inline { free :: proc(ptr: rawptr) #inline { __check_context() a := current_context().allocator - _ = a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0) + if ptr != null { + a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0) + } } free_all :: proc() #inline { __check_context() a := current_context().allocator - _ = a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0) + a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0) } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 20d4bb904..c6d206dbf 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -9,10 +9,91 @@ 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 // even within a procedure + struct Delay { + Entity *e; + DeclInfo *d; + }; + gbArray(Delay) delayed; gb_array_init(delayed, gb_heap_allocator()); + + gb_for_array(i, stmts) { + AstNode *node = stmts[i]; + switch (node->kind) { + case_ast_node(cd, ConstDecl, node); + gb_for_array(i, cd->values) { + AstNode *name = cd->names[i]; + AstNode *value = cd->values[i]; + ExactValue v = {ExactValue_Invalid}; + + Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v); + add_entity(c, e->scope, name, e); + + DeclInfo *di = make_declaration_info(c->allocator, e->scope); + di->type_expr = cd->type; + di->init_expr = value; + + Delay delay = {e, di}; + gb_array_append(delayed, delay); + } + + isize lhs_count = gb_array_count(cd->names); + isize rhs_count = gb_array_count(cd->values); + + if (rhs_count == 0 && cd->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"); + } + case_end; + + case_ast_node(td, TypeDecl, node); + Entity *e = make_entity_type_name(c->allocator, c->context.scope, td->name->Ident, NULL); + add_entity(c, c->context.scope, td->name, e); + + DeclInfo *d = make_declaration_info(c->allocator, e->scope); + d->type_expr = td->type; + + Delay delay = {e, d}; + gb_array_append(delayed, delay); + case_end; + + case_ast_node(pd, ProcDecl, node); + ast_node(name, Ident, pd->name); + Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL); + add_entity(c, c->context.scope, pd->name, e); + + DeclInfo *d = make_declaration_info(c->allocator, e->scope); + d->proc_decl = node; + + Delay delay = {e, d}; + gb_array_append(delayed, delay); + case_end; + } + } + + auto check_scope_entity = [](Checker *c, gbArray(Delay) delayed, EntityKind kind) { + gb_for_array(i, delayed) { + auto delay = delayed[i]; + Entity *e = delay.e; + if (e->kind == kind) { + DeclInfo *d = delay.d; + Scope *prev_scope = c->context.scope; + c->context.scope = d->scope; + GB_ASSERT(d->scope == e->scope); + check_entity_decl(c, e, d, NULL); + c->context.scope = prev_scope; + } + } + }; + check_scope_entity(c, delayed, Entity_TypeName); + check_scope_entity(c, delayed, Entity_Constant); + check_scope_entity(c, delayed, Entity_Procedure); + + b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0; u32 f = flags & (~Stmt_FallthroughAllowed); @@ -1512,24 +1593,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { case_end; case_ast_node(cd, ConstDecl, node); - check_const_decl_node(c, node); + // NOTE(bill): Handled elsewhere case_end; case_ast_node(pd, ProcDecl, node); - ast_node(name, Ident, pd->name); - Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL); - add_entity(c, c->context.scope, pd->name, e); - - DeclInfo *decl = make_declaration_info(c->allocator, e->scope); - decl->proc_decl = node; - check_proc_decl(c, e, decl); + // NOTE(bill): Handled elsewhere case_end; case_ast_node(td, TypeDecl, node); - ast_node(name, Ident, td->name); - Entity *e = make_entity_type_name(c->allocator, c->context.scope, *name, NULL); - add_entity(c, c->context.scope, td->name, e); - check_type_decl(c, e, td->type, NULL, NULL); + // NOTE(bill): Handled elsewhere case_end; } } diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index e66d4fd03..c8a272202 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -635,6 +635,10 @@ void ssa_gen_tree(ssaGen *s) { ssa_end_procedure_body(proc); } + gb_for_array(i, m->procs) { + ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent); + } + diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index 6226424dd..c1f9e7c64 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -62,6 +62,8 @@ struct ssaModule { Map type_names; // Key: Type * Map debug_info; // Key: Unique pointer i32 global_string_index; + + gbArray(ssaValue *) procs; // NOTE(bill): Procedures to generate }; @@ -405,6 +407,7 @@ void ssa_init_module(ssaModule *m, Checker *c) { map_init(&m->members, gb_heap_allocator()); map_init(&m->debug_info, gb_heap_allocator()); map_init(&m->type_names, gb_heap_allocator()); + gb_array_init(m->procs, gb_heap_allocator()); // Default states m->stmt_state_flags = 0; @@ -468,6 +471,7 @@ void ssa_destroy_module(ssaModule *m) { map_destroy(&m->members); map_destroy(&m->type_names); map_destroy(&m->debug_info); + gb_array_free(m->procs); gb_arena_free(&m->arena); } @@ -3199,10 +3203,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { proc->module, e, e->type, pd->type, pd->body, name); value->Proc.tags = pd->tags; + value->Proc.parent = proc; ssa_module_add_value(proc->module, e, value); gb_array_append(proc->children, &value->Proc); - ssa_build_proc(value, proc); + gb_array_append(proc->module->procs, value); } else { // FFI - Foreign function interace String original_name = pd->name->Ident.string; @@ -3390,10 +3395,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { Type *ret_type = proc->type->Proc.results; v = ssa_add_local_generated(proc, ret_type); gb_for_array(i, results) { - Type *t = return_type_tuple->variables[i]->type; - ssaValue *e = ssa_emit_conv(proc, results[i], t); - ssaValue *gep = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, t)); - ssa_emit_store(proc, gep, e); + Entity *e = return_type_tuple->variables[i]; + ssaValue *res = ssa_emit_conv(proc, results[i], e->type); + ssaValue *field = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, e->type)); + ssa_emit_store(proc, field, res); } v = ssa_emit_load(proc, v); @@ -3410,7 +3415,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { gb_for_array(i, rs->results) { Entity *e = return_type_tuple->variables[i]; ssaValue *res = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[i]), e->type); - ssaValue *field = ssa_emit_struct_gep(proc, v, i, e->type); + ssaValue *field = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, e->type)); ssa_emit_store(proc, field, res); } v = ssa_emit_load(proc, v); @@ -3452,7 +3457,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL); proc->scope_index--; - ssa_emit_jump(proc, done); } gb_array_append(proc->blocks, done);