aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-06-08 18:51:31 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-06-08 18:51:31 -0400
commit771e88951a9af48335abe14e4c44b5c4f5b252de (patch)
treec6b4831bd61ba18dc819e6ebce1f50b841b4ad80 /src/codegen.cpp
parent52eb34718862928b5d83c58990d5d7a6b07e20e2 (diff)
downloadzig-771e88951a9af48335abe14e4c44b5c4f5b252de.tar.gz
zig-771e88951a9af48335abe14e4c44b5c4f5b252de.zip
result location mechanism for struct initialization
```zig export fn entry() void { const static = Foo{ .x = 9, .bar = Bar{ .y = 10 }, }; const runtime = foo(true); } fn foo(c: bool) Foo { return Foo{ .x = 12, .bar = if (c) bar1() else bar2(), }; } fn bar1() Bar { return Bar{ .y = 34 }; } fn bar2() Bar { return Bar{ .y = 56 }; } ``` ```llvm @0 = internal unnamed_addr constant %Foo { i32 9, %Bar { i32 10 } }, align 4 @1 = internal unnamed_addr constant %Bar { i32 34 }, align 4 @2 = internal unnamed_addr constant %Bar { i32 56 }, align 4 define void @entry() #2 !dbg !35 { Entry: %runtime = alloca %Foo, align 4 call void @llvm.dbg.declare(metadata %Foo* @0, metadata !39, metadata !DIExpression()), !dbg !50 call fastcc void @foo(%Foo* sret %runtime, i1 true), !dbg !51 call void @llvm.dbg.declare(metadata %Foo* %runtime, metadata !49, metadata !DIExpression()), !dbg !52 ret void, !dbg !53 } define internal fastcc void @foo(%Foo* nonnull sret, i1) unnamed_addr #2 !dbg !54 { Entry: %c = alloca i1, align 1 store i1 %1, i1* %c, align 1 call void @llvm.dbg.declare(metadata i1* %c, metadata !60, metadata !DIExpression()), !dbg !61 %2 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 0, !dbg !62 store i32 12, i32* %2, align 4, !dbg !62 %3 = getelementptr inbounds %Foo, %Foo* %0, i32 0, i32 1, !dbg !64 %4 = load i1, i1* %c, align 1, !dbg !65 br i1 %4, label %Then, label %Else, !dbg !65 Then: ; preds = %Entry call fastcc void @bar1(%Bar* sret %3), !dbg !66 br label %EndIf, !dbg !64 Else: ; preds = %Entry call fastcc void @bar2(%Bar* sret %3), !dbg !67 br label %EndIf, !dbg !64 EndIf: ; preds = %Else, %Then ret void, !dbg !68 } define internal fastcc void @bar1(%Bar* nonnull sret) unnamed_addr #2 !dbg !69 { Entry: %1 = bitcast %Bar* %0 to i8*, !dbg !73 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @1 to i8*), i64 4, i1 false), !dbg !73 ret void, !dbg !73 } define internal fastcc void @bar2(%Bar* nonnull sret) unnamed_addr #2 !dbg !75 { Entry: %1 = bitcast %Bar* %0 to i8*, !dbg !76 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Bar* @2 to i8*), i64 4, i1 false), !dbg !76 ret void, !dbg !76 } !39 = !DILocalVariable(name: "static", scope: !40, file: !5, line: 2, type: !41) !49 = !DILocalVariable(name: "runtime", scope: !40, file: !5, line: 6, type: !41) ```
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp73
1 files changed, 39 insertions, 34 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index eecc2239db..4fa13c39a2 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -715,6 +715,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
case ScopeIdCompTime:
case ScopeIdCoroPrelude:
case ScopeIdRuntime:
+ case ScopeIdElide:
return get_di_scope(g, scope->parent);
}
zig_unreachable();
@@ -2383,7 +2384,6 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, IrExecutable *execut
}
static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
- LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
ZigType *return_type = return_instruction->value->value.type;
if (want_first_arg_sret(g, &g->cur_fn->type_entry->data.fn.fn_type_id)) {
@@ -2391,13 +2391,16 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
if (return_instruction->value->value.special != ConstValSpecialRuntime) {
// if it's comptime we have to do this but if it's runtime trust that
// result location mechanism took care of it.
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
}
LLVMBuildRetVoid(g->builder);
} else if (handle_is_ptr(return_type)) {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, "");
LLVMBuildRet(g->builder, by_val_value);
} else {
+ LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
LLVMBuildRet(g->builder, value);
}
return nullptr;
@@ -5032,29 +5035,6 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, IrExecutable *executable, Ir
return get_handle_value(g, tag_field_ptr, tag_type, ptr_type);
}
-static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable, IrInstructionStructInit *instruction) {
- for (size_t i = 0; i < instruction->field_count; i += 1) {
- IrInstructionStructInitField *field = &instruction->fields[i];
- TypeStructField *type_struct_field = field->type_struct_field;
- if (!type_has_bits(type_struct_field->type_entry))
- continue;
-
- LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
- (unsigned)type_struct_field->gen_index, "");
- LLVMValueRef value = ir_llvm_value(g, field->value);
-
- uint32_t field_align_bytes = get_abi_alignment(g, type_struct_field->type_entry);
- uint32_t host_int_bytes = get_host_int_bytes(g, instruction->struct_type, type_struct_field);
-
- ZigType *ptr_type = get_pointer_to_type_extra(g, type_struct_field->type_entry,
- false, false, PtrLenSingle, field_align_bytes,
- (uint32_t)type_struct_field->bit_offset_in_host, host_int_bytes, false);
-
- gen_assign_raw(g, field_ptr, ptr_type, value);
- }
- return instruction->tmp_ptr;
-}
-
static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
TypeUnionField *type_union_field = instruction->field;
@@ -5531,10 +5511,6 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
}
static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
- if (!g->strip_debug_symbols) {
- set_debug_location(g, instruction);
- }
-
switch (instruction->id) {
case IrInstructionIdInvalid:
case IrInstructionIdConst:
@@ -5609,6 +5585,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdEndExpr:
case IrInstructionIdAllocaGen:
case IrInstructionIdImplicitCast:
+ case IrInstructionIdResolveResult:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5705,8 +5682,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_err_wrap_payload(g, executable, (IrInstructionErrWrapPayload *)instruction);
case IrInstructionIdUnionTag:
return ir_render_union_tag(g, executable, (IrInstructionUnionTag *)instruction);
- case IrInstructionIdStructInit:
- return ir_render_struct_init(g, executable, (IrInstructionStructInit *)instruction);
case IrInstructionIdUnionInit:
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
@@ -5791,6 +5766,34 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
zig_unreachable();
}
+static bool scope_is_elided(Scope *scope) {
+ for (;;) {
+ switch (scope->id) {
+ case ScopeIdDecls:
+ case ScopeIdCompTime:
+ case ScopeIdCImport:
+ zig_unreachable();
+ case ScopeIdElide:
+ if (reinterpret_cast<ScopeElide *>(scope)->activated)
+ return true;
+ // fallthrough
+ case ScopeIdBlock:
+ case ScopeIdDefer:
+ case ScopeIdDeferExpr:
+ case ScopeIdVarDecl:
+ case ScopeIdLoop:
+ case ScopeIdSuspend:
+ case ScopeIdCoroPrelude:
+ case ScopeIdRuntime:
+ scope = scope->parent;
+ continue;
+ case ScopeIdFnDef:
+ return false;
+ }
+ zig_unreachable();
+ }
+}
+
static void ir_render(CodeGen *g, ZigFn *fn_entry) {
assert(fn_entry);
@@ -5806,7 +5809,12 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
continue;
- instruction->llvm_value = ir_render_instruction(g, executable, instruction);
+ if (!scope_is_elided(instruction->scope)) {
+ if (!g->strip_debug_symbols) {
+ set_debug_location(g, instruction);
+ }
+ instruction->llvm_value = ir_render_instruction(g, executable, instruction);
+ }
}
current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
}
@@ -6891,9 +6899,6 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdContainerInitList) {
IrInstructionContainerInitList *container_init_list_instruction = (IrInstructionContainerInitList *)instruction;
slot = &container_init_list_instruction->tmp_ptr;
- } else if (instruction->id == IrInstructionIdStructInit) {
- IrInstructionStructInit *struct_init_instruction = (IrInstructionStructInit *)instruction;
- slot = &struct_init_instruction->tmp_ptr;
} else if (instruction->id == IrInstructionIdUnionInit) {
IrInstructionUnionInit *union_init_instruction = (IrInstructionUnionInit *)instruction;
slot = &union_init_instruction->tmp_ptr;