Commit 786677f80c

Andrew Kelley <superjoe30@gmail.com>
2017-02-22 06:54:11
fix regression with bit fields that align properly
1 parent d794549
Changed files (2)
src
test
src/codegen.cpp
@@ -1473,19 +1473,20 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
         if (canon_child_type->id == TypeTableEntryIdStruct &&
             canon_child_type->data.structure.layout == ContainerLayoutPacked)
         {
-            LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
-            LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
             size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
-            assert(unaligned_bit_count != 0);
-            assert(unaligned_bit_count % 8 == 0);
-            LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
-                    unaligned_bit_count / 8, false);
-            LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
-            LLVMValueRef indices[] = {
-                byte_offset
-            };
-            LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
-            return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
+            if (unaligned_bit_count != 0) {
+                LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
+                LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
+                assert(unaligned_bit_count % 8 == 0);
+                LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
+                        unaligned_bit_count / 8, false);
+                LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
+                LLVMValueRef indices[] = {
+                    byte_offset
+                };
+                LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
+                return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
+            }
         }
         LLVMValueRef indices[] = {
             LLVMConstNull(g->builtin_types.entry_usize->type_ref),
test/cases/struct.zig
@@ -369,3 +369,29 @@ fn packedArray24Bits() {
 
     assert(bytes[bytes.len - 1] == 0xaa);
 }
+
+const FooStructAligned = packed struct {
+    a: u8,
+    b: u8,
+};
+
+const FooArrayOfAligned = packed struct {
+    a: [2]FooStructAligned,
+};
+
+fn alignedArrayOfPackedStruct() {
+    @setFnTest(this);
+
+    comptime {
+        assert(@sizeOf(FooStructAligned) == 2);
+        assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
+    }
+
+    var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
+    const ptr = &([]FooArrayOfAligned)(bytes[0...bytes.len])[0];
+
+    assert(ptr.a[0].a == 0xbb);
+    assert(ptr.a[0].b == 0xbb);
+    assert(ptr.a[1].a == 0xbb);
+    assert(ptr.a[1].b == 0xbb);
+}