aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm_backend_stmt.cpp')
-rw-r--r--src/llvm_backend_stmt.cpp327
1 files changed, 239 insertions, 88 deletions
diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp
index 9a5f25712..758cd353f 100644
--- a/src/llvm_backend_stmt.cpp
+++ b/src/llvm_backend_stmt.cpp
@@ -5,8 +5,6 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd)
auto *min_dep_set = &p->module->info->minimum_dependency_set;
- static i32 global_guid = 0;
-
for (Ast *ident : vd->names) {
GB_ASSERT(ident->kind == Ast_Ident);
Entity *e = entity_of_node(ident);
@@ -32,7 +30,8 @@ gb_internal void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd)
continue;
}
- lb_set_nested_type_name_ir_mangled_name(e, p, p->module);
+ String name = lb_get_entity_name(p->module, e);
+ gb_unused(name);
}
for_array(i, vd->names) {
@@ -208,8 +207,8 @@ gb_internal void lb_open_scope(lbProcedure *p, Scope *s) {
}
-gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, bool pop_stack=true) {
- lb_emit_defer_stmts(p, kind, block);
+gb_internal void lb_close_scope(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node, bool pop_stack=true) {
+ lb_emit_defer_stmts(p, kind, block, node);
GB_ASSERT(p->scope_index > 0);
// NOTE(bill): Remove `context`s made in that scope
@@ -256,7 +255,7 @@ gb_internal void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) {
gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr,
lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_,
- bool is_reverse) {
+ bool is_reverse, i64 unroll_count=0) {
lbModule *m = p->module;
lbValue count = {};
@@ -721,7 +720,7 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node,
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node->left);
lb_pop_target_list(p);
if (check != nullptr) {
@@ -854,7 +853,7 @@ gb_internal void lb_build_range_tuple(lbProcedure *p, AstRangeStmt *rs, Scope *s
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -976,7 +975,7 @@ gb_internal void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1192,7 +1191,7 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc
lb_build_stmt(p, rs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
lb_pop_target_list(p);
lb_emit_jump(p, loop);
lb_start_block(p, done);
@@ -1230,7 +1229,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
TypeAndValue tav = type_and_value_of_expr(expr);
if (is_ast_range(expr)) {
-
lbAddr val0_addr = {};
lbAddr val1_addr = {};
if (val0_type) val0_addr = lb_build_addr(p, val0);
@@ -1268,7 +1266,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
}
}
-
} else if (tav.mode == Addressing_Type) {
GB_ASSERT(is_type_enum(type_deref(tav.type)));
Type *et = type_deref(tav.type);
@@ -1293,77 +1290,208 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
if (val0_type) val0_addr = lb_build_addr(p, val0);
if (val1_type) val1_addr = lb_build_addr(p, val1);
- GB_ASSERT(expr->tav.mode == Addressing_Constant);
+ ExactValue unroll_count_ev = {};
+ if (rs->args.count != 0) {
+ unroll_count_ev = rs->args[0]->tav.value;
+ }
- Type *t = base_type(expr->tav.type);
+ if (unroll_count_ev.kind == ExactValue_Invalid) {
+ GB_ASSERT(expr->tav.mode == Addressing_Constant);
- switch (t->kind) {
- case Type_Basic:
- GB_ASSERT(is_type_string(t));
- {
- ExactValue value = expr->tav.value;
- GB_ASSERT(value.kind == ExactValue_String);
- String str = value.value_string;
- Rune codepoint = 0;
- isize offset = 0;
- do {
- isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint);
- if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint)));
- if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset)));
- lb_build_stmt(p, rs->body);
+ Type *t = base_type(expr->tav.type);
- offset += width;
- } while (offset < str.len);
- }
- break;
- case Type_Array:
- if (t->Array.count > 0) {
- lbValue val = lb_build_expr(p, expr);
- lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
-
- for (i64 i = 0; i < t->Array.count; i++) {
- if (val0_type) {
- // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
- lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
- lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
- }
- if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i)));
+ switch (t->kind) {
+ case Type_Basic:
+ GB_ASSERT(is_type_string(t));
+ {
+ ExactValue value = expr->tav.value;
+ GB_ASSERT(value.kind == ExactValue_String);
+ String str = value.value_string;
+ Rune codepoint = 0;
+ isize offset = 0;
+ do {
+ isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint);
+ if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint)));
+ if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset)));
+ lb_build_stmt(p, rs->body);
- lb_build_stmt(p, rs->body);
+ offset += width;
+ } while (offset < str.len);
}
+ break;
+ case Type_Array:
+ if (t->Array.count > 0) {
+ lbValue val = lb_build_expr(p, expr);
+ lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
+
+ for (i64 i = 0; i < t->Array.count; i++) {
+ if (val0_type) {
+ // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
+ lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
+ lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
+ }
+ if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i)));
- }
- break;
- case Type_EnumeratedArray:
- if (t->EnumeratedArray.count > 0) {
- lbValue val = lb_build_expr(p, expr);
- lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
-
- for (i64 i = 0; i < t->EnumeratedArray.count; i++) {
- if (val0_type) {
- // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
- lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
- lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
+ lb_build_stmt(p, rs->body);
}
- if (val1_type) {
- ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value);
- lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx));
+
+ }
+ break;
+ case Type_EnumeratedArray:
+ if (t->EnumeratedArray.count > 0) {
+ lbValue val = lb_build_expr(p, expr);
+ lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
+
+ for (i64 i = 0; i < t->EnumeratedArray.count; i++) {
+ if (val0_type) {
+ // NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
+ lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
+ lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
+ }
+ if (val1_type) {
+ ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value);
+ lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx));
+ }
+
+ lb_build_stmt(p, rs->body);
}
- lb_build_stmt(p, rs->body);
}
+ break;
+ default:
+ GB_PANIC("Invalid '#unroll for' type");
+ break;
+ }
+ } else {
+
+ ////////////////////////////////
+ // //
+ // #unroll(N) logic //
+ // //
+ ////////////////////////////////
+
+
+ i64 unroll_count = exact_value_to_i64(unroll_count_ev);
+ gb_unused(unroll_count);
+
+ Type *t = base_type(expr->tav.type);
+ lbValue data_ptr = {};
+ lbValue count_ptr = {};
+
+ switch (t->kind) {
+ case Type_Slice:
+ case Type_DynamicArray: {
+ lbValue slice = lb_build_expr(p, expr);
+ if (is_type_pointer(slice.type)) {
+ count_ptr = lb_emit_struct_ep(p, slice, 1);
+ slice = lb_emit_load(p, slice);
+ } else {
+ count_ptr = lb_add_local_generated(p, t_int, false).addr;
+ lb_emit_store(p, count_ptr, lb_slice_len(p, slice));
+ }
+ data_ptr = lb_emit_struct_ev(p, slice, 0);
+ break;
}
- break;
- default:
- GB_PANIC("Invalid '#unroll for' type");
- break;
+
+ case Type_Array: {
+ lbValue array = lb_build_expr(p, expr);
+ count_ptr = lb_add_local_generated(p, t_int, false).addr;
+ lb_emit_store(p, count_ptr, lb_const_int(p->module, t_int, t->Array.count));
+
+ if (!is_type_pointer(array.type)) {
+ array = lb_address_from_load_or_generate_local(p, array);
+ }
+
+ GB_ASSERT(is_type_pointer(array.type));
+ data_ptr = lb_emit_conv(p, array, alloc_type_pointer(t->Array.elem));
+ break;
+ }
+
+ default:
+ GB_PANIC("Invalid '#unroll for' type");
+ break;
+ }
+
+ data_ptr.type = alloc_type_multi_pointer_to_pointer(data_ptr.type);
+
+ lbBlock *loop_top = lb_create_block(p, "for.unroll.loop.top");
+
+ lbBlock *body_top = lb_create_block(p, "for.unroll.body.top");
+ lbBlock *body_bot = lb_create_block(p, "for.unroll.body.bot");
+
+ lbBlock *done = lb_create_block(p, "for.unroll.done");
+
+ lbBlock *loop_bot = unroll_count > 1 ? lb_create_block(p, "for.unroll.loop.bot") : done;
+
+ /*
+ i := 0
+ for ; i+N <= len(array); i += N {
+ body
+ }
+ for ; i < len(array); i += 1 {
+ body
+ }
+ */
+
+ Entity *val_entity = val0 ? entity_of_node(val0) : nullptr;
+ Entity *idx_entity = val1 ? entity_of_node(val1) : nullptr;
+
+ lbAddr val_addr = lb_add_local(p, type_deref(data_ptr.type, true), val_entity);
+ lbAddr idx_addr = lb_add_local(p, t_int, idx_entity);
+ lb_addr_store(p, idx_addr, lb_const_nil(p->module, t_int));
+
+ lb_emit_jump(p, loop_top);
+ lb_start_block(p, loop_top);
+
+ lbValue idx_add_n = lb_addr_load(p, idx_addr);
+ idx_add_n = lb_emit_arith(p, Token_Add, idx_add_n, lb_const_int(p->module, t_int, unroll_count), t_int);
+
+ lbValue cond_top = lb_emit_comp(p, Token_LtEq, idx_add_n, lb_emit_load(p, count_ptr));
+ lb_emit_if(p, cond_top, body_top, loop_bot);
+
+ lb_start_block(p, body_top);
+ for (i64 top = 0; top < unroll_count; top++) {
+ lbValue idx = lb_addr_load(p, idx_addr);
+ lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx));
+ lb_addr_store(p, val_addr, val);
+
+ lb_build_stmt(p, rs->body);
+
+ lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr));
+ }
+ lb_emit_jump(p, loop_top);
+
+ if (unroll_count > 1) {
+ lb_start_block(p, loop_bot);
+
+ lbValue cond_bot = lb_emit_comp(p, Token_Lt, lb_addr_load(p, idx_addr), lb_emit_load(p, count_ptr));
+ lb_emit_if(p, cond_bot, body_bot, done);
+
+ lb_start_block(p, body_bot);
+ {
+ lbValue idx = lb_addr_load(p, idx_addr);
+ lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx));
+ lb_addr_store(p, val_addr, val);
+
+ lb_build_stmt(p, rs->body);
+
+ lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr));
+ }
+ lb_emit_jump(p, loop_bot);
+ }
+
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
+ lb_emit_jump(p, done);
+ lb_start_block(p, done);
+
+ return;
}
}
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
}
gb_internal bool lb_switch_stmt_can_be_trivial_jump_table(AstSwitchStmt *ss, bool *default_found_) {
@@ -1433,6 +1561,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
ast_node(body, BlockStmt, ss->body);
isize case_count = body->stmts.count;
+ Ast *default_clause = nullptr;
Slice<Ast *> default_stmts = {};
lbBlock *default_fall = nullptr;
lbBlock *default_block = nullptr;
@@ -1482,6 +1611,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
if (cc->list.count == 0) {
// default case
+ default_clause = clause;
default_stmts = cc->stmts;
default_fall = fall;
if (switch_instr == nullptr) {
@@ -1552,7 +1682,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, fall);
lb_open_scope(p, body->scope);
lb_build_stmt_list(p, cc->stmts);
- lb_close_scope(p, lbDeferExit_Default, body);
+ lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1570,13 +1700,13 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope *
lb_push_target_list(p, ss->label, done, nullptr, default_fall);
lb_open_scope(p, default_block->scope);
lb_build_stmt_list(p, default_stmts);
- lb_close_scope(p, lbDeferExit_Default, default_block);
+ lb_close_scope(p, lbDeferExit_Default, default_block, default_clause);
lb_pop_target_list(p);
}
lb_emit_jump(p, done);
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, done);
+ lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) {
@@ -1627,7 +1757,7 @@ gb_internal void lb_type_case_body(lbProcedure *p, Ast *label, Ast *clause, lbBl
lb_push_target_list(p, label, done, nullptr, nullptr);
lb_build_stmt_list(p, cc->stmts);
- lb_close_scope(p, lbDeferExit_Default, body);
+ lb_close_scope(p, lbDeferExit_Default, body, clause);
lb_pop_target_list(p);
lb_emit_jump(p, done);
@@ -1835,7 +1965,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss
lb_emit_jump(p, done);
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, done);
+ lb_close_scope(p, lbDeferExit_Default, done, ss->body);
}
@@ -1959,7 +2089,7 @@ gb_internal void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice
p->in_multi_assignment = prev_in_assignment;
}
-gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
+gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res, TokenPos pos) {
lbFunctionType *ft = lb_get_function_type(p->module, p->type);
bool return_by_pointer = ft->ret.kind == lbArg_Indirect;
bool split_returns = ft->multiple_return_original_type != nullptr;
@@ -1982,7 +2112,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
}
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2012,7 +2142,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
}
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2021,7 +2151,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
}
}
}
-gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results) {
+gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return_results, TokenPos pos) {
lb_ensure_abi_function_type(p->module, p);
isize return_count = p->type->Proc.result_count;
@@ -2029,7 +2159,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
if (return_count == 0) {
// No return values
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
// Check for terminator in the defer stmts
LLVMValueRef instr = LLVMGetLastInstruction(p->curr_block->block);
@@ -2138,11 +2268,11 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
GB_ASSERT(result_values.count-1 == result_eps.count);
lb_addr_store(p, p->return_ptr, result_values[result_values.count-1]);
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
} else {
- return lb_build_return_stmt_internal(p, result_values[result_values.count-1]);
+ return lb_build_return_stmt_internal(p, result_values[result_values.count-1], pos);
}
} else {
@@ -2169,7 +2299,7 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
}
if (return_by_pointer) {
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr, pos);
LLVMBuildRetVoid(p->builder);
return;
}
@@ -2177,13 +2307,13 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
res = lb_emit_load(p, res);
}
}
- lb_build_return_stmt_internal(p, res);
+ lb_build_return_stmt_internal(p, res, pos);
}
gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
ast_node(is, IfStmt, node);
lb_open_scope(p, is->scope); // Scope #1
- defer (lb_close_scope(p, lbDeferExit_Default, nullptr));
+ defer (lb_close_scope(p, lbDeferExit_Default, nullptr, node));
lbBlock *then = lb_create_block(p, "if.then");
lbBlock *done = lb_create_block(p, "if.done");
@@ -2234,7 +2364,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
}
lb_emit_jump(p, done);
@@ -2251,7 +2381,7 @@ gb_internal void lb_build_if_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, scope_of_node(is->else_stmt));
lb_build_stmt(p, is->else_stmt);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, is->else_stmt);
lb_emit_jump(p, done);
}
@@ -2322,7 +2452,7 @@ gb_internal void lb_build_for_stmt(lbProcedure *p, Ast *node) {
}
lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node);
}
gb_internal void lb_build_assign_stmt_array(lbProcedure *p, TokenKind op, lbAddr const &lhs, lbValue const &value) {
@@ -2588,7 +2718,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
lb_open_scope(p, bs->scope);
lb_build_stmt_list(p, bs->stmts);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_close_scope(p, lbDeferExit_Default, nullptr, node);
if (done != nullptr) {
lb_emit_jump(p, done);
@@ -2702,7 +2832,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
case_end;
case_ast_node(rs, ReturnStmt, node);
- lb_build_return_stmt(p, rs->results);
+ lb_build_return_stmt(p, rs->results, ast_token(node).pos);
case_end;
case_ast_node(is, IfStmt, node);
@@ -2755,7 +2885,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
}
}
if (block != nullptr) {
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, node);
}
lb_emit_jump(p, block);
lb_start_block(p, lb_create_block(p, "unreachable"));
@@ -2795,7 +2925,13 @@ gb_internal void lb_build_defer_stmt(lbProcedure *p, lbDefer const &d) {
}
}
-gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block) {
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, TokenPos pos) {
+ TokenPos prev_token_pos = p->branch_location_pos;
+ if (p->uses_branch_location) {
+ p->branch_location_pos = pos;
+ }
+ defer (p->branch_location_pos = prev_token_pos);
+
isize count = p->defer_stmts.count;
isize i = count;
while (i --> 0) {
@@ -2822,6 +2958,21 @@ gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlo
}
}
+gb_internal void lb_emit_defer_stmts(lbProcedure *p, lbDeferExitKind kind, lbBlock *block, Ast *node) {
+ TokenPos pos = {};
+ if (node) {
+ if (node->kind == Ast_BlockStmt) {
+ pos = ast_end_token(node).pos;
+ } else if (node->kind == Ast_CaseClause) {
+ pos = ast_end_token(node).pos;
+ } else {
+ pos = ast_token(node).pos;
+ }
+ }
+ return lb_emit_defer_stmts(p, kind, block, pos);
+}
+
+
gb_internal void lb_add_defer_node(lbProcedure *p, isize scope_index, Ast *stmt) {
Type *pt = base_type(p->type);
GB_ASSERT(pt->kind == Type_Proc);