Skip to content

Commit 3b128b4

Browse files
committed
IRGen: fix the address alignment calculation of index_addr and tail_addr.
This was wrong if the alignment of the base operand was larger than the alignment of the element type. rdar://problem/28346274
1 parent 3bf6b60 commit 3b128b4

File tree

2 files changed

+54
-6
lines changed

2 files changed

+54
-6
lines changed

lib/IRGen/GenValueWitness.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,7 +1518,9 @@ Address TypeInfo::indexArray(IRGenFunction &IGF, Address base,
15181518
// do a byte-level GEP with the proper stride.
15191519
const FixedTypeInfo *fixedTI = dyn_cast<FixedTypeInfo>(this);
15201520

1521-
Address dest;
1521+
llvm::Value *destValue = nullptr;
1522+
Size stride(1);
1523+
15221524
// TODO: Arrays currently lower-bound the stride to 1.
15231525
if (!fixedTI
15241526
|| std::max(Size(1), fixedTI->getFixedStride()) != fixedTI->getFixedSize()) {
@@ -1528,15 +1530,21 @@ Address TypeInfo::indexArray(IRGenFunction &IGF, Address base,
15281530
if (size->getType() != index->getType())
15291531
size = IGF.Builder.CreateZExtOrTrunc(size, index->getType());
15301532
llvm::Value *distance = IGF.Builder.CreateNSWMul(index, size);
1531-
llvm::Value *destValue = IGF.Builder.CreateInBoundsGEP(byteAddr, distance);
1533+
destValue = IGF.Builder.CreateInBoundsGEP(byteAddr, distance);
15321534
destValue = IGF.Builder.CreateBitCast(destValue, base.getType());
1533-
return Address(destValue, base.getAlignment());
15341535
} else {
15351536
// We don't expose a non-inbounds GEP operation.
1536-
llvm::Value *destValue = IGF.Builder.CreateInBoundsGEP(base.getAddress(),
1537-
index);
1538-
return Address(destValue, base.getAlignment());
1537+
destValue = IGF.Builder.CreateInBoundsGEP(base.getAddress(), index);
1538+
stride = fixedTI->getFixedStride();
15391539
}
1540+
if (auto *IndexConst = dyn_cast<llvm::ConstantInt>(index)) {
1541+
// If we know the indexing value, we can get a better guess on the
1542+
// alignment.
1543+
// This even works if the stride is not known (and assumed to be 1).
1544+
stride *= IndexConst->getValue().getZExtValue();
1545+
}
1546+
Alignment Align = base.getAlignment().alignmentAtOffset(stride);
1547+
return Address(destValue, Align);
15401548
}
15411549

15421550
Address TypeInfo::roundUpToTypeAlignment(IRGenFunction &IGF, Address base,

test/IRGen/tail_alloc.sil

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,44 @@ bb0(%0 : $Builtin.RawPointer, %1 : $Int32):
160160
return %r : $()
161161
}
162162

163+
// sizeof(EmptyClass) = 16 bytes
164+
class EmptyClass {
165+
}
166+
167+
sil_vtable EmptyClass {}
168+
169+
// CHECK-LABEL: define{{( protected)?}} i8 @test_align_1_int8
170+
// CHECK: load i8, i8* %{{.*}}, align 1
171+
// CHECK: ret
172+
sil @test_align_1_int8 : $@convention(thin) (EmptyClass) -> Int8 {
173+
bb0(%0 : $EmptyClass):
174+
%a = ref_tail_addr %0 : $EmptyClass, $Int8
175+
%w = integer_literal $Builtin.Word, 1
176+
%i = index_addr %a : $*Int8, %w : $Builtin.Word
177+
%l = load %i : $*Int8
178+
return %l : $Int8
179+
}
180+
181+
// CHECK-LABEL: define{{( protected)?}} i8 @test_align_2_int8
182+
// CHECK: load i8, i8* %{{.*}}, align 2
183+
// CHECK: ret
184+
sil @test_align_2_int8 : $@convention(thin) (EmptyClass) -> Int8 {
185+
bb0(%0 : $EmptyClass):
186+
%a = ref_tail_addr %0 : $EmptyClass, $Int8
187+
%w = integer_literal $Builtin.Word, 2
188+
%i = index_addr %a : $*Int8, %w : $Builtin.Word
189+
%l = load %i : $*Int8
190+
return %l : $Int8
191+
}
192+
193+
// CHECK-LABEL: define{{( protected)?}} i32 @test_align_int32
194+
// CHECK: load i32, i32* %{{.*}}, align 4
195+
// CHECK: ret
196+
sil @test_align_int32 : $@convention(thin) (EmptyClass, Builtin.Word) -> Int32 {
197+
bb0(%0 : $EmptyClass, %1 : $Builtin.Word):
198+
%a = ref_tail_addr %0 : $EmptyClass, $Int32
199+
%i = index_addr %a : $*Int32, %1 : $Builtin.Word
200+
%l = load %i : $*Int32
201+
return %l : $Int32
202+
}
163203

0 commit comments

Comments
 (0)