Index: include/llvm/MC/ConstantPools.h =================================================================== --- include/llvm/MC/ConstantPools.h +++ include/llvm/MC/ConstantPools.h @@ -25,18 +25,20 @@ // A class to keep track of assembler-generated constant pools that are use to // implement the ldr-pseudo. class ConstantPool { - typedef SmallVector, 4> EntryVecTy; + unsigned MaxAlignment; + typedef SmallVector, 4> EntryVecTy; EntryVecTy Entries; public: // Initialize a new empty constant pool - ConstantPool() {} + ConstantPool(); // Add a new entry to the constant pool in the next slot. // \param Value is the new entry to put in the constant pool. // // \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 = 4); // Emit the contents of the constant pool using the provided streamer. void emitEntries(MCStreamer &Streamer); @@ -69,7 +71,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 = 4); 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 @@ -20,25 +20,35 @@ // // ConstantPool implementation // +ConstantPool::ConstantPool() : MaxAlignment(4) {}; // Emit the contents of the constant pool using the provided streamer. void ConstantPool::emitEntries(MCStreamer &Streamer) { + unsigned Alignment = 0; if (Entries.empty()) return; - Streamer.EmitCodeAlignment(4); // align to 4-byte address + Streamer.EmitCodeAlignment(MaxAlignment); // align naturally 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); + unsigned Size = std::get<2>(*I); + if (Alignment && Size > Alignment) + Streamer.EmitCodeAlignment(Size); + Alignment = (Alignment + Size) % MaxAlignment; + Streamer.EmitLabel(std::get<0>(*I)); + Streamer.EmitValue(std::get<1>(*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)); + if (Size > MaxAlignment) + MaxAlignment = Size; + + Entries.push_back(std::make_tuple(CPEntryLabel, Value, Size)); return MCSymbolRefExpr::Create(CPEntryLabel, Context); } @@ -89,7 +99,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 @@ -3087,13 +3087,15 @@ 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 +3111,14 @@ ShiftAmt, true, S, E, Ctx)); return false; } + int64_t Simm = Imm << ShiftAmt; + if (!IsXReg && (Simm >= 1LL << 32 || Simm < INT32_MIN)) + 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: 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,71 +23,71 @@ .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]+]] - 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]+]] - adds x0, x0, #1 - adds x0, x0, #1 + ldr w0, =0x10002 +// CHECK: ldr w0, .Ltmp[[TMP1:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + ldr w0, =0x10003 +// CHECK: ldr w0, .Ltmp[[TMP2:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 // TODO: the same constants should have the same constant pool location .section d,"ax",@progbits // CHECK-LABEL: f5: f5: - ldr x0, =0x10004 -// CHECK: ldr x0, .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 - adds x0, x0, #1 - ldr x0, =0x10004 -// CHECK: ldr x0, .Ltmp[[TMP4:[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 w0, =0x10004 +// CHECK: ldr w0, .Ltmp[[TMP3:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + ldr w0, =0x10004 +// CHECK: ldr w0, .Ltmp[[TMP4:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 // a section defined in multiple pieces should be merged and use a single constant pool .section e,"ax",@progbits // CHECK-LABEL: f6: f6: - ldr x0, =0x10006 -// CHECK: ldr x0, .Ltmp[[TMP5:[0-9]+]] - adds x0, x0, #1 - adds x0, x0, #1 - adds x0, x0, #1 + ldr w0, =0x10006 +// CHECK: ldr w0, .Ltmp[[TMP5:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 .section f, "ax", @progbits // CHECK-LABEL: f7: f7: - adds x0, x0, #1 - adds x0, x0, #1 - adds x0, x0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + adds w0, w0, #1 .section e, "ax", @progbits // CHECK-LABEL: f8: f8: - adds x0, x0, #1 - ldr x0, =0x10007 -// CHECK: ldr x0, .Ltmp[[TMP6:[0-9]+]] - adds x0, x0, #1 - adds x0, x0, #1 + adds w0, w0, #1 + ldr w0, =0x10007 +// CHECK: ldr w0, .Ltmp[[TMP6:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 // // Check that symbols can be loaded using ldr pseudo @@ -97,70 +97,97 @@ .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]+]] // CHECK-LABEL: f12: f12: - adds x0, x0, #1 - adds x0, x0, #1 + adds w0, w0, #1 + adds w0, w0, #1 .section j,"ax",@progbits // mix of symbols and constants // CHECK-LABEL: f13: f13: - adds x0, x0, #1 - adds x0, x0, #1 - ldr x0, =0x101 -// CHECK: movz x0, #0x101 - adds x0, x0, #1 - adds x0, x0, #1 - ldr x0, =bar -// CHECK: ldr x0, .Ltmp[[TMP11:[0-9]+]] - adds x0, x0, #1 - adds x0, x0, #1 + adds w0, w0, #1 + adds w0, w0, #1 + ldr w0, =0x101 +// CHECK: movz w0, #0x101 + adds w0, w0, #1 + adds w0, w0, #1 + ldr w0, =bar +// CHECK: ldr w0, .Ltmp[[TMP11:[0-9]+]] + adds w0, w0, #1 + adds w0, w0, #1 // // Check for correct usage in other contexts // // 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]+]] - adds x0, x0, #1 - ldr x0, =bar+4 -// CHECK: ldr x0, .Ltmp[[TMP15:[0-9]+]] - adds x0, x0, #1 + ldr w0, =0x10001+8 +// CHECK: ldr w0, .Ltmp[[TMP14:[0-9]+]] + adds w0, w0, #1 + ldr w0, =bar+4 +// CHECK: ldr w0, .Ltmp[[TMP15:[0-9]+]] + adds w0, w0, #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 @@ -229,3 +256,22 @@ // CHECK: .word 65545 // CHECK: .Ltmp[[TMP15]] // CHECK: .word bar+4 + +// CHECK: .section m,"ax",@progbits +// CHECK: .align 3 +// CHECK: .Ltmp[[TMP16]] +// CHECK: .xword 72623859790382856 +// 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: .Ltmp[[TMP20]] +// CHECK: .word -2147483647 +// CHECK: .Ltmp[[TMP21]] +// CHECK: .word -1