aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-11-16 22:06:08 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-11-16 22:06:08 -0500
commit5d2ba056c801f46a07182a05c07887e06fd197fa (patch)
treee05d1de9c4d201ee4ed3787facb189b1f7baeb7e /src/codegen.cpp
parente26ccd5166000f81a589c446d04102c21045bff6 (diff)
downloadzig-5d2ba056c801f46a07182a05c07887e06fd197fa.tar.gz
zig-5d2ba056c801f46a07182a05c07887e06fd197fa.zip
fix codegen for union init with runtime value
see #144
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp27
1 files changed, 22 insertions, 5 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index eb56d26cae..680f5a9e35 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -3414,17 +3414,34 @@ static LLVMValueRef ir_render_struct_init(CodeGen *g, IrExecutable *executable,
static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, IrInstructionUnionInit *instruction) {
TypeUnionField *type_union_field = instruction->field;
- assert(type_has_bits(type_union_field->type_entry));
-
- LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
- LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
+ if (!type_has_bits(type_union_field->type_entry))
+ return nullptr;
uint32_t field_align_bytes = get_abi_alignment(g, type_union_field->type_entry);
-
TypeTableEntry *ptr_type = get_pointer_to_type_extra(g, type_union_field->type_entry,
false, false, field_align_bytes,
0, 0);
+ LLVMValueRef uncasted_union_ptr;
+ // Even if safety is off in this block, if the union type has the safety field, we have to populate it
+ // correctly. Otherwise safety code somewhere other than here could fail.
+ TypeTableEntry *union_type = instruction->union_type;
+ if (union_type->data.unionation.gen_tag_index != SIZE_MAX) {
+ LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ union_type->data.unionation.gen_tag_index, "");
+ LLVMValueRef tag_value = LLVMConstInt(union_type->data.unionation.tag_type->type_ref,
+ type_union_field->value, false);
+ gen_store_untyped(g, tag_value, tag_field_ptr, 0, false);
+
+ uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ (unsigned)union_type->data.unionation.gen_union_index, "");
+ } else {
+ uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, "");
+ }
+
+ LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, ptr_type->type_ref, "");
+ LLVMValueRef value = ir_llvm_value(g, instruction->init_value);
+
gen_assign_raw(g, field_ptr, ptr_type, value);
return instruction->tmp_ptr;