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
signaturelock-open 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,...@@ -3218,7 +3218,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
3218 assert(var->value->type == init_value->value.type);3218 assert(var->value->type == init_value->value.type);
3219 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,3219 ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
3220 PtrLenSingle, var->align_bytes, 0, 0);3220 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);
3222 } else {3223 } else {
3223 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);3224 bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
3224 if (want_safe) {3225 if (want_safe) {
...@@ -5863,12 +5864,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5863,12 +5864,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5863 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,5864 LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
5864 &const_val->data.x_union.tag);5865 &const_val->data.x_union.tag);
58655866
5866 LLVMValueRef fields[2];5867 LLVMValueRef fields[3];
5867 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;5868 fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
5868 fields[type_entry->data.unionation.gen_tag_index] = tag_value;5869 fields[type_entry->data.unionation.gen_tag_index] = tag_value;
58695870
5870 if (make_unnamed_struct) {5871 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;
5872 } else {5881 } else {
5873 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);5882 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
5874 }5883 }
test/behavior.zig+1
...@@ -10,6 +10,7 @@ comptime {...@@ -10,6 +10,7 @@ comptime {
10 _ = @import("cases/bool.zig");10 _ = @import("cases/bool.zig");
11 _ = @import("cases/bugs/1111.zig");11 _ = @import("cases/bugs/1111.zig");
12 _ = @import("cases/bugs/1277.zig");12 _ = @import("cases/bugs/1277.zig");
13 _ = @import("cases/bugs/1381.zig");
13 _ = @import("cases/bugs/1421.zig");14 _ = @import("cases/bugs/1421.zig");
14 _ = @import("cases/bugs/394.zig");15 _ = @import("cases/bugs/394.zig");
15 _ = @import("cases/bugs/655.zig");16 _ = @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}