Skip to content

Commit d0dcfea

Browse files
committed
copy elision: if bool expression with aggregate
```zig export fn entry() void { var y = true; var z = bar(); var x = if (y) foo() else z; } ``` ```llvm define void @entry() #2 !dbg !41 { Entry: %y = alloca i1, align 1 %z = alloca %Foo, align 4 %x = alloca %Foo, align 4 store i1 true, i1* %y, align 1, !dbg !57 call void @llvm.dbg.declare(metadata i1* %y, metadata !45, metadata !DIExpression()), !dbg !58 call fastcc void @bar(%Foo* sret %z), !dbg !59 call void @llvm.dbg.declare(metadata %Foo* %z, metadata !48, metadata !DIExpression()), !dbg !60 %0 = load i1, i1* %y, align 1, !dbg !61 br i1 %0, label %Then, label %Else, !dbg !61 Then: ; preds = %Entry call fastcc void @foo(%Foo* sret %x), !dbg !62 br label %EndIf, !dbg !63 Else: ; preds = %Entry %1 = bitcast %Foo* %z to i8*, !dbg !64 %2 = bitcast %Foo* %x to i8*, !dbg !64 call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %2, i8* align 4 %1, i64 8, i1 false), !dbg !64 br label %EndIf, !dbg !63 EndIf: ; preds = %Else, %Then call void @llvm.dbg.declare(metadata %Foo* %x, metadata !55, metadata !DIExpression()), !dbg !65 ret void, !dbg !66 } ```
1 parent ff943d9 commit d0dcfea

File tree

4 files changed

+247
-173
lines changed

4 files changed

+247
-173
lines changed

Diff for: src/all_types.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -2184,6 +2184,7 @@ enum IrInstructionId {
21842184
IrInstructionIdStoreResult,
21852185
IrInstructionIdAllocaSrc,
21862186
IrInstructionIdAllocaGen,
2187+
IrInstructionIdAssertNonError,
21872188
};
21882189

21892190
struct IrInstruction {
@@ -2338,6 +2339,7 @@ struct IrInstructionLoadPtr {
23382339
IrInstruction base;
23392340

23402341
IrInstruction *ptr;
2342+
IrInstruction *result_loc;
23412343
};
23422344

23432345
struct IrInstructionStorePtr {
@@ -3011,6 +3013,8 @@ struct IrInstructionTypeName {
30113013
enum LVal {
30123014
LValNone,
30133015
LValPtr,
3016+
LValErrorUnion,
3017+
LValOptional,
30143018
};
30153019

30163020
struct IrInstructionDeclRef {
@@ -3346,6 +3350,12 @@ struct IrInstructionAllocaGen {
33463350
const char *name_hint;
33473351
};
33483352

3353+
struct IrInstructionAssertNonError {
3354+
IrInstruction base;
3355+
3356+
IrInstruction *err_code;
3357+
};
3358+
33493359
static const size_t slice_ptr_index = 0;
33503360
static const size_t slice_len_index = 1;
33513361

Diff for: src/codegen.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -5108,6 +5108,26 @@ 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_assert_non_error(CodeGen *g, IrExecutable *executable,
5112+
IrInstructionAssertNonError *instruction)
5113+
{
5114+
if (!ir_want_runtime_safety(g, &instruction->base) || g->errors_by_index.length <= 1) {
5115+
return nullptr;
5116+
}
5117+
LLVMValueRef err_val = ir_llvm_value(g, instruction->err_code);
5118+
LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
5119+
LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
5120+
LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError");
5121+
LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk");
5122+
LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
5123+
5124+
LLVMPositionBuilderAtEnd(g->builder, err_block);
5125+
gen_safety_crash_for_err(g, err_val, instruction->base.scope);
5126+
5127+
LLVMPositionBuilderAtEnd(g->builder, ok_block);
5128+
return nullptr;
5129+
}
5130+
51115131
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
51125132
AstNode *source_node = instruction->source_node;
51135133
Scope *scope = instruction->scope;
@@ -5351,6 +5371,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
53515371
return ir_render_result_return(g, executable, (IrInstructionResultReturn *)instruction);
53525372
case IrInstructionIdResultOptionalPayload:
53535373
return ir_render_result_optional_payload(g, executable, (IrInstructionResultOptionalPayload *)instruction);
5374+
case IrInstructionIdAssertNonError:
5375+
return ir_render_assert_non_error(g, executable, (IrInstructionAssertNonError *)instruction);
53545376
case IrInstructionIdResultErrorUnionPayload:
53555377
zig_panic("TODO");
53565378
case IrInstructionIdResultSliceToBytes:

0 commit comments

Comments
 (0)