1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 11:13:28 +01:00

MC: support different sized constants in constant pools

On AArch64 the pseudo instruction ldr <reg>, =... supports both
32-bit and 64-bit constants. Add support for 64 bit constants for
the pools to support the pseudo instruction fully.

Changes the AArch64 ldr-pseudo tests to use 32-bit registers and
adds tests with 64-bit registers.

Patch by Janne Grunau!

Differential Revision: http://reviews.llvm.org/D4279

llvm-svn: 213387
This commit is contained in:
David Peixotto 2014-07-18 16:05:14 +00:00
parent 000be1bc2f
commit 569d73691e
10 changed files with 200 additions and 67 deletions

View File

@ -22,10 +22,17 @@ class MCExpr;
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:
@ -34,9 +41,11 @@ 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);
@ -69,7 +78,8 @@ public:
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);

View File

@ -97,7 +97,7 @@ public:
/// 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.

View File

@ -24,21 +24,22 @@ using namespace llvm;
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 @@ void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
}
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);
}

View File

@ -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"
@ -3067,13 +3068,18 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
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) {
@ -3089,9 +3095,14 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
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;
}

View File

@ -28,8 +28,9 @@ AArch64TargetStreamer::~AArch64TargetStreamer() {}
// 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() {

View File

@ -28,7 +28,7 @@ ARMTargetStreamer::~ARMTargetStreamer() {}
// 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() {

View File

@ -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: ^

View File

@ -23,21 +23,21 @@ f1:
.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 @@ f4:
.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 @@ f5:
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 @@ f5:
.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 @@ f7:
// 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 @@ f8:
.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 @@ f12:
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,70 @@ f13:
// 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
//
@ -174,6 +217,7 @@ f15:
// CHECK: .align 2
// CHECK: .Ltmp[[TMP1]]
// CHECK: .word 65538
// CHECK: .align 2
// CHECK: .Ltmp[[TMP2]]
// CHECK: .word 65539
@ -181,6 +225,7 @@ f15:
// CHECK: .align 2
// CHECK: .Ltmp[[TMP3]]
// CHECK: .word 65540
// CHECK: .align 2
// CHECK: .Ltmp[[TMP4]]
// CHECK: .word 65540
@ -188,6 +233,7 @@ f15:
// CHECK: .align 2
// CHECK: .Ltmp[[TMP5]]
// CHECK: .word 65542
// CHECK: .align 2
// CHECK: .Ltmp[[TMP6]]
// CHECK: .word 65543
@ -208,6 +254,7 @@ f15:
// CHECK: .align 2
// CHECK: .Ltmp[[TMP9]]
// CHECK: .word f12
// CHECK: .align 2
// CHECK: .Ltmp[[TMP10]]
// CHECK: .word 245760
@ -220,6 +267,7 @@ f15:
// CHECK: .align 2
// CHECK: .Ltmp[[TMP12]]
// CHECK: .word 65544
// CHECK: .align 2
// CHECK: .Ltmp[[TMP13]]
// CHECK: .word baz
@ -227,5 +275,45 @@ f15:
// 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

View File

@ -156,35 +156,38 @@ f15:
@ 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 @@ f15:
@ 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

View File

@ -19,8 +19,8 @@ f2:
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 @@ f4:
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 @@ f5:
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 @@ f9:
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 @@ f11:
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 @@ f13:
@ 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