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
master
Andrew Kelley 2017-12-24 04:10:26 -05:00
parent 86397a532e
commit 2a25398c86
3 changed files with 35 additions and 8 deletions

View File

@ -3705,12 +3705,24 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar
ConstParent *parent = &array_const_val->data.x_array.s_none.parent;
LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent);
TypeTableEntry *usize = g->builtin_types.entry_usize;
LLVMValueRef indices[] = {
LLVMConstNull(usize->type_ref),
LLVMConstInt(usize->type_ref, index, false),
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr)));
if (el_type == LLVMArrayTypeKind) {
TypeTableEntry *usize = g->builtin_types.entry_usize;
LLVMValueRef indices[] = {
LLVMConstNull(usize->type_ref),
LLVMConstInt(usize->type_ref, index, false),
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
} else if (el_type == LLVMStructTypeKind) {
TypeTableEntry *u32 = g->builtin_types.entry_u32;
LLVMValueRef indices[] = {
LLVMConstNull(u32->type_ref),
LLVMConstInt(u32->type_ref, index, false),
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
} else {
zig_unreachable();
}
}
static 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
TypeTableEntry *u32 = g->builtin_types.entry_u32;
LLVMValueRef indices[] = {
LLVMConstNull(u32->type_ref),
LLVMConstInt(u32->type_ref, 0, false),
LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload
};
return LLVMConstInBoundsGEP(base_ptr, indices, 2);
}

View File

@ -8,7 +8,7 @@ const DW = std.dwarf;
const ArrayList = std.ArrayList;
const builtin = @import("builtin");
pub use @import("./failing_allocator.zig");
pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator;
error MissingDebugInfo;
error InvalidDebugInfo;

View File

@ -220,3 +220,18 @@ fn assertIsTheUnion2Item1(value: &const TheUnion2) {
assert(*value == TheUnion2.Item1);
}
pub const PackThis = union(enum) {
Invalid: bool,
StringLiteral: u2,
};
test "constant packed union" {
testConstPackedUnion([]PackThis {
PackThis { .StringLiteral = 1 },
});
}
fn testConstPackedUnion(expected_tokens: []const PackThis) {
assert(expected_tokens[0].StringLiteral == 1);
}