mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
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> llvm-svn: 183544
This commit is contained in:
parent
a9cbca5c30
commit
a8970e620f
@ -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,
|
||||
|
18
test/CodeGen/ARM/emit-big-cst.ll
Normal file
18
test/CodeGen/ARM/emit-big-cst.ll
Normal 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
|
||||
}
|
17
test/CodeGen/Mips/emit-big-cst.ll
Normal file
17
test/CodeGen/Mips/emit-big-cst.ll
Normal 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
|
||||
}
|
17
test/CodeGen/X86/emit-big-cst.ll
Normal file
17
test/CodeGen/X86/emit-big-cst.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user