aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-09-30 15:04:17 +0100
committergingerBill <bill@gingerbill.org>2023-09-30 15:04:17 +0100
commit648b83d6ead67a291dc023f93a7262622991be2a (patch)
tree722495f871bb992e44e321d894879337dd03c20c /src/llvm_backend_expr.cpp
parent4e97b833126d9773ec23a0a0652beb19aab4aea4 (diff)
Add `or_break` and `or_continue` constructs
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index d6e8843fa..aba129ea4 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -3305,6 +3305,62 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
return lb_emit_or_return(p, oe->expr, tv);
case_end;
+ case_ast_node(be, OrBranchExpr, expr);
+ lbBlock *block = nullptr;
+
+ if (be->label != nullptr) {
+ lbBranchBlocks bb = lb_lookup_branch_blocks(p, be->label);
+ switch (be->token.kind) {
+ case Token_or_break: block = bb.break_; break;
+ case Token_or_continue: block = bb.continue_; break;
+ }
+ } else {
+ for (lbTargetList *t = p->target_list; t != nullptr && block == nullptr; t = t->prev) {
+ if (t->is_block) {
+ continue;
+ }
+
+ switch (be->token.kind) {
+ case Token_or_break: block = t->break_; break;
+ case Token_or_continue: block = t->continue_; break;
+ }
+ }
+ }
+
+ lbValue lhs = {};
+ lbValue rhs = {};
+ lb_emit_try_lhs_rhs(p, be->expr, tv, &lhs, &rhs);
+
+ Type *type = default_type(tv.type);
+
+ lbBlock *then = lb_create_block(p, "or_branch.then");
+ lbBlock *done = lb_create_block(p, "or_branch.done"); // NOTE(bill): Append later
+ lbBlock *else_ = lb_create_block(p, "or_branch.else");
+
+ lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
+ lb_start_block(p, then);
+
+ lbValue res = {};
+ if (lhs.value) {
+ res = lb_emit_conv(p, lhs, type);
+ }
+
+ lb_emit_jump(p, done);
+ lb_start_block(p, else_);
+
+ if (lhs.value) {
+ res = lb_const_nil(p->module, type);
+ }
+
+ if (block != nullptr) {
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ }
+ lb_emit_jump(p, block);
+ lb_start_block(p, done);
+
+ return res;
+ case_end;
+
case_ast_node(ta, TypeAssertion, expr);
TokenPos pos = ast_token(expr).pos;
lbValue e = lb_build_expr(p, ta->expr);