Skip to content

Commit c7c3cfc

Browse files
committed
copy elision - var decl init to aggregate fn call
```zig export fn entry() void { var y = foo(); } fn foo() Foo { return Foo.{ .x = 1, .y = 2, }; } ``` ```llvm define void @entry() #2 !dbg !41 { Entry: %y = alloca %Foo, align 4 call fastcc void @foo(%Foo* sret %y), !dbg !52 call void @llvm.dbg.declare(metadata %Foo* %y, metadata !45, metadata !DIExpression()), !dbg !53 ret void, !dbg !54 } define internal fastcc void @foo(%Foo* nonnull sret) unnamed_addr #2 !dbg !55 { Entry: %1 = bitcast %Foo* %0 to i8*, !dbg !60 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%Foo* @0 to i8*), i64 8, i1 false), !dbg !60 ret void, !dbg !60 } ```
1 parent 9a60a65 commit c7c3cfc

File tree

2 files changed

+54
-26
lines changed

2 files changed

+54
-26
lines changed

src/ir.cpp

+52-25
Original file line numberDiff line numberDiff line change
@@ -1211,16 +1211,12 @@ static IrInstruction *ir_build_call(IrBuilder *irb, Scope *scope, AstNode *sourc
12111211
call_instruction->new_stack = new_stack;
12121212
call_instruction->result_loc = result_loc;
12131213

1214-
if (fn_ref)
1215-
ir_ref_instruction(fn_ref, irb->current_basic_block);
1214+
if (fn_ref) ir_ref_instruction(fn_ref, irb->current_basic_block);
12161215
for (size_t i = 0; i < arg_count; i += 1)
12171216
ir_ref_instruction(args[i], irb->current_basic_block);
1218-
if (async_allocator)
1219-
ir_ref_instruction(async_allocator, irb->current_basic_block);
1220-
if (new_stack != nullptr)
1221-
ir_ref_instruction(new_stack, irb->current_basic_block);
1222-
1223-
ir_ref_instruction(result_loc, irb->current_basic_block);
1217+
if (async_allocator != nullptr) ir_ref_instruction(async_allocator, irb->current_basic_block);
1218+
if (new_stack != nullptr) ir_ref_instruction(new_stack, irb->current_basic_block);
1219+
if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
12241220

12251221
return &call_instruction->base;
12261222
}
@@ -13108,6 +13104,26 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
1310813104
return var_ptr_instruction;
1310913105
}
1311013106

13107+
static Error resolve_alloca_inference(IrAnalyze *ira, IrInstructionAllocaGen *alloca, ZigType *child_type) {
13108+
Error err;
13109+
if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown)))
13110+
return err;
13111+
alloca->base.value.type = get_pointer_to_type_extra(ira->codegen, child_type, false, false,
13112+
PtrLenSingle, alloca->align, 0, 0);
13113+
return ErrorNone;
13114+
}
13115+
13116+
static Error resolve_possible_alloca_inference(IrAnalyze *ira, IrInstruction *base, ZigType *child_type) {
13117+
Error err;
13118+
assert(base->value.type->id == ZigTypeIdPointer);
13119+
ZigType *infer_child = base->value.type->data.pointer.child_type;
13120+
if (base->id == IrInstructionIdAllocaGen && infer_child == ira->codegen->builtin_types.entry_infer) {
13121+
if ((err = resolve_alloca_inference(ira, reinterpret_cast<IrInstructionAllocaGen *>(base), child_type)))
13122+
return err;
13123+
}
13124+
return ErrorNone;
13125+
}
13126+
1311113127
static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction,
1311213128
ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
1311313129
IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
@@ -13650,10 +13666,20 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
1365013666
return ira->codegen->invalid_instruction;
1365113667
}
1365213668

13669+
IrInstruction *result_loc = nullptr;
13670+
13671+
if (handle_is_ptr(return_type)) {
13672+
result_loc = call_instruction->result_loc->child;
13673+
if (type_is_invalid(result_loc->value.type))
13674+
return ira->codegen->invalid_instruction;
13675+
if ((err = resolve_possible_alloca_inference(ira, result_loc, return_type)))
13676+
return ira->codegen->invalid_instruction;
13677+
}
13678+
1365313679
IrInstruction *new_call_instruction = ir_build_call(&ira->new_irb,
1365413680
call_instruction->base.scope, call_instruction->base.source_node,
1365513681
fn_entry, fn_ref, call_param_count, casted_args, false, fn_inline, false, nullptr,
13656-
casted_new_stack, nullptr);
13682+
casted_new_stack, result_loc);
1365713683
new_call_instruction->value.type = return_type;
1365813684
return ir_finish_anal(ira, new_call_instruction);
1365913685
}
@@ -15168,20 +15194,9 @@ static IrInstruction *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstruc
1516815194
return ir_analyze_store_ptr(ira, &instruction->base, ptr, value);
1516915195
}
1517015196

15171-
static void resolve_alloca_inference(IrAnalyze *ira, IrInstructionAllocaGen *alloca, ZigType *child_type) {
15172-
alloca->base.value.type = get_pointer_to_type_extra(ira->codegen, child_type, false, false,
15173-
PtrLenSingle, alloca->align, 0, 0);
15174-
}
15175-
15176-
static void resolve_possible_alloca_inference(IrAnalyze *ira, IrInstruction *base, ZigType *child_type) {
15177-
assert(base->value.type->id == ZigTypeIdPointer);
15178-
ZigType *infer_child = base->value.type->data.pointer.child_type;
15179-
if (base->id == IrInstructionIdAllocaGen && infer_child == ira->codegen->builtin_types.entry_infer) {
15180-
resolve_alloca_inference(ira, reinterpret_cast<IrInstructionAllocaGen *>(base), child_type);
15181-
}
15182-
}
15183-
1518415197
static IrInstruction *ir_analyze_instruction_store_result(IrAnalyze *ira, IrInstructionStoreResult *instruction) {
15198+
Error err;
15199+
1518515200
IrInstruction *value = instruction->value->child;
1518615201
if (type_is_invalid(value->value.type))
1518715202
return ira->codegen->invalid_instruction;
@@ -15190,7 +15205,8 @@ static IrInstruction *ir_analyze_instruction_store_result(IrAnalyze *ira, IrInst
1519015205
if (type_is_invalid(result_loc->value.type))
1519115206
return ira->codegen->invalid_instruction;
1519215207

15193-
resolve_possible_alloca_inference(ira, result_loc, value->value.type);
15208+
if ((err = resolve_possible_alloca_inference(ira, result_loc, value->value.type)))
15209+
return ira->codegen->invalid_instruction;
1519415210

1519515211
// If the type is a scalar value, treat this instruction as a normal store pointer instruction.
1519615212
// Or if the value is comptime known, analyze it as a store pointer, so that the
@@ -20984,7 +21000,15 @@ static IrInstruction *ir_analyze_instruction_result_error_union_payload(IrAnalyz
2098421000
}
2098521001

2098621002
static IrInstruction *ir_analyze_instruction_result_return(IrAnalyze *ira, IrInstructionResultReturn *instruction) {
20987-
zig_panic("TODO");
21003+
ZigFn *fn = exec_fn_entry(ira->new_irb.exec);
21004+
if (fn == nullptr) {
21005+
ir_add_error(ira, &instruction->base, buf_sprintf("return outside function"));
21006+
return ira->codegen->invalid_instruction;
21007+
}
21008+
ZigType *result_type = get_pointer_to_type(ira->codegen, fn->type_entry->data.fn.fn_type_id.return_type, false);
21009+
IrInstruction *result = ir_build_result_return(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
21010+
result->value.type = result_type;
21011+
return result;
2098821012
}
2098921013

2099021014
static IrInstruction *ir_analyze_instruction_result_param(IrAnalyze *ira, IrInstructionResultParam *instruction) {
@@ -20996,6 +21020,8 @@ static IrInstruction *ir_analyze_instruction_result_ptr_cast(IrAnalyze *ira, IrI
2099621020
}
2099721021

2099821022
static IrInstruction *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructionAllocaSrc *instruction) {
21023+
Error err;
21024+
2099921025
uint32_t align = 0;
2100021026
if (instruction->align != nullptr) {
2100121027
if (!ir_resolve_align(ira, instruction->align->child, &align)) {
@@ -21015,7 +21041,8 @@ static IrInstruction *ir_analyze_instruction_alloca(IrAnalyze *ira, IrInstructio
2101521041
if (type_is_invalid(child_type))
2101621042
return ira->codegen->invalid_instruction;
2101721043

21018-
resolve_alloca_inference(ira, result, child_type);
21044+
if ((err = resolve_alloca_inference(ira, result, child_type)))
21045+
return ira->codegen->invalid_instruction;
2101921046
}
2102021047

2102121048
ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);

src/ir_print.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,8 @@ static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
225225
fprintf(irp->f, ", ");
226226
ir_print_other_instruction(irp, arg);
227227
}
228-
fprintf(irp->f, ")");
228+
fprintf(irp->f, ") result=");
229+
ir_print_other_instruction(irp, call_instruction->result_loc);
229230
}
230231

231232
static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {

0 commit comments

Comments
 (0)