diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 64bed838a..556774ea4 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -211,12 +211,11 @@ context_from_allocator :: proc(a: Allocator) -> runtime.Context { destroy_arena :: proc(using a: ^Arena) { if backing.procedure != nil { - context <- context_from_allocator(backing) { - if memory != nil { - free(&memory[0]); - } - memory = nil; + context = context_from_allocator(backing); + if memory != nil { + free(&memory[0]); } + memory = nil; } } diff --git a/core/thread/thread_windows.odin b/core/thread/thread_windows.odin index 369a61072..743f0fec8 100644 --- a/core/thread/thread_windows.odin +++ b/core/thread/thread_windows.odin @@ -29,13 +29,9 @@ create :: proc(procedure: Thread_Proc) -> ^Thread { if t.use_init_context { c = t.init_context; } + context = c; - exit := 0; - context <- c { - exit = t.procedure(t); - } - - return i32(exit); + return i32(t.procedure(t)); } diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index 477408e62..4860d9414 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -364,26 +364,24 @@ parametric_polymorphism :: proc() { allocate :: proc(table: ^$T/Table, capacity: int) { c := context; if table.allocator.procedure != nil do c.allocator = table.allocator; + context = c; - context <- c { - table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN)); - } + table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN)); } expand :: proc(table: ^$T/Table) { c := context; if table.allocator.procedure != nil do c.allocator = table.allocator; + context = c; - context <- c { - old_slots := table.slots; - defer delete(old_slots); + old_slots := table.slots; + defer delete(old_slots); - cap := max(2*len(table.slots), TABLE_SIZE_MIN); - allocate(table, cap); + cap := max(2*len(table.slots), TABLE_SIZE_MIN); + allocate(table, cap); - for s in old_slots do if s.occupied { - put(table, s.key, s.value); - } + for s in old_slots do if s.occupied { + put(table, s.key, s.value); } } diff --git a/src/array.cpp b/src/array.cpp index c28463c1b..1d3ceafed 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -40,6 +40,15 @@ template void array_resize (Array *array, isize count) template void array_set_capacity (Array *array, isize capacity); template Array array_slice (Array const &array, isize lo, isize hi); +template +T *array_end_ptr(Array *array) { + if (array->count > 0) { + return &array->data[array->count-1]; + } + return nullptr; +} + + template gb_inline void array_init(Array *array, gbAllocator const &a) { isize cap = ARRAY_GROW_FORMULA(0); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 479103241..163d7f6d0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -578,7 +578,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type if (is_type_any(dst)) { if (!is_type_polymorphic(src)) { - if (operand->mode == Addressing_Immutable && operand->type == t_context) { + if (operand->mode == Addressing_Context && operand->type == t_context) { return -1; } else { // NOTE(bill): Anything can cast to 'Any' @@ -2040,6 +2040,17 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) { return; } + if (x->mode == Addressing_Builtin) { + x->mode = Addressing_Invalid; + error(x->expr, "built-in expression in binary expression"); + return; + } + if (y->mode == Addressing_Builtin) { + x->mode = Addressing_Invalid; + error(y->expr, "built-in expression in binary expression"); + return; + } + if (token_is_shift(op.kind)) { check_shift(c, x, y, node); return; @@ -2724,6 +2735,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ // TODO(bill): Is this the rule I need? if (operand->mode == Addressing_Immutable) { // Okay + } else if (operand->mode == Addressing_Context) { + operand->mode = Addressing_Value; // TODO(bill): Should this be Value or Immutable? } else if (sel.indirect || operand->mode != Addressing_Value) { operand->mode = Addressing_Variable; } else { @@ -5211,7 +5224,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type } init_core_context(c->checker); - o->mode = Addressing_Immutable; + o->mode = Addressing_Context; o->type = t_context; break; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 4a98db600..4a7c6c621 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -167,10 +167,6 @@ bool check_is_terminating(Ast *node) { } return has_default; case_end; - - case_ast_node(pc, PushContext, node); - return check_is_terminating(pc->body); - case_end; } return false; @@ -306,6 +302,10 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs) break; } + case Addressing_Context: { + break; + } + default: { if (lhs->expr->kind == Ast_SelectorExpr) { // NOTE(bill): Extra error checks @@ -1597,13 +1597,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) { } case_end; - case_ast_node(pa, PushContext, node); - Operand op = {}; - check_expr(ctx, &op, pa->expr); - check_assignment(ctx, &op, t_context, str_lit("argument to context <-")); - check_stmt(ctx, pa->body, mod_flags); - case_end; - case_ast_node(fb, ForeignBlockDecl, node); Ast *foreign_library = fb->foreign_library; CheckerContext c = *ctx; diff --git a/src/common.cpp b/src/common.cpp index e7024ae43..3a9bb874b 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -338,6 +338,7 @@ gb_global bool global_module_path_set = false; typedef struct Arena { u8 * ptr; u8 * end; + u8 * prev; Array blocks; gbAllocator backing; isize block_size; @@ -363,11 +364,11 @@ void arena_grow(Arena *arena, isize min_size) { isize size = gb_max(arena->block_size, min_size); size = ALIGN_UP(size, ARENA_MIN_ALIGNMENT); void *new_ptr = gb_alloc(arena->backing, size); - arena->ptr = cast(u8 *)new_ptr; - gb_zero_size(arena->ptr, size); - GB_ASSERT(arena->ptr == ALIGN_DOWN_PTR(arena->ptr, ARENA_MIN_ALIGNMENT)); - arena->end = arena->ptr + size; - array_add(&arena->blocks, arena->ptr); + arena->ptr = cast(u8 *)new_ptr; + gb_zero_size(arena->ptr, size); + GB_ASSERT(arena->ptr == ALIGN_DOWN_PTR(arena->ptr, ARENA_MIN_ALIGNMENT)); + arena->end = arena->ptr + size; + array_add(&arena->blocks, arena->ptr); } void *arena_alloc(Arena *arena, isize size, isize alignment) { @@ -376,18 +377,19 @@ void *arena_alloc(Arena *arena, isize size, isize alignment) { arena->total_used += size; - if (size > (arena->end - arena->ptr)) { - arena_grow(arena, size); - GB_ASSERT(size <= (arena->end - arena->ptr)); - } + if (size > (arena->end - arena->ptr)) { + arena_grow(arena, size); + GB_ASSERT(size <= (arena->end - arena->ptr)); + } - isize align = gb_max(alignment, ARENA_MIN_ALIGNMENT); - void *ptr = arena->ptr; - arena->ptr = cast(u8 *)ALIGN_UP_PTR(arena->ptr + size, align); - GB_ASSERT(arena->ptr <= arena->end); - GB_ASSERT(ptr == ALIGN_DOWN_PTR(ptr, align)); - gb_zero_size(ptr, size); - return ptr; + isize align = gb_max(alignment, ARENA_MIN_ALIGNMENT); + void *ptr = arena->ptr; + arena->prev = arena->ptr; + arena->ptr = cast(u8 *)ALIGN_UP_PTR(arena->ptr + size, align); + GB_ASSERT(arena->ptr <= arena->end); + GB_ASSERT(ptr == ALIGN_DOWN_PTR(ptr, align)); + gb_zero_size(ptr, size); + return ptr; } void arena_free_all(Arena *arena) { @@ -395,11 +397,11 @@ void arena_free_all(Arena *arena) { defer (gb_mutex_unlock(&arena->mutex)); for_array(i, arena->blocks) { - gb_free(arena->backing, arena->blocks[i]); - } - array_clear(&arena->blocks); - arena->ptr = nullptr; - arena->end = nullptr; + gb_free(arena->backing, arena->blocks[i]); + } + array_clear(&arena->blocks); + arena->ptr = nullptr; + arena->end = nullptr; } diff --git a/src/ir.cpp b/src/ir.cpp index 274075dfa..535dcc73f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -113,6 +113,11 @@ struct irDebugLocation { irDebugInfo *debug_scope; }; +struct irContextData { + irValue *value; + i32 scope_index; +}; + struct irProcedure { irProcedure * parent; Array children; @@ -142,7 +147,7 @@ struct irProcedure { irTargetList * target_list; Array referrers; - Array context_stack; + Array context_stack; Array branch_blocks; @@ -443,6 +448,7 @@ enum irAddrKind { irAddr_Default, irAddr_Map, irAddr_BitField, + irAddr_Context, }; struct irAddr { @@ -473,6 +479,13 @@ irAddr ir_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_re return v; } + +irAddr ir_addr_context(irValue *addr) { + irAddr v = {irAddr_Context, addr}; + return v; +} + + irAddr ir_addr_bit_field(irValue *addr, i32 bit_field_value_index) { irAddr v = {irAddr_BitField, addr}; v.bit_field_value_index = bit_field_value_index; @@ -1354,7 +1367,10 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) { - +void ir_push_context_onto_stack(irProcedure *proc, irValue *ctx) { + irContextData cd = {ctx, proc->scope_index}; + array_add(&proc->context_stack, cd); +} irValue *ir_add_local(irProcedure *proc, Entity *e, Ast *expr, bool zero_initialized) { irBlock *b = proc->decl_block; // all variables must be in the first block @@ -1622,7 +1638,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index); irValue *ir_find_or_generate_context_ptr(irProcedure *proc) { if (proc->context_stack.count > 0) { - return proc->context_stack[proc->context_stack.count-1]; + return proc->context_stack[proc->context_stack.count-1].value; } irBlock *tmp_block = proc->curr_block; @@ -1631,7 +1647,7 @@ irValue *ir_find_or_generate_context_ptr(irProcedure *proc) { defer (proc->curr_block = tmp_block); irValue *c = ir_add_local_generated(proc, t_context); - array_add(&proc->context_stack, c); + ir_push_context_onto_stack(proc, c); ir_emit_store(proc, c, ir_emit_load(proc, proc->module->global_default_context)); irValue *ep = ir_emit_struct_ep(proc, c, 0); @@ -1763,6 +1779,21 @@ void ir_open_scope(irProcedure *proc) { void ir_close_scope(irProcedure *proc, irDeferExitKind kind, irBlock *block) { ir_emit_defer_stmts(proc, kind, block); GB_ASSERT(proc->scope_index > 0); + + + // NOTE(bill): Remove `context`s made in that scope + for (;;) { + irContextData *end = array_end_ptr(&proc->context_stack); + if (end == nullptr) { + break; + } + if (end->scope_index != proc->scope_index) { + break; + } + array_pop(&proc->context_stack); + } + + proc->scope_index--; } @@ -1923,6 +1954,7 @@ irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, Token irValue *ir_emit_source_code_location(irProcedure *proc, Ast *node); irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset); irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type); +irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel); irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type, irValue *map_key, irValue *map_value) { @@ -1945,12 +1977,13 @@ irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, T -irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { +void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { if (addr.addr == nullptr) { - return nullptr; + return; } if (addr.kind == irAddr_Map) { - return ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value); + ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value); + return; } else if (addr.kind == irAddr_BitField) { gbAllocator a = ir_allocator(); @@ -1966,7 +1999,7 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { i32 size_in_bytes = next_pow2((size_in_bits+7)/8); if (size_in_bytes == 0) { GB_ASSERT(size_in_bits == 0); - return nullptr; + return; } Type *int_type = nullptr; @@ -1994,7 +2027,8 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { } irValue *ptr = ir_emit_conv(proc, bytes, alloc_type_pointer(int_type)); v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type); - return ir_emit_store(proc, ptr, v); + ir_emit_store(proc, ptr, v); + return; } @@ -2015,12 +2049,30 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { irValue *ptr = ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), alloc_type_pointer(int_type)); irValue *v = ir_emit_arith(proc, Token_Shr, value, shift_amount, int_type); v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type); - return ir_emit_store(proc, ptr, v); + ir_emit_store(proc, ptr, v); + return; } + } else if (addr.kind == irAddr_Context) { + irValue *new_context = ir_emit_conv(proc, value, ir_addr_type(addr)); + + irValue *prev = ir_find_or_generate_context_ptr(proc); + GB_ASSERT(addr.addr == prev); + + irValue *next = ir_add_local_generated(proc, t_context); + ir_emit_store(proc, next, new_context); + + Selection sel = lookup_field(t_context, str_lit("parent"), false); + GB_ASSERT(sel.entity != nullptr); + irValue *parent_ptr = ir_emit_deep_field_gep(proc, next, sel); + ir_emit_store(proc, parent_ptr, prev); + + ir_push_context_onto_stack(proc, next); + + return; } irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr)); - return ir_emit_store(proc, addr.addr, v); + ir_emit_store(proc, addr.addr, v); } irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) { @@ -5559,7 +5611,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { } GB_ASSERT(v != nullptr); - return ir_addr(v); + return ir_addr_context(v); case_end; case_ast_node(i, Ident, expr); @@ -7408,32 +7460,6 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) { ir_emit_jump(proc, block); ir_emit_unreachable(proc); case_end; - - - case_ast_node(pc, PushContext, node); - ir_emit_comment(proc, str_lit("push_context")); - irValue *new_context = ir_build_expr(proc, pc->expr); - - ir_open_scope(proc); - - irValue *prev = ir_find_or_generate_context_ptr(proc); - irValue *next = ir_add_local_generated(proc, t_context); - ir_emit_store(proc, next, new_context); - - Selection sel = lookup_field(t_context, str_lit("parent"), false); - GB_ASSERT(sel.entity != nullptr); - irValue *parent_ptr = ir_emit_deep_field_gep(proc, next, sel); - ir_emit_store(proc, parent_ptr, prev); - - array_add(&proc->context_stack, next); - defer (array_pop(&proc->context_stack)); - - ir_build_stmt(proc, pc->body); - - ir_close_scope(proc, irDeferExit_Default, nullptr); - case_end; - - } } @@ -7583,7 +7609,7 @@ void ir_begin_procedure_body(irProcedure *proc) { e->flags |= EntityFlag_NoAlias; irValue *param = ir_value_param(proc, e, e->type); ir_module_add_value(proc->module, e, param); - array_add(&proc->context_stack, param); + array_add(&proc->context_stack, {param, proc->scope_index}); } } diff --git a/src/parser.cpp b/src/parser.cpp index 0b0c77bf0..a1f8ff1e1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -53,7 +53,6 @@ Token ast_token(Ast *node) { case Ast_DeferStmt: return node->DeferStmt.token; case Ast_BranchStmt: return node->BranchStmt.token; case Ast_UsingStmt: return node->UsingStmt.token; - case Ast_PushContext: return node->PushContext.token; case Ast_BadDecl: return node->BadDecl.begin; case Ast_Label: return node->Label.token; @@ -274,10 +273,6 @@ Ast *clone_ast(Ast *node) { case Ast_UsingStmt: n->UsingStmt.list = clone_ast_array(n->UsingStmt.list); break; - case Ast_PushContext: - n->PushContext.expr = clone_ast(n->PushContext.expr); - n->PushContext.body = clone_ast(n->PushContext.body); - break; case Ast_BadDecl: break; @@ -787,15 +782,6 @@ Ast *ast_using_stmt(AstFile *f, Token token, Array list) { return result; } -Ast *ast_push_context(AstFile *f, Token token, Ast *expr, Ast *body) { - Ast *result = alloc_ast_node(f, Ast_PushContext); - result->PushContext.token = token; - result->PushContext.expr = expr; - result->PushContext.body = body; - return result; -} - - Ast *ast_bad_decl(AstFile *f, Token begin, Token end) { @@ -1267,7 +1253,6 @@ bool is_semicolon_optional_for_node(AstFile *f, Ast *s) { case Ast_RangeStmt: case Ast_SwitchStmt: case Ast_TypeSwitchStmt: - case Ast_PushContext: return true; case Ast_HelperType: @@ -2540,25 +2525,6 @@ Ast *parse_simple_stmt(AstFile *f, u32 flags) { } } return parse_value_decl(f, lhs, docs); - - case Token_ArrowLeft: - if ((flags&StmtAllowFlag_Context) && lhs.count == 1) { - Token arrow = expect_token(f, Token_ArrowLeft); - Ast *body = nullptr; - isize prev_level = f->expr_level; - f->expr_level = -1; - Ast *expr = parse_expr(f, false); - f->expr_level = prev_level; - - if (allow_token(f, Token_do)) { - body = convert_stmt_to_body(f, parse_stmt(f)); - } else { - body = parse_block_stmt(f, false); - } - - return ast_push_context(f, token, expr, body); - } - break; } if (lhs.count > 1) { @@ -3548,7 +3514,7 @@ Ast *parse_stmt(AstFile *f) { case Token_Xor: case Token_Not: case Token_And: - s = parse_simple_stmt(f, StmtAllowFlag_Label|StmtAllowFlag_Context); + s = parse_simple_stmt(f, StmtAllowFlag_Label); expect_semicolon(f, s); return s; diff --git a/src/parser.hpp b/src/parser.hpp index 1020f784f..a9adee8d3 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -11,6 +11,7 @@ enum AddressingMode { Addressing_NoValue, // no value (void in C) Addressing_Value, // computed value (rvalue) Addressing_Immutable, // immutable computed value (const rvalue) + Addressing_Context, // context value Addressing_Variable, // addressable variable (lvalue) Addressing_Constant, // constant Addressing_Type, // type @@ -191,7 +192,6 @@ enum StmtAllowFlag { StmtAllowFlag_None = 0, StmtAllowFlag_In = 1<<0, StmtAllowFlag_Label = 1<<1, - StmtAllowFlag_Context = 1<<2, }; #define AST_KINDS \ @@ -343,11 +343,6 @@ AST_KIND(_ComplexStmtBegin, "", bool) \ Token token; \ Array list; \ }) \ - AST_KIND(PushContext, "context <- statement", struct { \ - Token token; \ - Ast *expr; \ - Ast *body; \ - }) \ AST_KIND(_ComplexStmtEnd, "", bool) \ AST_KIND(_StmtEnd, "", bool) \ AST_KIND(_DeclBegin, "", bool) \