summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2014-04-24 12:12:10 +0000
committerTim Northover <tnorthover@apple.com>2014-04-24 12:12:10 +0000
commit79ec019261e44ad5c03194aa124e4a5b1be04f7d (patch)
treedfecc805095d966b2839f8e68f902fcc6ecc384b /llvm/lib
parentcf16ec238e469dcc83d335fddaa25a713231a2aa (diff)
downloadbcm5719-llvm-79ec019261e44ad5c03194aa124e4a5b1be04f7d.tar.gz
bcm5719-llvm-79ec019261e44ad5c03194aa124e4a5b1be04f7d.zip
AArch64/ARM64: disentangle the "B.CC" and "LDR lit" operands
These can have different relocations in ELF. In particular both: b.eq global ldr x0, global are valid, giving different relocations. The only possible way to distinguish them is via a different fixup, so the operands had to be separated throughout the backend. llvm-svn: 207105
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/ARM64/ARM64InstrFormats.td29
-rw-r--r--llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp4
-rw-r--r--llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp9
-rw-r--r--llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp5
-rw-r--r--llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h3
-rw-r--r--llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp9
-rw-r--r--llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp6
-rw-r--r--llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h14
-rw-r--r--llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp30
-rw-r--r--llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp5
10 files changed, 77 insertions, 37 deletions
diff --git a/llvm/lib/Target/ARM64/ARM64InstrFormats.td b/llvm/lib/Target/ARM64/ARM64InstrFormats.td
index 64113d89625..abb92514a5b 100644
--- a/llvm/lib/Target/ARM64/ARM64InstrFormats.td
+++ b/llvm/lib/Target/ARM64/ARM64InstrFormats.td
@@ -858,14 +858,14 @@ def dotCcode : Operand<i32> {
// Conditional branch target. 19-bit immediate. The low two bits of the target
// offset are implied zero and so are not part of the immediate.
-def BranchTarget19Operand : AsmOperandClass {
- let Name = "BranchTarget19";
+def PCRelLabel19Operand : AsmOperandClass {
+ let Name = "PCRelLabel19";
}
def am_brcond : Operand<OtherVT> {
let EncoderMethod = "getCondBranchTargetOpValue";
- let DecoderMethod = "DecodeCondBranchTarget";
- let PrintMethod = "printAlignedBranchTarget";
- let ParserMatchClass = BranchTarget19Operand;
+ let DecoderMethod = "DecodePCRelLabel19";
+ let PrintMethod = "printAlignedLabel";
+ let ParserMatchClass = PCRelLabel19Operand;
}
class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
@@ -922,7 +922,7 @@ def BranchTarget14Operand : AsmOperandClass {
}
def am_tbrcond : Operand<OtherVT> {
let EncoderMethod = "getTestBranchTargetOpValue";
- let PrintMethod = "printAlignedBranchTarget";
+ let PrintMethod = "printAlignedLabel";
let ParserMatchClass = BranchTarget14Operand;
}
@@ -956,12 +956,12 @@ def BranchTarget26Operand : AsmOperandClass {
}
def am_b_target : Operand<OtherVT> {
let EncoderMethod = "getBranchTargetOpValue";
- let PrintMethod = "printAlignedBranchTarget";
+ let PrintMethod = "printAlignedLabel";
let ParserMatchClass = BranchTarget26Operand;
}
def am_bl_target : Operand<i64> {
let EncoderMethod = "getBranchTargetOpValue";
- let PrintMethod = "printAlignedBranchTarget";
+ let PrintMethod = "printAlignedLabel";
let ParserMatchClass = BranchTarget26Operand;
}
@@ -2128,9 +2128,18 @@ class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
// Load literal
//---
+// Load literal address: 19-bit immediate. The low two bits of the target
+// offset are implied zero and so are not part of the immediate.
+def am_ldrlit : Operand<OtherVT> {
+ let EncoderMethod = "getLoadLiteralOpValue";
+ let DecoderMethod = "DecodePCRelLabel19";
+ let PrintMethod = "printAlignedLabel";
+ let ParserMatchClass = PCRelLabel19Operand;
+}
+
let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
- : I<(outs regtype:$Rt), (ins am_brcond:$label),
+ : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
asm, "\t$Rt, $label", "", []>,
Sched<[WriteLD]> {
bits<5> Rt;
@@ -2145,7 +2154,7 @@ class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
- : I<(outs), (ins prfop:$Rt, am_brcond:$label),
+ : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
asm, "\t$Rt, $label", "", pat>,
Sched<[WriteLD]> {
bits<5> Rt;
diff --git a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
index 2f720e9c969..7efc4572bda 100644
--- a/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
+++ b/llvm/lib/Target/ARM64/AsmParser/ARM64AsmParser.cpp
@@ -558,7 +558,7 @@ public:
return false;
return (Val >= -(0x2000000 << 2) && Val <= (0x1ffffff << 2));
}
- bool isBranchTarget19() const {
+ bool isPCRelLabel19() const {
if (!isImm())
return false;
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
@@ -1272,7 +1272,7 @@ public:
Inst.addOperand(MCOperand::CreateImm(MCE->getValue() >> 2));
}
- void addBranchTarget19Operands(MCInst &Inst, unsigned N) const {
+ void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
// Branch operands don't encode the low bits, so shift them off
// here. If it's a label, however, just put it on directly as there's
// not enough information now to do anything.
diff --git a/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
index 097594f0340..2ada4a4cf9e 100644
--- a/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
+++ b/llvm/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp
@@ -87,9 +87,8 @@ static DecodeStatus DecodeFixedPointScaleImm32(llvm::MCInst &Inst, unsigned Imm,
static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeCondBranchTarget(llvm::MCInst &Inst, unsigned Imm,
- uint64_t Address,
- const void *Decoder);
+static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm,
+ uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMRSSystemRegister(llvm::MCInst &Inst, unsigned Imm,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMSRSystemRegister(llvm::MCInst &Inst, unsigned Imm,
@@ -582,8 +581,8 @@ static DecodeStatus DecodeFixedPointScaleImm64(llvm::MCInst &Inst, unsigned Imm,
return Success;
}
-static DecodeStatus DecodeCondBranchTarget(llvm::MCInst &Inst, unsigned Imm,
- uint64_t Addr, const void *Decoder) {
+static DecodeStatus DecodePCRelLabel19(llvm::MCInst &Inst, unsigned Imm,
+ uint64_t Addr, const void *Decoder) {
int64_t ImmVal = Imm;
const ARM64Disassembler *Dis =
static_cast<const ARM64Disassembler *>(Decoder);
diff --git a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp
index 28af3f01666..0dea241ed18 100644
--- a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp
+++ b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.cpp
@@ -1422,9 +1422,8 @@ void ARM64InstPrinter::printVectorIndex(const MCInst *MI, unsigned OpNum,
O << "[" << MI->getOperand(OpNum).getImm() << "]";
}
-void ARM64InstPrinter::printAlignedBranchTarget(const MCInst *MI,
- unsigned OpNum,
- raw_ostream &O) {
+void ARM64InstPrinter::printAlignedLabel(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNum);
// If the label has already been resolved to an immediate offset (say, when
diff --git a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h
index 778e8651b8f..7f2a9fe12a0 100644
--- a/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h
+++ b/llvm/lib/Target/ARM64/InstPrinter/ARM64InstPrinter.h
@@ -69,8 +69,7 @@ protected:
void printExtend(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printDotCondCode(const MCInst *MI, unsigned OpNum, raw_ostream &O);
- void printAlignedBranchTarget(const MCInst *MI, unsigned OpNum,
- raw_ostream &O);
+ void printAlignedLabel(const MCInst *MI, unsigned OpNum, raw_ostream &O);
void printAMIndexed(const MCInst *MI, unsigned OpNum, unsigned Scale,
raw_ostream &O);
void printAMIndexedWB(const MCInst *MI, unsigned OpNum, unsigned Scale,
diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp
index 55ba91d7267..c9b95a2c163 100644
--- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp
+++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp
@@ -45,9 +45,10 @@ public:
{ "fixup_arm64_ldst_imm12_scale4", 10, 12, 0 },
{ "fixup_arm64_ldst_imm12_scale8", 10, 12, 0 },
{ "fixup_arm64_ldst_imm12_scale16", 10, 12, 0 },
+ { "fixup_arm64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal },
{ "fixup_arm64_movw", 5, 16, 0 },
{ "fixup_arm64_pcrel_branch14", 5, 14, PCRelFlagVal },
- { "fixup_arm64_pcrel_imm19", 5, 19, PCRelFlagVal },
+ { "fixup_arm64_pcrel_branch19", 5, 19, PCRelFlagVal },
{ "fixup_arm64_pcrel_branch26", 0, 26, PCRelFlagVal },
{ "fixup_arm64_pcrel_call26", 0, 26, PCRelFlagVal },
{ "fixup_arm64_tlsdesc_call", 0, 0, 0 }
@@ -101,7 +102,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM64::fixup_arm64_ldst_imm12_scale4:
case ARM64::fixup_arm64_ldst_imm12_scale8:
case ARM64::fixup_arm64_ldst_imm12_scale16:
- case ARM64::fixup_arm64_pcrel_imm19:
+ case ARM64::fixup_arm64_ldr_pcrel_imm19:
+ case ARM64::fixup_arm64_pcrel_branch19:
return 3;
case ARM64::fixup_arm64_pcrel_adr_imm21:
@@ -133,7 +135,8 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
return AdrImmBits(Value & 0x1fffffULL);
case ARM64::fixup_arm64_pcrel_adrp_imm21:
return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
- case ARM64::fixup_arm64_pcrel_imm19:
+ case ARM64::fixup_arm64_ldr_pcrel_imm19:
+ case ARM64::fixup_arm64_pcrel_branch19:
// Signed 21-bit immediate
if (SignedValue > 2097151 || SignedValue < -2097152)
report_fatal_error("fixup value out of range");
diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp
index fe3070c019e..718501f918e 100644
--- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp
+++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64ELFObjectWriter.cpp
@@ -82,11 +82,11 @@ unsigned ARM64ELFObjectWriter::GetRelocType(const MCValue &Target,
return ELF::R_AARCH64_JUMP26;
case ARM64::fixup_arm64_pcrel_call26:
return ELF::R_AARCH64_CALL26;
- case ARM64::fixup_arm64_pcrel_imm19:
- // A bit of an oddity here: shared by both "ldr x0, :gottprel:var" and
- // "b.eq var".
+ case ARM64::fixup_arm64_ldr_pcrel_imm19:
if (SymLoc == ARM64MCExpr::VK_GOTTPREL)
return ELF::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19;
+ return ELF::R_AARCH64_LD_PREL_LO19;
+ case ARM64::fixup_arm64_pcrel_branch19:
return ELF::R_AARCH64_CONDBR19;
default:
llvm_unreachable("Unsupported pc-relative fixup kind");
diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h
index 02eb91f805f..7106b314ea2 100644
--- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h
+++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64FixupKinds.h
@@ -36,6 +36,11 @@ enum Fixups {
fixup_arm64_ldst_imm12_scale8,
fixup_arm64_ldst_imm12_scale16,
+ // fixup_arm64_ldr_pcrel_imm19 - The high 19 bits of a 21-bit pc-relative
+ // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this is used by
+ // pc-relative loads and generates relocations directly when necessary.
+ fixup_arm64_ldr_pcrel_imm19,
+
// FIXME: comment
fixup_arm64_movw,
@@ -43,11 +48,10 @@ enum Fixups {
// immediate.
fixup_arm64_pcrel_branch14,
- // fixup_arm64_pcrel_imm19 - The high 19 bits of a 21-bit pc-relative
- // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this
- // is not used as part of a lo/hi pair and thus generates relocations
- // directly when necessary.
- fixup_arm64_pcrel_imm19,
+ // fixup_arm64_pcrel_branch19 - The high 19 bits of a 21-bit pc-relative
+ // immediate. Same encoding as fixup_arm64_pcrel_adrhi, except this is use by
+ // b.cc and generates relocations directly when necessary.
+ fixup_arm64_pcrel_branch19,
// fixup_arm64_pcrel_branch26 - The high 26 bits of a 28-bit pc-relative
// immediate.
diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp
index 85acdf31916..8910337d0d2 100644
--- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp
+++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MCCodeEmitter.cpp
@@ -83,6 +83,12 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ /// getLoadLiteralOpValue - Return the encoded value for a load-literal
+ /// pc-relative address.
+ uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
/// getTestBranchTargetOpValue - Return the encoded value for a test-bit-and-
/// branch target.
uint32_t getTestBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
@@ -305,7 +311,29 @@ uint32_t ARM64MCCodeEmitter::getCondBranchTargetOpValue(
return MO.getImm();
assert(MO.isExpr() && "Unexpected target type!");
- MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_imm19);
+ MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_pcrel_branch19);
+ Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
+
+ ++MCNumFixups;
+
+ // All of the information is in the fixup.
+ return 0;
+}
+
+/// getLoadLiteralOpValue - Return the encoded value for a load-literal
+/// pc-relative address.
+uint32_t
+ARM64MCCodeEmitter::getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ const MCOperand &MO = MI.getOperand(OpIdx);
+
+ // If the destination is an immediate, we have nothing to do.
+ if (MO.isImm())
+ return MO.getImm();
+ assert(MO.isExpr() && "Unexpected target type!");
+
+ MCFixupKind Kind = MCFixupKind(ARM64::fixup_arm64_ldr_pcrel_imm19);
Fixups.push_back(MCFixup::Create(0, MO.getExpr(), Kind, MI.getLoc()));
++MCNumFixups;
diff --git a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp
index f28896c1f9e..1695b393055 100644
--- a/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp
+++ b/llvm/lib/Target/ARM64/MCTargetDesc/ARM64MachObjectWriter.cpp
@@ -136,14 +136,13 @@ void ARM64MachObjectWriter::RecordRelocation(
// ADRP fixups use relocations for the whole symbol value and only
// put the addend in the instruction itself. Clear out any value the
// generic code figured out from the sybmol definition.
- if (Kind == ARM64::fixup_arm64_pcrel_adrp_imm21 ||
- Kind == ARM64::fixup_arm64_pcrel_imm19)
+ if (Kind == ARM64::fixup_arm64_pcrel_adrp_imm21)
FixedValue = 0;
// imm19 relocations are for conditional branches, which require
// assembler local symbols. If we got here, that's not what we have,
// so complain loudly.
- if (Kind == ARM64::fixup_arm64_pcrel_imm19) {
+ if (Kind == ARM64::fixup_arm64_pcrel_branch19) {
Asm.getContext().FatalError(Fixup.getLoc(),
"conditional branch requires assembler-local"
" label. '" +
OpenPOWER on IntegriCloud