Skip to content

Commit 7608505

Browse files
committed
copy elision: implicit cast payload to error union
```zig export fn entry() void { var x: error!Foo = foo(); } ``` ```llvm define void @entry() #2 !dbg !41 { Entry: %x = alloca { i16, %Foo }, align 4 %0 = getelementptr inbounds { i16, %Foo }, { i16, %Foo }* %x, i32 0, i32 0, !dbg !56 store i16 0, i16* %0, align 2, !dbg !56 %1 = getelementptr inbounds { i16, %Foo }, { i16, %Foo }* %x, i32 0, i32 1, !dbg !56 call fastcc void @foo(%Foo* sret %1), !dbg !57 call void @llvm.dbg.declare(metadata { i16, %Foo }* %x, metadata !45, metadata !DIExpression()), !dbg !56 ret void, !dbg !58 } ```
1 parent d0dcfea commit 7608505

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

src/codegen.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -5108,6 +5108,16 @@ static LLVMValueRef ir_render_result_optional_payload(CodeGen *g, IrExecutable *
51085108
return LLVMBuildStructGEP(g->builder, prev_result_loc, maybe_child_index, "");
51095109
}
51105110

5111+
static LLVMValueRef ir_render_result_error_union_payload(CodeGen *g, IrExecutable *executable,
5112+
IrInstructionResultErrorUnionPayload *instruction)
5113+
{
5114+
LLVMValueRef prev_result_loc = ir_llvm_value(g, instruction->prev_result_loc);
5115+
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, prev_result_loc, err_union_err_index, "");
5116+
LLVMTypeRef err_type_ref = g->builtin_types.entry_global_error_set->type_ref;
5117+
gen_store_untyped(g, LLVMConstInt(err_type_ref, 0, false), err_val_ptr, 0, false);
5118+
return LLVMBuildStructGEP(g->builder, prev_result_loc, err_union_payload_index, "");
5119+
}
5120+
51115121
static LLVMValueRef ir_render_assert_non_error(CodeGen *g, IrExecutable *executable,
51125122
IrInstructionAssertNonError *instruction)
51135123
{
@@ -5371,10 +5381,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53715381
return ir_render_result_return(g, executable, (IrInstructionResultReturn *)instruction);
53725382
case IrInstructionIdResultOptionalPayload:
53735383
return ir_render_result_optional_payload(g, executable, (IrInstructionResultOptionalPayload *)instruction);
5384+
case IrInstructionIdResultErrorUnionPayload:
5385+
return ir_render_result_error_union_payload(g, executable, (IrInstructionResultErrorUnionPayload *)instruction);
53745386
case IrInstructionIdAssertNonError:
53755387
return ir_render_assert_non_error(g, executable, (IrInstructionAssertNonError *)instruction);
5376-
case IrInstructionIdResultErrorUnionPayload:
5377-
zig_panic("TODO");
53785388
case IrInstructionIdResultSliceToBytes:
53795389
zig_panic("TODO");
53805390
case IrInstructionIdResultBytesToSlice:

src/ir.cpp

+39-5
Original file line numberDiff line numberDiff line change
@@ -2805,6 +2805,17 @@ static IrInstruction *ir_build_result_optional_payload(IrBuilder *irb, Scope *sc
28052805
return &instruction->base;
28062806
}
28072807

2808+
static IrInstruction *ir_build_result_error_union_payload(IrBuilder *irb, Scope *scope, AstNode *source_node,
2809+
IrInstruction *prev_result_loc)
2810+
{
2811+
IrInstructionResultErrorUnionPayload *instruction = ir_build_instruction<IrInstructionResultErrorUnionPayload>(irb, scope, source_node);
2812+
instruction->prev_result_loc = prev_result_loc;
2813+
2814+
ir_ref_instruction(prev_result_loc, irb->current_basic_block);
2815+
2816+
return &instruction->base;
2817+
}
2818+
28082819
static IrInstruction *ir_build_result_return(IrBuilder *irb, Scope *scope, AstNode *source_node) {
28092820
IrInstructionResultReturn *instruction = ir_build_instruction<IrInstructionResultReturn>(irb, scope, source_node);
28102821
return &instruction->base;
@@ -9812,17 +9823,31 @@ static IrInstruction *ir_analyze_result_optional_payload(IrAnalyze *ira, IrInstr
98129823
ZigType *old_ptr_type = result_loc->value.type;
98139824
assert(old_ptr_type->id == ZigTypeIdPointer);
98149825
ZigType *new_ptr_type = get_pointer_to_type_extra(ira->codegen, needed_child_type,
9815-
old_ptr_type->data.pointer.is_const,
9816-
old_ptr_type->data.pointer.is_volatile,
9817-
old_ptr_type->data.pointer.ptr_len,
9818-
0, 0, 0);
9826+
false, old_ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
98199827

98209828
IrInstruction *result = ir_build_result_optional_payload(&ira->new_irb, result_loc->scope,
98219829
result_loc->source_node, result_loc);
98229830
result->value.type = new_ptr_type;
98239831
return result;
98249832
}
98259833

9834+
static IrInstruction *ir_analyze_result_error_union_payload(IrAnalyze *ira, IrInstruction *result_loc,
9835+
ZigType *needed_child_type)
9836+
{
9837+
if (instr_is_comptime(result_loc)) {
9838+
zig_panic("TODO comptime ir_analyze_result_error_union_payload");
9839+
}
9840+
ZigType *old_ptr_type = result_loc->value.type;
9841+
assert(old_ptr_type->id == ZigTypeIdPointer);
9842+
ZigType *new_ptr_type = get_pointer_to_type_extra(ira->codegen, needed_child_type,
9843+
false, old_ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0);
9844+
9845+
IrInstruction *result = ir_build_result_error_union_payload(&ira->new_irb, result_loc->scope,
9846+
result_loc->source_node, result_loc);
9847+
result->value.type = new_ptr_type;
9848+
return result;
9849+
}
9850+
98269851
static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
98279852
ZigType *wanted_type)
98289853
{
@@ -10787,7 +10812,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1078710812
return ir_analyze_null_to_maybe(ira, source_instr, value, wanted_type);
1078810813
}
1078910814

10790-
// cast from child type of error type to error type
10815+
// cast from T to E!T
1079110816
if (wanted_type->id == ZigTypeIdErrorUnion) {
1079210817
if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
1079310818
source_node, false).id == ConstCastResultIdOk)
@@ -11127,6 +11152,15 @@ static IrInstruction *ir_implicit_cast_result(IrAnalyze *ira, IrInstruction *res
1112711152
}
1112811153
}
1112911154

11155+
// cast from T to E!T
11156+
if (have_child_type->id == ZigTypeIdErrorUnion) {
11157+
if (types_match_const_cast_only(ira, have_child_type->data.error_union.payload_type, needed_child_type,
11158+
source_node, false).id == ConstCastResultIdOk)
11159+
{
11160+
return ir_analyze_result_error_union_payload(ira, result_loc, needed_child_type);
11161+
}
11162+
}
11163+
1113011164
ErrorMsg *parent_msg = ir_add_error_node(ira, source_node,
1113111165
buf_sprintf("expected type '%s', found '%s'",
1113211166
buf_ptr(&have_child_type->name),

src/ir_print.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1332,7 +1332,9 @@ static void ir_print_result_optional_payload(IrPrint *irp, IrInstructionResultOp
13321332
}
13331333

13341334
static void ir_print_result_error_union_payload(IrPrint *irp, IrInstructionResultErrorUnionPayload *instruction) {
1335-
fprintf(irp->f, "ResultErrorUnionPayload");
1335+
fprintf(irp->f, "ResultErrorUnionPayload(");
1336+
ir_print_other_instruction(irp, instruction->prev_result_loc);
1337+
fprintf(irp->f, ")");
13361338
}
13371339

13381340
static void ir_print_result_return(IrPrint *irp, IrInstructionResultReturn *instruction) {

0 commit comments

Comments
 (0)