authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-22 00:54:11-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-22 00:58:31-05:00
log786677f80cf7fb34ad8ab45768b910296f9c34cf
treeff2b3a517fb53a80df27fe7230a52550b8927d64
parentd794549985fc9a3fd6d6b1620be15d290f6a759f

fix regression with bit fields that align properly


2 files changed, 39 insertions(+), 12 deletions(-)

src/codegen.cpp+13-12
......@@ -1473,19 +1473,20 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
14731473 if (canon_child_type->id == TypeTableEntryIdStruct &&
14741474 canon_child_type->data.structure.layout == ContainerLayoutPacked)
14751475 {
1476 LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
1477 LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
14781476 size_t unaligned_bit_count = instruction->base.value.type->data.pointer.unaligned_bit_count;
1479 assert(unaligned_bit_count != 0);
1480 assert(unaligned_bit_count % 8 == 0);
1481 LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1482 unaligned_bit_count / 8, false);
1483 LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
1484 LLVMValueRef indices[] = {
1485 byte_offset
1486 };
1487 LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
1488 return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
1477 if (unaligned_bit_count != 0) {
1478 LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0);
1479 LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, "");
1480 assert(unaligned_bit_count % 8 == 0);
1481 LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
1482 unaligned_bit_count / 8, false);
1483 LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, "");
1484 LLVMValueRef indices[] = {
1485 byte_offset
1486 };
1487 LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, "");
1488 return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(canon_child_type->type_ref, 0), "");
1489 }
14891490 }
14901491 LLVMValueRef indices[] = {
14911492 LLVMConstNull(g->builtin_types.entry_usize->type_ref),
test/cases/struct.zig+26
......@@ -369,3 +369,29 @@ fn packedArray24Bits() {
369369
370370 assert(bytes[bytes.len - 1] == 0xaa);
371371}
372
373const FooStructAligned = packed struct {
374 a: u8,
375 b: u8,
376};
377
378const FooArrayOfAligned = packed struct {
379 a: [2]FooStructAligned,
380};
381
382fn alignedArrayOfPackedStruct() {
383 @setFnTest(this);
384
385 comptime {
386 assert(@sizeOf(FooStructAligned) == 2);
387 assert(@sizeOf(FooArrayOfAligned) == 2 * 2);
388 }
389
390 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
391 const ptr = &([]FooArrayOfAligned)(bytes[0...bytes.len])[0];
392
393 assert(ptr.a[0].a == 0xbb);
394 assert(ptr.a[0].b == 0xbb);
395 assert(ptr.a[1].a == 0xbb);
396 assert(ptr.a[1].b == 0xbb);
397}