aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-12-15 11:10:50 +0000
committergingerBill <bill@gingerbill.org>2019-12-15 11:10:50 +0000
commit7f5021c8e95e2861388c89d9d467d773339d5f4a (patch)
treea47b0593e862ba1f730a2a943b9cc5d1d1a2f1e1 /src/ir.cpp
parent8bec32477995f5a48fdb784bebe522015aedb036 (diff)
Disallow procedure calls with an associated deferred procedure to be used in logical binary expressions (short-circuiting)
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp51
1 files changed, 40 insertions, 11 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 6a9835636..19fa94485 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -91,6 +91,7 @@ enum irDeferExitKind {
enum irDeferKind {
irDefer_Node,
irDefer_Instr,
+ irDefer_Proc,
};
struct irDefer {
@@ -102,6 +103,10 @@ struct irDefer {
Ast *stmt;
// NOTE(bill): 'instr' will be copied every time to create a new one
irValue *instr;
+ struct {
+ irValue *deferred;
+ Array<irValue *> result_as_args;
+ } proc;
};
};
@@ -1554,6 +1559,17 @@ irDefer ir_add_defer_instr(irProcedure *proc, isize scope_index, irValue *instr)
return d;
}
+irDefer ir_add_defer_proc(irProcedure *proc, isize scope_index, irValue *deferred, Array<irValue *> const &result_as_args) {
+ irDefer d = {irDefer_Proc};
+ d.scope_index = proc->scope_index;
+ d.block = proc->curr_block;
+ d.proc.deferred = deferred;
+ d.proc.result_as_args = result_as_args;
+ array_add(&proc->defer_stmts, d);
+ return d;
+}
+
+
irValue *ir_add_module_constant(irModule *m, Type *type, ExactValue value) {
@@ -3202,8 +3218,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, Array<irValue *> const &ar
break;
}
- irValue *deferred_call = ir_de_emit(p, ir_emit_call(p, deferred, result_as_args));
- ir_add_defer_instr(p, p->scope_index, deferred_call);
+ ir_add_defer_proc(p, p->scope_index, deferred, result_as_args);
}
}
@@ -3271,21 +3286,34 @@ void ir_open_scope(irProcedure *proc) {
proc->scope_index++;
}
-void ir_close_scope(irProcedure *proc, irDeferExitKind kind, irBlock *block) {
+void ir_close_scope(irProcedure *proc, irDeferExitKind kind, irBlock *block, bool pop_stack=true) {
ir_emit_defer_stmts(proc, kind, block);
GB_ASSERT(proc->scope_index > 0);
// NOTE(bill): Remove `context`s made in that scope
+
+ isize end_idx = proc->context_stack.count-1;
+ isize pop_count = 0;
+
for (;;) {
- irContextData *end = array_end_ptr(&proc->context_stack);
+ if (end_idx < 0) {
+ break;
+ }
+ irContextData *end = &proc->context_stack[end_idx];
if (end == nullptr) {
break;
}
if (end->scope_index != proc->scope_index) {
break;
}
- array_pop(&proc->context_stack);
+ end_idx -= 1;
+ pop_count += 1;
+ }
+ if (pop_stack) {
+ for (isize i = 0; i < pop_count; i++) {
+ array_pop(&proc->context_stack);
+ }
}
@@ -6256,6 +6284,8 @@ void ir_build_defer_stmt(irProcedure *proc, irDefer d) {
// NOTE(bill): Need to make a new copy
irValue *instr = cast(irValue *)gb_alloc_copy(ir_allocator(), d.instr, gb_size_of(irValue));
ir_emit(proc, instr);
+ } else if (d.kind == irDefer_Proc) {
+ ir_emit_call(proc, d.proc.deferred, d.proc.result_as_args);
}
}
@@ -6959,11 +6989,6 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
return nullptr;
case_end;
- case_ast_node(re, RunExpr, expr);
- // TODO(bill): Run Expression
- return ir_build_expr(proc, re->expr);
- case_end;
-
case_ast_node(de, DerefExpr, expr);
return ir_addr_load(proc, ir_build_addr(proc, expr));
case_end;
@@ -9499,7 +9524,6 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
case_ast_node(is, IfStmt, node);
ir_emit_comment(proc, str_lit("IfStmt"));
ir_open_scope(proc); // Scope #1
- defer (ir_close_scope(proc, irDeferExit_Default, nullptr));
if (is->init != nullptr) {
// TODO(bill): Should this have a separate block to begin with?
@@ -9525,7 +9549,9 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
tl->is_block = true;
}
+ // ir_open_scope(proc);
ir_build_stmt(proc, is->body);
+ // ir_close_scope(proc, irDeferExit_Default, nullptr);
ir_emit_jump(proc, done);
@@ -9539,7 +9565,10 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
ir_emit_jump(proc, done);
}
+
ir_start_block(proc, done);
+ ir_close_scope(proc, irDeferExit_Default, nullptr);
+
case_end;
case_ast_node(fs, ForStmt, node);