authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-11 12:57:53-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-11 12:59:39-04:00
logdd1338b0e6280b10b9b62ca73bf9ece34bd8524e
treee9745fe1b7a469cf8859b820c7a73715d76832d1
parentc4f96ea745ae2aa56ec5cb2c871e5b3d86b04c8f
signature Commit is signed but in an unrecognized format.

fix incorrect union const value generation

closes #1381 The union was generated as a 3 byte struct when it needed to be 4 bytes so that the packed struct bitcast could work correctly. Now it recognizes this situation and adds padding bytes to become the correct size so that it can fit into an array.

3 files changed, 34 insertions(+), 3 deletions(-)

src/codegen.cpp+12-3
......@@ -3218,7 +3218,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
32183218 assert(var->value->type == init_value->value.type);
32193219 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
32203220 PtrLenSingle, var->align_bytes, 0, 0);
3221 gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value));
3221 LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
3222 gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
32223223 } else {
32233224 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
32243225 if (want_safe) {
......@@ -5863,12 +5864,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58635864 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
58645865 &const_val->data.x_union.tag);
58655866
5866 LLVMValueRef fields[2];
5867 LLVMValueRef fields[3];
58675868 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
58685869 fields[type_entry->data.unionation.gen_tag_index] = tag_value;
58695870
58705871 if (make_unnamed_struct) {
5871 return LLVMConstStruct(fields, 2, false);
5872 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
5873 size_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
5874 size_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
5875 if (actual_sz < expected_sz) {
5876 unsigned pad_sz = expected_sz - actual_sz;
5877 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
5878 result = LLVMConstStruct(fields, 3, false);
5879 }
5880 return result;
58725881 } else {
58735882 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
58745883 }
test/behavior.zig+1
......@@ -10,6 +10,7 @@ comptime {
1010 _ = @import("cases/bool.zig");
1111 _ = @import("cases/bugs/1111.zig");
1212 _ = @import("cases/bugs/1277.zig");
13 _ = @import("cases/bugs/1381.zig");
1314 _ = @import("cases/bugs/1421.zig");
1415 _ = @import("cases/bugs/394.zig");
1516 _ = @import("cases/bugs/655.zig");
test/cases/bugs/1381.zig created+21
......@@ -0,0 +1,21 @@
1const std = @import("std");
2
3const B = union(enum) {
4 D: u8,
5 E: u16,
6};
7
8const A = union(enum) {
9 B: B,
10 C: u8,
11};
12
13test "union that needs padding bytes inside an array" {
14 var as = []A{
15 A{ .B = B{ .D = 1 } },
16 A{ .B = B{ .D = 1 } },
17 };
18
19 const a = as[0].B;
20 std.debug.assertOrPanic(a.D == 1);
21}