Index: include/llvm/MC/ConstantPools.h =================================================================== --- include/llvm/MC/ConstantPools.h +++ include/llvm/MC/ConstantPools.h @@ -22,10 +22,17 @@ 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, 4> EntryVecTy; + typedef SmallVector EntryVecTy; EntryVecTy Entries; public: @@ -34,9 +41,11 @@ // 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); @@ -69,7 +78,8 @@ 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); Index: include/llvm/MC/MCStreamer.h =================================================================== --- include/llvm/MC/MCStreamer.h +++ include/llvm/MC/MCStreamer.h @@ -97,7 +97,7 @@ /// 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. Index: lib/MC/ConstantPools.cpp =================================================================== --- lib/MC/ConstantPools.cpp +++ lib/MC/ConstantPools.cpp @@ -24,21 +24,22 @@ 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); } @@ -89,7 +90,9 @@ } 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); } Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -25,6 +25,7 @@ #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" @@ -3087,13 +3088,18 @@ if (getParser().parseExpression(SubExprVal)) return true; + if (Operands.size() < 2 || + !static_cast(*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(SubExprVal) && Operands.size() >= 2 && - static_cast(*Operands[1]).isReg()) { - bool IsXReg = AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains( - Operands[1]->getReg()); + if (isa(SubExprVal)) { uint64_t Imm = (cast(SubExprVal))->getValue(); uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16; while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) { @@ -3109,9 +3115,14 @@ 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; } Index: lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp =================================================================== --- lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp +++ lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.cpp @@ -28,8 +28,9 @@ // 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() { Index: lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp +++ lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp @@ -28,7 +28,7 @@ // 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() { Index: test/MC/AArch64/ldr-pseudo-diagnostics.s =================================================================== --- /dev/null +++ test/MC/AArch64/ldr-pseudo-diagnostics.s @@ -0,0 +1,14 @@ +//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: ^ Index: test/MC/AArch64/ldr-pseudo.s =================================================================== --- test/MC/AArch64/ldr-pseudo.s +++ test/MC/AArch64/ldr-pseudo.s @@ -23,21 +23,21 @@ .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 @@ -45,8 +45,8 @@ .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 @@ -54,8 +54,8 @@ 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 @@ -67,8 +67,8 @@ .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 @@ -84,8 +84,8 @@ // 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 @@ -97,22 +97,22 @@ .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]+]] @@ -127,12 +127,12 @@ 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 // @@ -141,27 +141,54 @@ // 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 + +// check range for 32-bit regs +.section n, "ax", @progbits +// CHECK-LABEL: f17: +f17: + ldr w0, =0xFFFFFFFF +// CHECK: ldr w0, .Ltmp[[TMP19:[0-9]+]] + add w0, w0, #1 + ldr w1, =-0x7FFFFFFF +// CHECK: ldr w1, .Ltmp[[TMP20:[0-9]+]] + add w0, w0, #1 + ldr w0, =-1 +// CHECK: ldr w0, .Ltmp[[TMP21:[0-9]+]] + add w0, w0, #1 + // // Constant Pools // @@ -174,6 +201,7 @@ // CHECK: .align 2 // CHECK: .Ltmp[[TMP1]] // CHECK: .word 65538 +// CHECK: .align 2 // CHECK: .Ltmp[[TMP2]] // CHECK: .word 65539 @@ -181,6 +209,7 @@ // CHECK: .align 2 // CHECK: .Ltmp[[TMP3]] // CHECK: .word 65540 +// CHECK: .align 2 // CHECK: .Ltmp[[TMP4]] // CHECK: .word 65540 @@ -188,6 +217,7 @@ // CHECK: .align 2 // CHECK: .Ltmp[[TMP5]] // CHECK: .word 65542 +// CHECK: .align 2 // CHECK: .Ltmp[[TMP6]] // CHECK: .word 65543 @@ -208,6 +238,7 @@ // CHECK: .align 2 // CHECK: .Ltmp[[TMP9]] // CHECK: .word f12 +// CHECK: .align 2 // CHECK: .Ltmp[[TMP10]] // CHECK: .word 245760 @@ -220,6 +251,7 @@ // CHECK: .align 2 // CHECK: .Ltmp[[TMP12]] // CHECK: .word 65544 +// CHECK: .align 2 // CHECK: .Ltmp[[TMP13]] // CHECK: .word baz @@ -227,5 +259,28 @@ // 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: .section n,"ax",@progbits +// CHECK: .align 2 +// CHECK: .Ltmp[[TMP19]] +// CHECK: .word 4294967295 +// CHECK: .align 2 +// CHECK: .Ltmp[[TMP20]] +// CHECK: .word -2147483647 +// CHECK: .align 2 +// CHECK: .Ltmp[[TMP21]] +// CHECK: .word -1 Index: test/MC/ARM/ldr-pseudo-darwin.s =================================================================== --- test/MC/ARM/ldr-pseudo-darwin.s +++ test/MC/ARM/ldr-pseudo-darwin.s @@ -156,35 +156,38 @@ @ 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 @@ -193,49 +196,52 @@ @ 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 Index: test/MC/ARM/ltorg-darwin.s =================================================================== --- test/MC/ARM/ltorg-darwin.s +++ test/MC/ARM/ltorg-darwin.s @@ -19,8 +19,8 @@ b f3 .ltorg @ constant pool -@ CHECK: .align 2 @ CHECK: .data_region +@ CHECK: .align 2 @ CHECK-LABEL: Ltmp0: @ CHECK: .long 65537 @ CHECK: .end_data_region @@ -41,8 +41,8 @@ b f5 .ltorg @ constant pool -@ CHECK: .align 2 @ CHECK: .data_region +@ CHECK: .align 2 @ CHECK-LABEL: Ltmp1: @ CHECK: .long 65538 @ CHECK: .end_data_region @@ -57,8 +57,8 @@ b f6 .ltorg @ constant pool -@ CHECK: .align 2 @ CHECK: .data_region +@ CHECK: .align 2 @ CHECK-LABEL: Ltmp2: @ CHECK: .long 65539 @ CHECK: .end_data_region @@ -92,8 +92,8 @@ b f10 .ltorg @ constant pool -@ CHECK: .align 2 @ CHECK: .data_region +@ CHECK: .align 2 @ CHECK-LABEL: Ltmp3: @ CHECK: .long bar @ CHECK: .end_data_region @@ -114,8 +114,8 @@ b f12 .ltorg @ constant pool -@ CHECK: .align 2 @ CHECK: .data_region +@ CHECK: .align 2 @ CHECK-LABEL: Ltmp4: @ CHECK: .long 65540 @ CHECK: .end_data_region @@ -141,8 +141,8 @@ @ 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