authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-24 04:10:26-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-24 04:11:58-05:00
log2a25398c869fcdefe8b6508974a5c463ca833520
treecab802b768a4b2559a234c2a29c301435678bac3
parent86397a532ec3c6699c39c8eeb966cd56b66c6c96

fix segfault when passing union enum with sub byte...

...field to const slice parameter we use a packed struct internally to represent a const array of disparate union values, and needed to update the internal getelementptr instruction to recognize that. closes #664

3 files changed, 35 insertions(+), 8 deletions(-)

src/codegen.cpp+19-7
......@@ -3705,12 +3705,24 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
37053705 ConstParent *parent = &array_const_val->data.x_array.s_none.parent;
37063706 LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
37073707
3708 TypeTableEntry *usize = g->builtin_types.entry_usize;
3709 LLVMValueRef indices[] = {
3710 LLVMConstNull(usize->type_ref),
3711 LLVMConstInt(usize->type_ref, index, false),
3712 };
3713 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
3708 LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
3709 if (el_type == LLVMArrayTypeKind) {
3710 TypeTableEntry *usize = g->builtin_types.entry_usize;
3711 LLVMValueRef indices[] = {
3712 LLVMConstNull(usize->type_ref),
3713 LLVMConstInt(usize->type_ref, index, false),
3714 };
3715 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
3716 } else if (el_type == LLVMStructTypeKind) {
3717 TypeTableEntry *u32 = g->builtin_types.entry_u32;
3718 LLVMValueRef indices[] = {
3719 LLVMConstNull(u32->type_ref),
3720 LLVMConstInt(u32->type_ref, index, false),
3721 };
3722 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
3723 } else {
3724 zig_unreachable();
3725 }
37143726}
37153727
37163728static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *struct_const_val, size_t field_index) {
......@@ -3732,7 +3744,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un
37323744 TypeTableEntry *u32 = g->builtin_types.entry_u32;
37333745 LLVMValueRef indices[] = {
37343746 LLVMConstNull(u32->type_ref),
3735 LLVMConstInt(u32->type_ref, 0, false),
3747 LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload
37363748 };
37373749 return LLVMConstInBoundsGEP(base_ptr, indices, 2);
37383750}
std/debug/index.zig+1-1
......@@ -8,7 +8,7 @@ const DW = std.dwarf;
88const ArrayList = std.ArrayList;
99const builtin = @import("builtin");
1010
11pub use @import("./failing_allocator.zig");
11pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
1212
1313error MissingDebugInfo;
1414error InvalidDebugInfo;
test/cases/union.zig+15
......@@ -220,3 +220,18 @@ fn assertIsTheUnion2Item1(value: &const TheUnion2) {
220220 assert(*value == TheUnion2.Item1);
221221}
222222
223
224pub const PackThis = union(enum) {
225 Invalid: bool,
226 StringLiteral: u2,
227};
228
229test "constant packed union" {
230 testConstPackedUnion([]PackThis {
231 PackThis { .StringLiteral = 1 },
232 });
233}
234
235fn testConstPackedUnion(expected_tokens: []const PackThis) {
236 assert(expected_tokens[0].StringLiteral == 1);
237}