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.
This commit is contained in:
parent
c4f96ea745
commit
dd1338b0e6
@ -3218,7 +3218,8 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
|
|||||||
assert(var->value->type == init_value->value.type);
|
assert(var->value->type == init_value->value.type);
|
||||||
ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
ZigType *var_ptr_type = get_pointer_to_type_extra(g, var->value->type, false, false,
|
||||||
PtrLenSingle, var->align_bytes, 0, 0);
|
PtrLenSingle, var->align_bytes, 0, 0);
|
||||||
gen_assign_raw(g, var->value_ref, var_ptr_type, ir_llvm_value(g, init_value));
|
LLVMValueRef llvm_init_val = ir_llvm_value(g, init_value);
|
||||||
|
gen_assign_raw(g, var->value_ref, var_ptr_type, llvm_init_val);
|
||||||
} else {
|
} else {
|
||||||
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
bool want_safe = ir_want_runtime_safety(g, &decl_var_instruction->base);
|
||||||
if (want_safe) {
|
if (want_safe) {
|
||||||
@ -5863,12 +5864,20 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||||||
LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
|
LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref,
|
||||||
&const_val->data.x_union.tag);
|
&const_val->data.x_union.tag);
|
||||||
|
|
||||||
LLVMValueRef fields[2];
|
LLVMValueRef fields[3];
|
||||||
fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
|
fields[type_entry->data.unionation.gen_union_index] = union_value_ref;
|
||||||
fields[type_entry->data.unionation.gen_tag_index] = tag_value;
|
fields[type_entry->data.unionation.gen_tag_index] = tag_value;
|
||||||
|
|
||||||
if (make_unnamed_struct) {
|
if (make_unnamed_struct) {
|
||||||
return LLVMConstStruct(fields, 2, false);
|
LLVMValueRef result = LLVMConstStruct(fields, 2, false);
|
||||||
|
size_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||||
|
size_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
|
||||||
|
if (actual_sz < expected_sz) {
|
||||||
|
unsigned pad_sz = expected_sz - actual_sz;
|
||||||
|
fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
|
||||||
|
result = LLVMConstStruct(fields, 3, false);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
|
return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ comptime {
|
|||||||
_ = @import("cases/bool.zig");
|
_ = @import("cases/bool.zig");
|
||||||
_ = @import("cases/bugs/1111.zig");
|
_ = @import("cases/bugs/1111.zig");
|
||||||
_ = @import("cases/bugs/1277.zig");
|
_ = @import("cases/bugs/1277.zig");
|
||||||
|
_ = @import("cases/bugs/1381.zig");
|
||||||
_ = @import("cases/bugs/1421.zig");
|
_ = @import("cases/bugs/1421.zig");
|
||||||
_ = @import("cases/bugs/394.zig");
|
_ = @import("cases/bugs/394.zig");
|
||||||
_ = @import("cases/bugs/655.zig");
|
_ = @import("cases/bugs/655.zig");
|
||||||
|
21
test/cases/bugs/1381.zig
Normal file
21
test/cases/bugs/1381.zig
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const B = union(enum) {
|
||||||
|
D: u8,
|
||||||
|
E: u16,
|
||||||
|
};
|
||||||
|
|
||||||
|
const A = union(enum) {
|
||||||
|
B: B,
|
||||||
|
C: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
test "union that needs padding bytes inside an array" {
|
||||||
|
var as = []A{
|
||||||
|
A{ .B = B{ .D = 1 } },
|
||||||
|
A{ .B = B{ .D = 1 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
const a = as[0].B;
|
||||||
|
std.debug.assertOrPanic(a.D == 1);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user