class MCSection;
class MCStreamer;
class MCSymbol;
+
+struct ConstantPoolEntry {
+ MCSymbol *Label;
+ const MCExpr *Value;
+ unsigned Size;
+};
+
// A class to keep track of assembler-generated constant pools that are use to
// implement the ldr-pseudo.
class ConstantPool {
- typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy;
+ typedef SmallVector<ConstantPoolEntry, 4> EntryVecTy;
EntryVecTy Entries;
public:
// Add a new entry to the constant pool in the next slot.
// \param Value is the new entry to put in the constant pool.
+ // \param Size is the size in bytes of the entry
//
// \returns a MCExpr that references the newly inserted value
- const MCExpr *addEntry(const MCExpr *Value, MCContext &Context);
+ const MCExpr *addEntry(const MCExpr *Value, MCContext &Context,
+ unsigned Size);
// Emit the contents of the constant pool using the provided streamer.
void emitEntries(MCStreamer &Streamer);
void emitAll(MCStreamer &Streamer);
void emitForCurrentSection(MCStreamer &Streamer);
- const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr);
+ const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr,
+ unsigned Size);
private:
ConstantPool *getConstantPool(const MCSection *Section);
/// Callback used to implement the ldr= pseudo.
/// Add a new entry to the constant pool for the current section and return an
/// MCExpr that can be used to refer to the constant pool location.
- const MCExpr *addConstantPoolEntry(const MCExpr *);
+ const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size);
/// Callback used to implemnt the .ltorg directive.
/// Emit contents of constant pool for the current section.
void ConstantPool::emitEntries(MCStreamer &Streamer) {
if (Entries.empty())
return;
- Streamer.EmitCodeAlignment(4); // align to 4-byte address
Streamer.EmitDataRegion(MCDR_DataRegion);
for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
I != E; ++I) {
- Streamer.EmitLabel(I->first);
- Streamer.EmitValue(I->second, 4);
+ Streamer.EmitCodeAlignment(I->Size); // align naturally
+ Streamer.EmitLabel(I->Label);
+ Streamer.EmitValue(I->Value, I->Size);
}
Streamer.EmitDataRegion(MCDR_DataRegionEnd);
Entries.clear();
}
-const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) {
+const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context,
+ unsigned Size) {
MCSymbol *CPEntryLabel = Context.CreateTempSymbol();
- Entries.push_back(std::make_pair(CPEntryLabel, Value));
+ Entries.push_back( { CPEntryLabel, Value, Size } );
return MCSymbolRefExpr::Create(CPEntryLabel, Context);
}
}
const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
- const MCExpr *Expr) {
+ const MCExpr *Expr,
+ unsigned Size) {
const MCSection *Section = Streamer.getCurrentSection().first;
- return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext());
+ return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext(),
+ Size);
}
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
if (getParser().parseExpression(SubExprVal))
return true;
+ if (Operands.size() < 2 ||
+ !static_cast<AArch64Operand &>(*Operands[1]).isReg())
+ return true;
+
+ bool IsXReg =
+ AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
+ Operands[1]->getReg());
+
MCContext& Ctx = getContext();
E = SMLoc::getFromPointer(Loc.getPointer() - 1);
// If the op is an imm and can be fit into a mov, then replace ldr with mov.
- if (isa<MCConstantExpr>(SubExprVal) && Operands.size() >= 2 &&
- static_cast<AArch64Operand &>(*Operands[1]).isReg()) {
- bool IsXReg = AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
- Operands[1]->getReg());
+ if (isa<MCConstantExpr>(SubExprVal)) {
uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
ShiftAmt, true, S, E, Ctx));
return false;
}
+ APInt Simm = APInt(64, Imm << ShiftAmt);
+ // check if the immediate is an unsigned or signed 32-bit int for W regs
+ if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
+ return Error(Loc, "Immediate too large for register");
}
// If it is a label or an imm that cannot fit in a movz, put it into CP.
- const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal);
+ const MCExpr *CPLoc =
+ getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4);
Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
return false;
}
// The constant pool handling is shared by all AArch64TargetStreamer
// implementations.
-const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
- return ConstantPools->addEntry(Streamer, Expr);
+const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr,
+ unsigned Size) {
+ return ConstantPools->addEntry(Streamer, Expr, Size);
}
void AArch64TargetStreamer::emitCurrentConstantPool() {
// The constant pool handling is shared by all ARMTargetStreamer
// implementations.
const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
- return ConstantPools->addEntry(Streamer, Expr);
+ return ConstantPools->addEntry(Streamer, Expr, 4);
}
void ARMTargetStreamer::emitCurrentConstantPool() {
--- /dev/null
+//RUN: not llvm-mc -triple=aarch64-linux-gnu - < %s 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
+
+// simple test
+.section a, "ax", @progbits
+f1:
+ ldr w0, =0x100000001
+// CHECK-ERROR: error: Immediate too large for register
+// CHECK-ERROR: ldr w0, =0x100000001
+// CHECK-ERROR: ^
+f2:
+ ldr w0, =-0x80000001
+// CHECK-ERROR: error: Immediate too large for register
+// CHECK-ERROR: ldr w0, =-0x80000001
+// CHECK-ERROR: ^
.section b,"ax",@progbits
// CHECK-LABEL: f3:
f3:
- ldr x0, =0x10001
-// CHECK: ldr x0, .Ltmp[[TMP0:[0-9]+]]
+ ldr w0, =0x10001
+// CHECK: ldr w0, .Ltmp[[TMP0:[0-9]+]]
// loading multiple constants
.section c,"ax",@progbits
// CHECK-LABEL: f4:
f4:
- ldr x0, =0x10002
-// CHECK: ldr x0, .Ltmp[[TMP1:[0-9]+]]
+ ldr w0, =0x10002
+// CHECK: ldr w0, .Ltmp[[TMP1:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
- ldr x0, =0x10003
-// CHECK: ldr x0, .Ltmp[[TMP2:[0-9]+]]
+ ldr w0, =0x10003
+// CHECK: ldr w0, .Ltmp[[TMP2:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
.section d,"ax",@progbits
// CHECK-LABEL: f5:
f5:
- ldr x0, =0x10004
-// CHECK: ldr x0, .Ltmp[[TMP3:[0-9]+]]
+ ldr w0, =0x10004
+// CHECK: ldr w0, .Ltmp[[TMP3:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
- ldr x0, =0x10004
-// CHECK: ldr x0, .Ltmp[[TMP4:[0-9]+]]
+ ldr w0, =0x10004
+// CHECK: ldr w0, .Ltmp[[TMP4:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
.section e,"ax",@progbits
// CHECK-LABEL: f6:
f6:
- ldr x0, =0x10006
-// CHECK: ldr x0, .Ltmp[[TMP5:[0-9]+]]
+ ldr w0, =0x10006
+// CHECK: ldr w0, .Ltmp[[TMP5:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
adds x0, x0, #1
// CHECK-LABEL: f8:
f8:
adds x0, x0, #1
- ldr x0, =0x10007
-// CHECK: ldr x0, .Ltmp[[TMP6:[0-9]+]]
+ ldr w0, =0x10007
+// CHECK: ldr w0, .Ltmp[[TMP6:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
.section g,"ax",@progbits
// CHECK-LABEL: f9:
f9:
- ldr x0, =foo
-// CHECK: ldr x0, .Ltmp[[TMP7:[0-9]+]]
+ ldr w0, =foo
+// CHECK: ldr w0, .Ltmp[[TMP7:[0-9]+]]
// load a symbol from another section
.section h,"ax",@progbits
// CHECK-LABEL: f10:
f10:
- ldr x0, =f5
-// CHECK: ldr x0, .Ltmp[[TMP8:[0-9]+]]
+ ldr w0, =f5
+// CHECK: ldr w0, .Ltmp[[TMP8:[0-9]+]]
// load a symbol from the same section
.section i,"ax",@progbits
// CHECK-LABEL: f11:
f11:
- ldr x0, =f12
-// CHECK: ldr x0, .Ltmp[[TMP9:[0-9]+]]
+ ldr w0, =f12
+// CHECK: ldr w0, .Ltmp[[TMP9:[0-9]+]]
ldr w0,=0x3C000
// CHECK: ldr w0, .Ltmp[[TMP10:[0-9]+]]
f13:
adds x0, x0, #1
adds x0, x0, #1
- ldr x0, =0x101
-// CHECK: movz x0, #0x101
+ ldr w0, =0x101
+// CHECK: movz w0, #0x101
adds x0, x0, #1
adds x0, x0, #1
- ldr x0, =bar
-// CHECK: ldr x0, .Ltmp[[TMP11:[0-9]+]]
+ ldr w0, =bar
+// CHECK: ldr w0, .Ltmp[[TMP11:[0-9]+]]
adds x0, x0, #1
adds x0, x0, #1
//
// usage in macro
.macro useit_in_a_macro
- ldr x0, =0x10008
- ldr x0, =baz
+ ldr w0, =0x10008
+ ldr w0, =baz
.endm
.section k,"ax",@progbits
// CHECK-LABEL: f14:
f14:
useit_in_a_macro
-// CHECK: ldr x0, .Ltmp[[TMP12:[0-9]+]]
-// CHECK: ldr x0, .Ltmp[[TMP13:[0-9]+]]
+// CHECK: ldr w0, .Ltmp[[TMP12:[0-9]+]]
+// CHECK: ldr w0, .Ltmp[[TMP13:[0-9]+]]
// usage with expressions
.section l, "ax", @progbits
// CHECK-LABEL: f15:
f15:
- ldr x0, =0x10001+8
-// CHECK: ldr x0, .Ltmp[[TMP14:[0-9]+]]
+ ldr w0, =0x10001+8
+// CHECK: ldr w0, .Ltmp[[TMP14:[0-9]+]]
adds x0, x0, #1
- ldr x0, =bar+4
-// CHECK: ldr x0, .Ltmp[[TMP15:[0-9]+]]
+ ldr w0, =bar+4
+// CHECK: ldr w0, .Ltmp[[TMP15:[0-9]+]]
adds x0, x0, #1
+// usage with 64-bit regs
+.section m, "ax", @progbits
+// CHECK-LABEL: f16:
+f16:
+ ldr x0, =0x0102030405060708
+// CHECK: ldr x0, .Ltmp[[TMP16:[0-9]+]]
+ add x0, x0, #1
+ ldr w0, =bar
+// CHECK: ldr w0, .Ltmp[[TMP17:[0-9]+]]
+ ldr x0, =bar+16
+// CHECK: ldr x0, .Ltmp[[TMP18:[0-9]+]]
+ add x0, x0, #1
+ ldr x0, =0x100000001
+// CHECK: ldr x0, .Ltmp[[TMP19:[0-9]+]]
+ ldr x1, =-0x80000001
+// CHECK: ldr x1, .Ltmp[[TMP20:[0-9]+]]
+ ldr x2, =0x10001
+// CHECK: ldr x2, .Ltmp[[TMP21:[0-9]+]]
+
+// check range for 32-bit regs
+.section n, "ax", @progbits
+// CHECK-LABEL: f17:
+f17:
+ ldr w0, =0xFFFFFFFF
+// CHECK: ldr w0, .Ltmp[[TMP22:[0-9]+]]
+ add w0, w0, #1
+ ldr w1, =-0x7FFFFFFF
+// CHECK: ldr w1, .Ltmp[[TMP23:[0-9]+]]
+ add w0, w0, #1
+ ldr w0, =-1
+// CHECK: ldr w0, .Ltmp[[TMP24:[0-9]+]]
+ add w0, w0, #1
+
+// make sure the same contant uses different pools for 32- and 64-bit registers
+.section o, "ax", @progbits
+// CHECK-LABEL: f18:
+f18:
+ ldr w0, =0x320064
+// CHECK: ldr w0, .Ltmp[[TMP25:[0-9]+]]
+ add w0, w0, #1
+ ldr x1, =0x320064
+// CHECK: ldr x1, .Ltmp[[TMP26:[0-9]+]]
+
//
// Constant Pools
//
// CHECK: .align 2
// CHECK: .Ltmp[[TMP1]]
// CHECK: .word 65538
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP2]]
// CHECK: .word 65539
// CHECK: .align 2
// CHECK: .Ltmp[[TMP3]]
// CHECK: .word 65540
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP4]]
// CHECK: .word 65540
// CHECK: .align 2
// CHECK: .Ltmp[[TMP5]]
// CHECK: .word 65542
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP6]]
// CHECK: .word 65543
// CHECK: .align 2
// CHECK: .Ltmp[[TMP9]]
// CHECK: .word f12
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP10]]
// CHECK: .word 245760
// CHECK: .align 2
// CHECK: .Ltmp[[TMP12]]
// CHECK: .word 65544
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP13]]
// CHECK: .word baz
// CHECK: .align 2
// CHECK: .Ltmp[[TMP14]]
// CHECK: .word 65545
+// CHECK: .align 2
// CHECK: .Ltmp[[TMP15]]
// CHECK: .word bar+4
+
+// CHECK: .section m,"ax",@progbits
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP16]]
+// CHECK: .xword 72623859790382856
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP17]]
+// CHECK: .word bar
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP18]]
+// CHECK: .xword bar+16
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP19]]
+// CHECK: .xword 4294967297
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP20]]
+// CHECK: .xword -2147483649
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP21]]
+// CHECK: .xword 65537
+
+// CHECK: .section n,"ax",@progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP22]]
+// CHECK: .word 4294967295
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP23]]
+// CHECK: .word -2147483647
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP24]]
+// CHECK: .word -1
+
+// CHECK: .section o,"ax",@progbits
+// CHECK: .align 2
+// CHECK: .Ltmp[[TMP25]]
+// CHECK: .word 3276900
+// CHECK: .align 3
+// CHECK: .Ltmp[[TMP26]]
+// CHECK: .xword 3276900
@ Constant Pools
@
@ CHECK: .section __TEXT,b,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp0:
@ CHECK: .long 65537
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,c,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp1:
@ CHECK: .long 65538
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp2:
@ CHECK: .long 65539
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,d,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp3:
@ CHECK: .long 65540
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp4:
@ CHECK: .long 65540
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,e,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp5:
@ CHECK: .long 65542
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp6:
@ CHECK: .long 65543
@ CHECK: .end_data_region
@ CHECK-NOT: .section __TEXT,f,regular,pure_instructions
@ CHECK: .section __TEXT,g,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp7:
@ CHECK: .long foo
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,h,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp8:
@ CHECK: .long f5
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,i,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp9:
@ CHECK: .long f12
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,j,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp10:
@ CHECK: .long 257
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp11:
@ CHECK: .long bar
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,k,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp12:
@ CHECK: .long 65544
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp13:
@ CHECK: .long baz
@ CHECK: .end_data_region
@ CHECK: .section __TEXT,l,regular,pure_instructions
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp14:
@ CHECK: .long 65545
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp15:
@ CHECK: .long bar+4
@ CHECK: .end_data_region
b f3
.ltorg
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp0:
@ CHECK: .long 65537
@ CHECK: .end_data_region
b f5
.ltorg
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp1:
@ CHECK: .long 65538
@ CHECK: .end_data_region
b f6
.ltorg
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp2:
@ CHECK: .long 65539
@ CHECK: .end_data_region
b f10
.ltorg
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp3:
@ CHECK: .long bar
@ CHECK: .end_data_region
b f12
.ltorg
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp4:
@ CHECK: .long 65540
@ CHECK: .end_data_region
@ should have a non-empty constant pool at end of this section
@ CHECK: .section __TEXT,e,regular,pure_instructions
@ constant pool
-@ CHECK: .align 2
@ CHECK: .data_region
+@ CHECK: .align 2
@ CHECK-LABEL: Ltmp5:
@ CHECK: .long 65541
@ CHECK: .end_data_region