aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-05-24 22:09:21 +0100
committergingerBill <bill@gingerbill.org>2021-05-24 22:09:21 +0100
commit3f156bcb4b4d428c9d8547d63de145f01080d043 (patch)
tree4b4cb2574d3f065c8a8d0b2d73240b086c1a45be /src/llvm_backend.cpp
parentd35a9e65b68e9d38f470c3cf0e54909e08d7bde8 (diff)
Refactor backend code for assignments; Refactor some statements into separate procedures
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp734
1 files changed, 335 insertions, 399 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index bc519f70d..9121bc083 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -4425,7 +4425,7 @@ void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *scope) {
lb_start_block(p, done);
}
-void lb_build_inline_range_stmt(lbProcedure *p, AstUnrollRangeStmt *rs, Scope *scope) {
+void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *rs, Scope *scope) {
lbModule *m = p->module;
lb_open_scope(p, scope); // Open scope here
@@ -4943,6 +4943,321 @@ void lb_reset_copy_elision_hint(lbProcedure *p, lbCopyElisionHint prev_hint) {
p->copy_elision_hint = prev_hint;
}
+void lb_build_static_variables(lbProcedure *p, AstValueDecl *vd) {
+ for_array(i, vd->names) {
+ lbValue value = {};
+ if (vd->values.count > 0) {
+ GB_ASSERT(vd->names.count == vd->values.count);
+ Ast *ast_value = vd->values[i];
+ GB_ASSERT(ast_value->tav.mode == Addressing_Constant ||
+ ast_value->tav.mode == Addressing_Invalid);
+
+ bool allow_local = false;
+ value = lb_const_value(p->module, ast_value->tav.type, ast_value->tav.value, allow_local);
+ }
+
+ Ast *ident = vd->names[i];
+ GB_ASSERT(!is_blank_ident(ident));
+ Entity *e = entity_of_node(ident);
+ GB_ASSERT(e->flags & EntityFlag_Static);
+ String name = e->token.string;
+
+ String mangled_name = {};
+ {
+ gbString str = gb_string_make_length(permanent_allocator(), p->name.text, p->name.len);
+ str = gb_string_appendc(str, "-");
+ str = gb_string_append_fmt(str, ".%.*s-%llu", LIT(name), cast(long long)e->id);
+ mangled_name.text = cast(u8 *)str;
+ mangled_name.len = gb_string_length(str);
+ }
+
+ char *c_name = alloc_cstring(permanent_allocator(), mangled_name);
+
+ LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(p->module, e->type), c_name);
+ LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
+ if (value.value != nullptr) {
+ LLVMSetInitializer(global, value.value);
+ } else {
+ }
+ if (e->Variable.thread_local_model != "") {
+ LLVMSetThreadLocal(global, true);
+
+ String m = e->Variable.thread_local_model;
+ LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
+ if (m == "default") {
+ mode = LLVMGeneralDynamicTLSModel;
+ } else if (m == "localdynamic") {
+ mode = LLVMLocalDynamicTLSModel;
+ } else if (m == "initialexec") {
+ mode = LLVMInitialExecTLSModel;
+ } else if (m == "localexec") {
+ mode = LLVMLocalExecTLSModel;
+ } else {
+ GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
+ }
+ LLVMSetThreadLocalMode(global, mode);
+ } else {
+ LLVMSetLinkage(global, LLVMInternalLinkage);
+ }
+
+
+ lbValue global_val = {global, alloc_type_pointer(e->type)};
+ lb_add_entity(p->module, e, global_val);
+ lb_add_member(p->module, mangled_name, global_val);
+ }
+}
+
+
+void lb_build_assignment(lbProcedure *p, Array<lbAddr> &lvals, Slice<Ast *> const &values) {
+ if (values.count == 0) {
+ return;
+ }
+
+ auto inits = array_make<lbValue>(permanent_allocator(), 0, lvals.count);
+
+ for_array(i, values) {
+ Ast *rhs = values[i];
+ if (is_type_tuple(type_of_expr(rhs))) {
+ lbValue init = lb_build_expr(p, rhs);
+ Type *t = init.type;
+ GB_ASSERT(t->kind == Type_Tuple);
+ for_array(i, t->Tuple.variables) {
+ Entity *e = t->Tuple.variables[i];
+ lbValue v = lb_emit_struct_ev(p, init, cast(i32)i);
+ array_add(&inits, v);
+ }
+ } else {
+ auto prev_hint = lb_set_copy_elision_hint(p, lvals[inits.count], rhs);
+ lbValue init = lb_build_expr(p, rhs);
+ if (p->copy_elision_hint.used) {
+ lvals[inits.count] = {}; // zero lval
+ }
+ lb_reset_copy_elision_hint(p, prev_hint);
+ array_add(&inits, init);
+ }
+ }
+
+ GB_ASSERT(lvals.count == inits.count);
+ for_array(i, inits) {
+ lbAddr lval = lvals[i];
+ lbValue init = inits[i];
+ lb_addr_store(p, lval, init);
+ }
+}
+
+void lb_build_return_stmt(lbProcedure *p, AstReturnStmt *rs) {
+ lbValue res = {};
+
+ TypeTuple *tuple = &p->type->Proc.results->Tuple;
+ isize return_count = p->type->Proc.result_count;
+ isize res_count = rs->results.count;
+
+ if (return_count == 0) {
+ // No return values
+
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+
+ LLVMBuildRetVoid(p->builder);
+ return;
+ } else if (return_count == 1) {
+ Entity *e = tuple->variables[0];
+ if (res_count == 0) {
+ lbValue *found = map_get(&p->module->values, hash_entity(e));
+ GB_ASSERT(found);
+ res = lb_emit_load(p, *found);
+ } else {
+ res = lb_build_expr(p, rs->results[0]);
+ res = lb_emit_conv(p, res, e->type);
+ }
+ if (p->type->Proc.has_named_results) {
+ // NOTE(bill): store the named values before returning
+ if (e->token.string != "") {
+ lbValue *found = map_get(&p->module->values, hash_entity(e));
+ GB_ASSERT(found != nullptr);
+ lb_emit_store(p, *found, lb_emit_conv(p, res, e->type));
+ }
+ }
+
+ } else {
+ auto results = array_make<lbValue>(permanent_allocator(), 0, return_count);
+
+ if (res_count != 0) {
+ for (isize res_index = 0; res_index < res_count; res_index++) {
+ lbValue res = lb_build_expr(p, rs->results[res_index]);
+ Type *t = res.type;
+ if (t->kind == Type_Tuple) {
+ for_array(i, t->Tuple.variables) {
+ Entity *e = t->Tuple.variables[i];
+ lbValue v = lb_emit_struct_ev(p, res, cast(i32)i);
+ array_add(&results, v);
+ }
+ } else {
+ array_add(&results, res);
+ }
+ }
+ } else {
+ for (isize res_index = 0; res_index < return_count; res_index++) {
+ Entity *e = tuple->variables[res_index];
+ lbValue *found = map_get(&p->module->values, hash_entity(e));
+ GB_ASSERT(found);
+ lbValue res = lb_emit_load(p, *found);
+ array_add(&results, res);
+ }
+ }
+
+ GB_ASSERT(results.count == return_count);
+
+ if (p->type->Proc.has_named_results) {
+ // NOTE(bill): store the named values before returning
+ for_array(i, p->type->Proc.results->Tuple.variables) {
+ Entity *e = p->type->Proc.results->Tuple.variables[i];
+ if (e->kind != Entity_Variable) {
+ continue;
+ }
+
+ if (e->token.string == "") {
+ continue;
+ }
+ lbValue *found = map_get(&p->module->values, hash_entity(e));
+ GB_ASSERT(found != nullptr);
+ lb_emit_store(p, *found, lb_emit_conv(p, results[i], e->type));
+ }
+ }
+
+ Type *ret_type = p->type->Proc.results;
+ // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
+ res = lb_add_local_generated(p, ret_type, false).addr;
+ for_array(i, results) {
+ Entity *e = tuple->variables[i];
+ lbValue field = lb_emit_struct_ep(p, res, cast(i32)i);
+ lbValue val = lb_emit_conv(p, results[i], e->type);
+ lb_emit_store(p, field, val);
+ }
+
+ res = lb_emit_load(p, res);
+ }
+
+
+ lb_ensure_abi_function_type(p->module, p);
+ if (p->abi_function_type->ret.kind == lbArg_Indirect) {
+ if (res.value != nullptr) {
+ LLVMBuildStore(p->builder, res.value, p->return_ptr.addr.value);
+ } else {
+ LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
+ }
+
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+
+ LLVMBuildRetVoid(p->builder);
+ } else {
+ LLVMValueRef ret_val = res.value;
+ ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
+ if (p->abi_function_type->ret.cast_type != nullptr) {
+ ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type);
+ }
+
+ lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
+ LLVMBuildRet(p->builder, ret_val);
+ }
+}
+
+void lb_build_if_stmt(lbProcedure *p, Ast *node) {
+ ast_node(is, IfStmt, node);
+ lb_open_scope(p, node->scope); // Scope #1
+
+ if (is->init != nullptr) {
+ // TODO(bill): Should this have a separate block to begin with?
+ #if 1
+ lbBlock *init = lb_create_block(p, "if.init");
+ lb_emit_jump(p, init);
+ lb_start_block(p, init);
+ #endif
+ lb_build_stmt(p, is->init);
+ }
+ lbBlock *then = lb_create_block(p, "if.then");
+ lbBlock *done = lb_create_block(p, "if.done");
+ lbBlock *else_ = done;
+ if (is->else_stmt != nullptr) {
+ else_ = lb_create_block(p, "if.else");
+ }
+
+ lb_build_cond(p, is->cond, then, else_);
+ lb_start_block(p, then);
+
+ if (is->label != nullptr) {
+ lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr);
+ tl->is_block = true;
+ }
+
+ lb_build_stmt(p, is->body);
+
+ lb_emit_jump(p, done);
+
+ if (is->else_stmt != nullptr) {
+ lb_start_block(p, else_);
+
+ lb_open_scope(p, is->else_stmt->scope);
+ lb_build_stmt(p, is->else_stmt);
+ lb_close_scope(p, lbDeferExit_Default, nullptr);
+
+ lb_emit_jump(p, done);
+ }
+
+ lb_start_block(p, done);
+ lb_close_scope(p, lbDeferExit_Default, nullptr);
+}
+
+void lb_build_for_stmt(lbProcedure *p, Ast *node) {
+ ast_node(fs, ForStmt, node);
+
+ lb_open_scope(p, node->scope); // Open Scope here
+
+ if (fs->init != nullptr) {
+ #if 1
+ lbBlock *init = lb_create_block(p, "for.init");
+ lb_emit_jump(p, init);
+ lb_start_block(p, init);
+ #endif
+ lb_build_stmt(p, fs->init);
+ }
+ lbBlock *body = lb_create_block(p, "for.body");
+ lbBlock *done = lb_create_block(p, "for.done"); // NOTE(bill): Append later
+ lbBlock *loop = body;
+ if (fs->cond != nullptr) {
+ loop = lb_create_block(p, "for.loop");
+ }
+ lbBlock *post = loop;
+ if (fs->post != nullptr) {
+ post = lb_create_block(p, "for.post");
+ }
+
+
+ lb_emit_jump(p, loop);
+ lb_start_block(p, loop);
+
+ if (loop != body) {
+ lb_build_cond(p, fs->cond, body, done);
+ lb_start_block(p, body);
+ }
+
+ lb_push_target_list(p, fs->label, done, post, nullptr);
+
+ lb_build_stmt(p, fs->body);
+ lb_close_scope(p, lbDeferExit_Default, nullptr);
+
+ lb_pop_target_list(p);
+
+ lb_emit_jump(p, post);
+
+ if (fs->post != nullptr) {
+ lb_start_block(p, post);
+ lb_build_stmt(p, fs->post);
+ lb_emit_jump(p, loop);
+ }
+
+ lb_start_block(p, done);
+}
+
void lb_build_stmt(lbProcedure *p, Ast *node) {
Ast *prev_stmt = p->curr_stmt;
@@ -5028,156 +5343,24 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
}
if (is_static) {
- for_array(i, vd->names) {
- lbValue value = {};
- if (vd->values.count > 0) {
- GB_ASSERT(vd->names.count == vd->values.count);
- Ast *ast_value = vd->values[i];
- GB_ASSERT(ast_value->tav.mode == Addressing_Constant ||
- ast_value->tav.mode == Addressing_Invalid);
-
- bool allow_local = false;
- value = lb_const_value(p->module, ast_value->tav.type, ast_value->tav.value, allow_local);
- }
-
- Ast *ident = vd->names[i];
- GB_ASSERT(!is_blank_ident(ident));
- Entity *e = entity_of_node(ident);
- GB_ASSERT(e->flags & EntityFlag_Static);
- String name = e->token.string;
-
- String mangled_name = {};
- {
- gbString str = gb_string_make_length(permanent_allocator(), p->name.text, p->name.len);
- str = gb_string_appendc(str, "-");
- str = gb_string_append_fmt(str, ".%.*s-%llu", LIT(name), cast(long long)e->id);
- mangled_name.text = cast(u8 *)str;
- mangled_name.len = gb_string_length(str);
- }
-
- char *c_name = alloc_cstring(permanent_allocator(), mangled_name);
-
- LLVMValueRef global = LLVMAddGlobal(p->module->mod, lb_type(p->module, e->type), c_name);
- LLVMSetInitializer(global, LLVMConstNull(lb_type(p->module, e->type)));
- if (value.value != nullptr) {
- LLVMSetInitializer(global, value.value);
- } else {
- }
- if (e->Variable.thread_local_model != "") {
- LLVMSetThreadLocal(global, true);
-
- String m = e->Variable.thread_local_model;
- LLVMThreadLocalMode mode = LLVMGeneralDynamicTLSModel;
- if (m == "default") {
- mode = LLVMGeneralDynamicTLSModel;
- } else if (m == "localdynamic") {
- mode = LLVMLocalDynamicTLSModel;
- } else if (m == "initialexec") {
- mode = LLVMInitialExecTLSModel;
- } else if (m == "localexec") {
- mode = LLVMLocalExecTLSModel;
- } else {
- GB_PANIC("Unhandled thread local mode %.*s", LIT(m));
- }
- LLVMSetThreadLocalMode(global, mode);
- } else {
- LLVMSetLinkage(global, LLVMInternalLinkage);
- }
-
-
- lbValue global_val = {global, alloc_type_pointer(e->type)};
- lb_add_entity(p->module, e, global_val);
- lb_add_member(p->module, mangled_name, global_val);
- }
+ lb_build_static_variables(p, vd);
return;
}
- if (vd->values.count == 0) { // declared and zero-initialized
- for_array(i, vd->names) {
- Ast *name = vd->names[i];
- if (!is_blank_ident(name)) {
- Entity *e = entity_of_node(name);
- lb_add_local(p, e->type, e, true);
- }
- }
- } else if (vd->names.count == vd->values.count) {
- auto lvals = array_make<lbAddr>(permanent_allocator(), 0, vd->names.count);
- auto inits = array_make<lbValue>(permanent_allocator(), 0, vd->names.count);
-
- for_array(i, vd->names) {
- Ast *name = vd->names[i];
- lbAddr lval = {};
- if (!is_blank_ident(name)) {
- Entity *e = entity_of_node(name);
- bool zero_init = true;
- if (vd->names.count == vd->values.count) {
- // Possibly uses copy elision
- // Make the caller mem zero
- zero_init = true;
- }
- lval = lb_add_local(p, e->type, e, zero_init);
- }
- array_add(&lvals, lval);
- }
-
- for_array(i, vd->values) {
- Ast *rhs = unparen_expr(vd->values[i]);
-
- auto prev_hint = lb_set_copy_elision_hint(p, lvals[i], rhs);
-
- lbValue init = lb_build_expr(p, rhs);
- Type *t = init.type;
- GB_ASSERT(t->kind != Type_Tuple);
- array_add(&inits, init);
-
- if (p->copy_elision_hint.used) {
- lvals[i] = {}; // zero lval
- }
- lb_reset_copy_elision_hint(p, prev_hint);
- }
-
- for_array(i, inits) {
- lbAddr lval = lvals[i];
- lbValue init = inits[i];
- lb_addr_store(p, lval, init);
- }
- } else { // Tuple(s)
- auto lvals = array_make<lbAddr>(permanent_allocator(), 0, vd->names.count);
- auto inits = array_make<lbValue>(permanent_allocator(), 0, vd->names.count);
+ auto lvals = array_make<lbAddr>(permanent_allocator(), 0, vd->names.count);
- for_array(i, vd->names) {
- Ast *name = vd->names[i];
- lbAddr lval = {};
- if (!is_blank_ident(name)) {
- Entity *e = entity_of_node(name);
- bool zero_init = false;
- lval = lb_add_local(p, e->type, e, zero_init);
- }
- array_add(&lvals, lval);
- }
-
- for_array(i, vd->values) {
- Ast *rhs = unparen_expr(vd->values[i]);
- lbValue init = lb_build_expr(p, rhs);
- Type *t = init.type;
- if (t->kind == Type_Tuple) {
- for_array(i, t->Tuple.variables) {
- Entity *e = t->Tuple.variables[i];
- lbValue v = lb_emit_struct_ev(p, init, cast(i32)i);
- array_add(&inits, v);
- }
- } else {
- array_add(&inits, init);
- }
- }
-
- for_array(i, inits) {
- lbAddr lval = lvals[i];
- lbValue init = inits[i];
- lb_addr_store(p, lval, init);
+ for_array(i, vd->names) {
+ Ast *name = vd->names[i];
+ lbAddr lval = {};
+ if (!is_blank_ident(name)) {
+ Entity *e = entity_of_node(name);
+ bool zero_init = true; // Zero always and optimize out later
+ lval = lb_add_local(p, e->type, e, zero_init);
}
+ array_add(&lvals, lval);
}
+ lb_build_assignment(p, lvals, vd->values);
case_end;
case_ast_node(as, AssignStmt, node);
@@ -5192,54 +5375,10 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
}
array_add(&lvals, lval);
}
-
- if (as->lhs.count == as->rhs.count) {
- auto inits = array_make<lbValue>(permanent_allocator(), 0, lvals.count);
-
- for_array(i, as->rhs) {
- Ast *rhs = unparen_expr(as->rhs[i]);
-
- auto prev_hint = lb_set_copy_elision_hint(p, lvals[i], rhs);
-
- lbValue init = lb_build_expr(p, rhs);
- array_add(&inits, init);
-
- if (p->copy_elision_hint.used) {
- lvals[i] = {}; // zero lval
- }
- lb_reset_copy_elision_hint(p, prev_hint);
- }
-
- for_array(i, inits) {
- lbAddr lval = lvals[i];
- lbValue init = inits[i];
- lb_addr_store(p, lval, init);
- }
- } else {
- auto inits = array_make<lbValue>(permanent_allocator(), 0, lvals.count);
-
- for_array(i, as->rhs) {
- lbValue init = lb_build_expr(p, as->rhs[i]);
- Type *t = init.type;
- // TODO(bill): refactor for code reuse as this is repeated a bit
- if (t->kind == Type_Tuple) {
- for_array(i, t->Tuple.variables) {
- Entity *e = t->Tuple.variables[i];
- lbValue v = lb_emit_struct_ev(p, init, cast(i32)i);
- array_add(&inits, v);
- }
- } else {
- array_add(&inits, init);
- }
- }
-
- for_array(i, inits) {
- lbAddr lval = lvals[i];
- lbValue init = inits[i];
- lb_addr_store(p, lval, init);
- }
- }
+ lb_build_assignment(p, lvals, as->rhs);
} else {
+ GB_ASSERT(as->lhs.count == 1);
+ GB_ASSERT(as->rhs.count == 1);
// NOTE(bill): Only 1 += 1 is allowed, no tuples
// +=, -=, etc
i32 op = cast(i32)as->op.kind;
@@ -5270,222 +5409,19 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
case_end;
case_ast_node(ds, DeferStmt, node);
- isize scope_index = p->scope_index;
- lb_add_defer_node(p, scope_index, ds->stmt);
+ lb_add_defer_node(p, p->scope_index, ds->stmt);
case_end;
case_ast_node(rs, ReturnStmt, node);
- lbValue res = {};
-
- TypeTuple *tuple = &p->type->Proc.results->Tuple;
- isize return_count = p->type->Proc.result_count;
- isize res_count = rs->results.count;
-
- if (return_count == 0) {
- // No return values
-
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
-
- LLVMBuildRetVoid(p->builder);
- return;
- } else if (return_count == 1) {
- Entity *e = tuple->variables[0];
- if (res_count == 0) {
- lbValue *found = map_get(&p->module->values, hash_entity(e));
- GB_ASSERT(found);
- res = lb_emit_load(p, *found);
- } else {
- res = lb_build_expr(p, rs->results[0]);
- res = lb_emit_conv(p, res, e->type);
- }
- if (p->type->Proc.has_named_results) {
- // NOTE(bill): store the named values before returning
- if (e->token.string != "") {
- lbValue *found = map_get(&p->module->values, hash_entity(e));
- GB_ASSERT(found != nullptr);
- lb_emit_store(p, *found, lb_emit_conv(p, res, e->type));
- }
- }
-
- } else {
- auto results = array_make<lbValue>(permanent_allocator(), 0, return_count);
-
- if (res_count != 0) {
- for (isize res_index = 0; res_index < res_count; res_index++) {
- lbValue res = lb_build_expr(p, rs->results[res_index]);
- Type *t = res.type;
- if (t->kind == Type_Tuple) {
- for_array(i, t->Tuple.variables) {
- Entity *e = t->Tuple.variables[i];
- lbValue v = lb_emit_struct_ev(p, res, cast(i32)i);
- array_add(&results, v);
- }
- } else {
- array_add(&results, res);
- }
- }
- } else {
- for (isize res_index = 0; res_index < return_count; res_index++) {
- Entity *e = tuple->variables[res_index];
- lbValue *found = map_get(&p->module->values, hash_entity(e));
- GB_ASSERT(found);
- lbValue res = lb_emit_load(p, *found);
- array_add(&results, res);
- }
- }
-
- GB_ASSERT(results.count == return_count);
-
- if (p->type->Proc.has_named_results) {
- // NOTE(bill): store the named values before returning
- for_array(i, p->type->Proc.results->Tuple.variables) {
- Entity *e = p->type->Proc.results->Tuple.variables[i];
- if (e->kind != Entity_Variable) {
- continue;
- }
-
- if (e->token.string == "") {
- continue;
- }
- lbValue *found = map_get(&p->module->values, hash_entity(e));
- GB_ASSERT(found != nullptr);
- lb_emit_store(p, *found, lb_emit_conv(p, results[i], e->type));
- }
- }
-
- Type *ret_type = p->type->Proc.results;
- // NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
- res = lb_add_local_generated(p, ret_type, false).addr;
- for_array(i, results) {
- Entity *e = tuple->variables[i];
- lbValue field = lb_emit_struct_ep(p, res, cast(i32)i);
- lbValue val = lb_emit_conv(p, results[i], e->type);
- lb_emit_store(p, field, val);
- }
-
- res = lb_emit_load(p, res);
- }
-
-
- lb_ensure_abi_function_type(p->module, p);
- if (p->abi_function_type->ret.kind == lbArg_Indirect) {
- if (res.value != nullptr) {
- LLVMBuildStore(p->builder, res.value, p->return_ptr.addr.value);
- } else {
- LLVMBuildStore(p->builder, LLVMConstNull(p->abi_function_type->ret.type), p->return_ptr.addr.value);
- }
-
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
-
- LLVMBuildRetVoid(p->builder);
- } else {
- LLVMValueRef ret_val = res.value;
- ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
- if (p->abi_function_type->ret.cast_type != nullptr) {
- ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type);
- }
-
- lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
- LLVMBuildRet(p->builder, ret_val);
- }
-
-
-
+ lb_build_return_stmt(p, rs);
case_end;
case_ast_node(is, IfStmt, node);
- lb_open_scope(p, node->scope); // Scope #1
-
- if (is->init != nullptr) {
- // TODO(bill): Should this have a separate block to begin with?
- #if 1
- lbBlock *init = lb_create_block(p, "if.init");
- lb_emit_jump(p, init);
- lb_start_block(p, init);
- #endif
- lb_build_stmt(p, is->init);
- }
- lbBlock *then = lb_create_block(p, "if.then");
- lbBlock *done = lb_create_block(p, "if.done");
- lbBlock *else_ = done;
- if (is->else_stmt != nullptr) {
- else_ = lb_create_block(p, "if.else");
- }
-
- lb_build_cond(p, is->cond, then, else_);
- lb_start_block(p, then);
-
- if (is->label != nullptr) {
- lbTargetList *tl = lb_push_target_list(p, is->label, done, nullptr, nullptr);
- tl->is_block = true;
- }
-
- lb_build_stmt(p, is->body);
-
- lb_emit_jump(p, done);
-
- if (is->else_stmt != nullptr) {
- lb_start_block(p, else_);
-
- lb_open_scope(p, is->else_stmt->scope);
- lb_build_stmt(p, is->else_stmt);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
-
- lb_emit_jump(p, done);
- }
-
-
- lb_start_block(p, done);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
+ lb_build_if_stmt(p, node);
case_end;
case_ast_node(fs, ForStmt, node);
- lb_open_scope(p, node->scope); // Open Scope here
-
- if (fs->init != nullptr) {
- #if 1
- lbBlock *init = lb_create_block(p, "for.init");
- lb_emit_jump(p, init);
- lb_start_block(p, init);
- #endif
- lb_build_stmt(p, fs->init);
- }
- lbBlock *body = lb_create_block(p, "for.body");
- lbBlock *done = lb_create_block(p, "for.done"); // NOTE(bill): Append later
- lbBlock *loop = body;
- if (fs->cond != nullptr) {
- loop = lb_create_block(p, "for.loop");
- }
- lbBlock *post = loop;
- if (fs->post != nullptr) {
- post = lb_create_block(p, "for.post");
- }
-
-
- lb_emit_jump(p, loop);
- lb_start_block(p, loop);
-
- if (loop != body) {
- lb_build_cond(p, fs->cond, body, done);
- lb_start_block(p, body);
- }
-
- lb_push_target_list(p, fs->label, done, post, nullptr);
-
- lb_build_stmt(p, fs->body);
- lb_close_scope(p, lbDeferExit_Default, nullptr);
-
- lb_pop_target_list(p);
-
- lb_emit_jump(p, post);
-
- if (fs->post != nullptr) {
- lb_start_block(p, post);
- lb_build_stmt(p, fs->post);
- lb_emit_jump(p, loop);
- }
-
- lb_start_block(p, done);
+ lb_build_for_stmt(p, node);
case_end;
case_ast_node(rs, RangeStmt, node);
@@ -5493,7 +5429,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
case_end;
case_ast_node(rs, UnrollRangeStmt, node);
- lb_build_inline_range_stmt(p, rs, node->scope);
+ lb_build_unroll_range_stmt(p, rs, node->scope);
case_end;
case_ast_node(ss, SwitchStmt, node);