Skip to content

Commit 1dfca20

Browse files
committed
copy elision: test case: initialize scalar undefined
```zig export fn entry() void { var x: i32 = undefined; } ``` ```llvm define void @entry() #2 !dbg !41 { Entry: %x = alloca i32, align 4 %0 = bitcast i32* %x to i8*, !dbg !48 call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 -86, i64 4, i1 false), !dbg !48 call void @llvm.dbg.declare(metadata i32* %x, metadata !45, metadata !DIExpression()), !dbg !48 ret void, !dbg !49 } ```
1 parent 3037be1 commit 1dfca20

File tree

1 file changed

+45
-5
lines changed

1 file changed

+45
-5
lines changed

src/codegen.cpp

+45-5
Original file line numberDiff line numberDiff line change
@@ -3218,14 +3218,54 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
32183218
return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
32193219
}
32203220

3221-
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
3222-
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3223-
LLVMValueRef value = ir_llvm_value(g, instruction->value);
3221+
static bool value_is_all_undef(ConstExprValue *const_val) {
3222+
switch (const_val->special) {
3223+
case ConstValSpecialRuntime:
3224+
return false;
3225+
case ConstValSpecialUndef:
3226+
return true;
3227+
case ConstValSpecialStatic:
3228+
if (const_val->type->id == ZigTypeIdStruct) {
3229+
for (size_t i = 0; i < const_val->type->data.structure.src_field_count; i += 1) {
3230+
if (!value_is_all_undef(&const_val->data.x_struct.fields[i]))
3231+
return false;
3232+
}
3233+
return true;
3234+
} else {
3235+
return false;
3236+
}
3237+
}
3238+
zig_unreachable();
3239+
}
3240+
3241+
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
3242+
ZigType *usize = g->builtin_types.entry_usize;
3243+
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
3244+
assert(size_bytes > 0);
3245+
assert(ptr_align_bytes > 0);
3246+
// memset uninitialized memory to 0xaa
3247+
LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0);
3248+
LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false);
3249+
LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, "");
3250+
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
3251+
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
3252+
}
32243253

3225-
assert(instruction->ptr->value.type->id == ZigTypeIdPointer);
3254+
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
32263255
ZigType *ptr_type = instruction->ptr->value.type;
3256+
assert(ptr_type->id == ZigTypeIdPointer);
3257+
3258+
bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3259+
if (have_init_expr) {
3260+
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
3261+
LLVMValueRef value = ir_llvm_value(g, instruction->value);
32273262

3228-
gen_assign_raw(g, ptr, ptr_type, value);
3263+
gen_assign_raw(g, ptr, ptr_type, value);
3264+
}
3265+
if (ir_want_runtime_safety(g, &instruction->base)) {
3266+
gen_undef_init(g, get_ptr_align(g, ptr_type), instruction->value->value.type,
3267+
ir_llvm_value(g, instruction->ptr));
3268+
}
32293269

32303270
return nullptr;
32313271
}

0 commit comments

Comments
 (0)