[llvm] r183544 - Teach AsmPrinter how to print odd constants.

Quentin Colombet qcolombet at apple.com
Fri Jun 7 11:36:03 PDT 2013


Author: qcolombet
Date: Fri Jun  7 13:36:03 2013
New Revision: 183544

URL: http://llvm.org/viewvc/llvm-project?rev=183544&view=rev
Log:
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>

Added:
    llvm/trunk/test/CodeGen/ARM/emit-big-cst.ll
    llvm/trunk/test/CodeGen/Mips/emit-big-cst.ll
    llvm/trunk/test/CodeGen/X86/emit-big-cst.ll
Modified:
    llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=183544&r1=183543&r2=183544&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Fri Jun  7 13:36:03 2013
@@ -1795,16 +1795,57 @@ static void emitGlobalConstantLargeInt(c
                                        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,

Added: llvm/trunk/test/CodeGen/ARM/emit-big-cst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/emit-big-cst.ll?rev=183544&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/emit-big-cst.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/emit-big-cst.ll Fri Jun  7 13:36:03 2013
@@ -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
+
+ at 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
+}

Added: llvm/trunk/test/CodeGen/Mips/emit-big-cst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/emit-big-cst.ll?rev=183544&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/emit-big-cst.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/emit-big-cst.ll Fri Jun  7 13:36:03 2013
@@ -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
+
+ at 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
+}

Added: llvm/trunk/test/CodeGen/X86/emit-big-cst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/emit-big-cst.ll?rev=183544&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/emit-big-cst.ll (added)
+++ llvm/trunk/test/CodeGen/X86/emit-big-cst.ll Fri Jun  7 13:36:03 2013
@@ -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
+
+ at 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
+}





More information about the llvm-commits mailing list