Teach AsmPrinter how to print odd constants.

Fix an assertion when the compiler encounters big constants whose bit width is
not a multiple of 64-bits.
Although clang would never generate something like this, the backend should be
able to handle any legal IR.

<rdar://problem/13363576>


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183544 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Quentin Colombet 2013-06-07 18:36:03 +00:00
parent 576d49a775
commit fcca6c690c
4 changed files with 95 additions and 2 deletions

View File

@ -1795,16 +1795,57 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI,
unsigned AddrSpace, AsmPrinter &AP) {
const DataLayout *TD = AP.TM.getDataLayout();
unsigned BitWidth = CI->getBitWidth();
assert((BitWidth & 63) == 0 && "only support multiples of 64-bits");
// Copy the value as we may massage the layout for constants whose bit width
// is not a multiple of 64-bits.
APInt Realigned(CI->getValue());
uint64_t ExtraBits = 0;
unsigned ExtraBitsSize = BitWidth & 63;
if (ExtraBitsSize) {
// The bit width of the data is not a multiple of 64-bits.
// The extra bits are expected to be at the end of the chunk of the memory.
// Little endian:
// * Nothing to be done, just record the extra bits to emit.
// Big endian:
// * Record the extra bits to emit.
// * Realign the raw data to emit the chunks of 64-bits.
if (TD->isBigEndian()) {
// Basically the structure of the raw data is a chunk of 64-bits cells:
// 0 1 BitWidth / 64
// [chunk1][chunk2] ... [chunkN].
// The most significant chunk is chunkN and it should be emitted first.
// However, due to the alignment issue chunkN contains useless bits.
// Realign the chunks so that they contain only useless information:
// ExtraBits 0 1 (BitWidth / 64) - 1
// chu[nk1 chu][nk2 chu] ... [nkN-1 chunkN]
ExtraBits = Realigned.getRawData()[0] &
(((uint64_t)-1) >> (64 - ExtraBitsSize));
Realigned = Realigned.lshr(ExtraBitsSize);
} else
ExtraBits = Realigned.getRawData()[BitWidth / 64];
}
// We don't expect assemblers to support integer data directives
// for more than 64 bits, so we emit the data in at most 64-bit
// quantities at a time.
const uint64_t *RawData = CI->getValue().getRawData();
const uint64_t *RawData = Realigned.getRawData();
for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
uint64_t Val = TD->isBigEndian() ? RawData[e - i - 1] : RawData[i];
AP.OutStreamer.EmitIntValue(Val, 8, AddrSpace);
}
if (ExtraBitsSize) {
// Emit the extra bits after the 64-bits chunks.
// Emit a directive that fills the expected size.
uint64_t Size = AP.TM.getDataLayout()->getTypeAllocSize(CI->getType());
Size -= (BitWidth / 64) * 8;
assert(Size && Size * 8 >= ExtraBitsSize &&
(ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize)))
== ExtraBits && "Directive too small for extra bits.");
AP.OutStreamer.EmitIntValue(ExtraBits, Size, AddrSpace);
}
}
static void emitGlobalConstantImpl(const Constant *CV, unsigned AddrSpace,

View File

@ -0,0 +1,18 @@
; RUN: llc -mtriple=thumbv7-unknown-unknown < %s | FileCheck %s
; Check assembly printing of odd constants.
; CHECK: bigCst:
; CHECK-NEXT: .long 1694510592
; CHECK-NEXT: .long 2960197
; CHECK-NEXT: .long 26220
; CHECK-NEXT: .size bigCst, 12
@bigCst = internal constant i82 483673642326615442599424
define void @accessBig(i64* %storage) {
%addr = bitcast i64* %storage to i82*
%bigLoadedCst = load volatile i82* @bigCst
%tmp = add i82 %bigLoadedCst, 1
store i82 %tmp, i82* %addr
ret void
}

View File

@ -0,0 +1,17 @@
; RUN: llc -march=mips < %s | FileCheck %s
; Check assembly printing of odd constants.
; CHECK: bigCst:
; CHECK-NEXT: .8byte 1845068520838224192
; CHECK-NEXT: .8byte 11776
; CHECK-NEXT: .size bigCst, 16
@bigCst = internal constant i82 483673642326615442599424
define void @accessBig(i64* %storage) {
%addr = bitcast i64* %storage to i82*
%bigLoadedCst = load volatile i82* @bigCst
%tmp = add i82 %bigLoadedCst, 1
store i82 %tmp, i82* %addr
ret void
}

View File

@ -0,0 +1,17 @@
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
; Check assembly printing of odd constants.
; CHECK: bigCst:
; CHECK-NEXT: .quad 12713950999227904
; CHECK-NEXT: .quad 26220
; CHECK-NEXT: .size bigCst, 16
@bigCst = internal constant i82 483673642326615442599424
define void @accessBig(i64* %storage) {
%addr = bitcast i64* %storage to i82*
%bigLoadedCst = load volatile i82* @bigCst
%tmp = add i82 %bigLoadedCst, 1
store i82 %tmp, i82* %addr
ret void
}