diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-11-15 22:52:47 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-11-15 22:52:47 -0500 |
| commit | 018cbff438cedc19d0ad18021619ec7ede997307 (patch) | |
| tree | e21110319947f172100bda3b62685d2857c1fcdb /src/codegen.cpp | |
| parent | f276fd0f3728bf1a43b185e3e2d33d593309cb2f (diff) | |
| download | zig-018cbff438cedc19d0ad18021619ec7ede997307.tar.gz zig-018cbff438cedc19d0ad18021619ec7ede997307.zip | |
unions have a secret field for the type
See #144
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 57 |
1 files changed, 41 insertions, 16 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index fc949f2ecd..26a2590e44 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2408,9 +2408,15 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0); - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, ""); - LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); + if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { + LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, ""); + LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); + return bitcasted_union_field_ptr; + } + + LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_union_index, ""); + LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); return bitcasted_union_field_ptr; } @@ -3955,7 +3961,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } case TypeTableEntryIdUnion: { - LLVMTypeRef union_type_ref = type_entry->type_ref; + LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref; ConstExprValue *payload_value = const_val->data.x_union.value; assert(payload_value != nullptr); @@ -3964,29 +3970,48 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { } uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref); - uint64_t pad_bytes = type_entry->data.unionation.size_bytes - field_type_bytes; - + uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes; LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value); - bool make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || payload_value->type != type_entry->data.unionation.most_aligned_union_member; - unsigned field_count; - LLVMValueRef fields[2]; - fields[0] = correctly_typed_value; - if (pad_bytes == 0) { - field_count = 1; - } else { + LLVMValueRef union_value_ref; + { + unsigned field_count; + LLVMValueRef fields[2]; fields[0] = correctly_typed_value; - fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)); - field_count = 2; + if (pad_bytes == 0) { + field_count = 1; + } else { + fields[0] = correctly_typed_value; + fields[1] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), (unsigned)pad_bytes)); + field_count = 2; + } + + if (make_unnamed_struct || type_entry->data.unionation.gen_tag_index != SIZE_MAX) { + union_value_ref = LLVMConstStruct(fields, field_count, false); + } else { + union_value_ref = LLVMConstNamedStruct(union_type_ref, fields, field_count); + } + } + + if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) { + return union_value_ref; } + size_t distinct_type_index = type_entry->data.unionation.distinct_types.get(const_val->data.x_union.value->type); + LLVMValueRef tag_value = LLVMConstInt(type_entry->data.unionation.tag_type->type_ref, distinct_type_index, false); + + LLVMValueRef fields[2]; + fields[type_entry->data.unionation.gen_union_index] = union_value_ref; + fields[type_entry->data.unionation.gen_tag_index] = tag_value; + if (make_unnamed_struct) { - return LLVMConstStruct(fields, field_count, false); + return LLVMConstStruct(fields, 2, false); } else { - return LLVMConstNamedStruct(type_entry->type_ref, fields, field_count); + return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); } + } case TypeTableEntryIdEnum: { |
