Commit 2a25398c86

Andrew Kelley <superjoe30@gmail.com>
2017-12-24 10:10:26
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
1 parent 86397a5
Changed files (3)
src
std
debug
test
cases
src/codegen.cpp
@@ -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);
 }
std/debug/index.zig
@@ -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;
test/cases/union.zig
@@ -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);
+}