aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2012-02-27 21:36:23 +0000
committerJim Grosbach <grosbach@apple.com>2012-02-27 21:36:23 +0000
commit7b25ecf6adbf3c4709c48033acfeb6ebbb4452ab (patch)
tree649c04d8126e29b74b9881df0434fadd4aec39d9
parent945c2b3965a5d327055f624dd5dab659551da108 (diff)
ARM BL/BLX instruction fixups should use relocations.
We on the linker to resolve calls to the appropriate BL/BLX instruction to make interworking function correctly. It uses the symbol in the relocation to do that, so we need to be careful about being too clever. To enable this for ARM mode, split the BL/BLX fixup kind off from the unconditional-branch fixups. rdar://10927209 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151571 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAsmBackend.h6
-rw-r--r--lib/MC/MCAssembler.cpp6
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp2
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td4
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp20
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp2
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h6
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp23
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp2
-rw-r--r--test/MC/ARM/arm_fixups.s2
-rw-r--r--test/MC/ARM/basic-arm-instructions.s4
11 files changed, 57 insertions, 20 deletions
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index 11a081b207..641ded5ef0 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -92,11 +92,13 @@ public:
virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
/// processFixupValue - Target hook to adjust the literal value of a fixup
- /// if necessary. The default does nothing.
+ /// if necessary. IsResolved signals whether the caller believes a relocation
+ /// is needed; the target can modify the value. The default does nothing.
virtual void processFixupValue(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value) {}
+ MCValue &Target, uint64_t &Value,
+ bool &IsResolved) {}
/// @}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index c041f65640..a2aaf4e835 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -299,8 +299,10 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout,
Value -= Offset;
}
- // Let the backend adjust the fixup value if necessary.
- Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value);
+ // Let the backend adjust the fixup value if necessary, including whether
+ // we need a relocation.
+ Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value,
+ IsResolved);
return IsResolved;
}
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index 3064f5701f..8b101e6c4f 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -189,6 +189,8 @@ namespace {
unsigned Op) const { return 0; }
unsigned getARMBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
+ unsigned getARMBLTargetOpValue(const MachineInstr &MI, unsigned Op)
+ const { return 0; }
unsigned getARMBLXTargetOpValue(const MachineInstr &MI, unsigned Op)
const { return 0; }
unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index dae09c70dd..1c2976d354 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -349,13 +349,11 @@ def bltarget : Operand<i32> {
// Call target for ARM. Handles conditional/unconditional
// FIXME: rename bl_target to t2_bltarget?
def bl_target : Operand<i32> {
- // Encoded the same as branch targets.
- let EncoderMethod = "getARMBranchTargetOpValue";
+ let EncoderMethod = "getARMBLTargetOpValue";
let OperandType = "OPERAND_PCREL";
}
def blx_target : Operand<i32> {
- // Encoded the same as branch targets.
let EncoderMethod = "getARMBLXTargetOpValue";
let OperandType = "OPERAND_PCREL";
}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 55ea023d97..d3a3d3a3b0 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -78,6 +78,8 @@ public:
{ "fixup_t2_condbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_t2_uncondbranch", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_br", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_bl", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_blx", 0, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_blx", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_cb", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
@@ -106,18 +108,28 @@ public:
/// if necessary.
void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
- MCValue &Target, uint64_t &Value) {
+ MCValue &Target, uint64_t &Value,
+ bool &IsResolved) {
+ const MCSymbolRefExpr *A = Target.getSymA();
// Some fixups to thumb function symbols need the low bit (thumb bit)
// twiddled.
if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 &&
(unsigned)Fixup.getKind() != ARM::fixup_t2_ldst_pcrel_12 &&
(unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) {
- if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ if (A) {
const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
if (Asm.isThumbFunc(&Sym))
Value |= 1;
}
}
+ // We must always generate a relocation for BL/BLX instructions if we have
+ // a symbol to reference, as the linker relies on knowing the destination
+ // symbol's thumb-ness to get interworking right.
+ if (A && ((unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_blx ||
+ (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl ||
+ (unsigned)Fixup.getKind() == ARM::fixup_arm_blx ||
+ (unsigned)Fixup.getKind() == ARM::fixup_arm_bl))
+ IsResolved = false;
}
bool mayNeedRelaxation(const MCInst &Inst) const;
@@ -343,6 +355,8 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
+ case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_blx:
// These values don't encode the low two bits since they're always zero.
// Offset by 8 just as above.
return 0xffffff & ((Value - 8) >> 2);
@@ -552,6 +566,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM::fixup_arm_ldst_pcrel_12:
case ARM::fixup_arm_pcrel_10:
case ARM::fixup_arm_adr_pcrel_12:
+ case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_blx:
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
return 3;
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
index a6a67e4af3..5476a46b71 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp
@@ -177,6 +177,8 @@ unsigned ARMELFObjectWriter::GetRelocTypeInner(const MCValue &Target,
break;
}
break;
+ case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_blx:
case ARM::fixup_arm_uncondbranch:
switch (Modifier) {
case MCSymbolRefExpr::VK_ARM_PLT:
diff --git a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
index a819361ad0..182798630b 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h
@@ -59,6 +59,12 @@ enum Fixups {
// fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions.
fixup_arm_thumb_br,
+ // fixup_arm_bl - Fixup for ARM BL instructions.
+ fixup_arm_bl,
+
+ // fixup_arm_blx - Fixup for ARM BLX instructions.
+ fixup_arm_blx,
+
// fixup_arm_thumb_bl - Fixup for Thumb BL instructions.
fixup_arm_thumb_bl,
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
index 3a3b1674c7..4445dcd8dd 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp
@@ -118,8 +118,10 @@ public:
/// branch target.
uint32_t getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const;
+ uint32_t getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const;
uint32_t getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
- SmallVectorImpl<MCFixup> &Fixups) const;
+ SmallVectorImpl<MCFixup> &Fixups) const;
/// getAdrLabelOpValue - Return encoding info for 12-bit immediate
/// ADR label target.
@@ -592,16 +594,21 @@ getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
}
uint32_t ARMMCCodeEmitter::
+getARMBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ const MCOperand MO = MI.getOperand(OpIdx);
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_bl, Fixups);
+
+ return MO.getImm() >> 2;
+}
+
+uint32_t ARMMCCodeEmitter::
getARMBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand MO = MI.getOperand(OpIdx);
- if (MO.isExpr()) {
- if (HasConditionalBranch(MI))
- return ::getBranchTargetOpValue(MI, OpIdx,
- ARM::fixup_arm_condbranch, Fixups);
- return ::getBranchTargetOpValue(MI, OpIdx,
- ARM::fixup_arm_uncondbranch, Fixups);
- }
+ if (MO.isExpr())
+ return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_blx, Fixups);
return MO.getImm() >> 1;
}
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp
index 96a11ebe07..faf73ac07d 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMMachObjectWriter.cpp
@@ -82,6 +82,8 @@ static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
case ARM::fixup_arm_adr_pcrel_12:
case ARM::fixup_arm_condbranch:
case ARM::fixup_arm_uncondbranch:
+ case ARM::fixup_arm_bl:
+ case ARM::fixup_arm_blx:
RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
// Report as 'long', even though that is not quite accurate.
Log2Size = llvm::Log2_32(4);
diff --git a/test/MC/ARM/arm_fixups.s b/test/MC/ARM/arm_fixups.s
index aba0cd824d..2f3474836b 100644
--- a/test/MC/ARM/arm_fixups.s
+++ b/test/MC/ARM/arm_fixups.s
@@ -3,7 +3,7 @@
bl _printf
@ CHECK: bl _printf @ encoding: [A,A,A,0xeb]
-@ CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_uncondbranch
+@ CHECK: @ fixup A - offset: 0, value: _printf, kind: fixup_arm_bl
mov r9, :lower16:(_foo)
movw r9, :lower16:(_foo)
diff --git a/test/MC/ARM/basic-arm-instructions.s b/test/MC/ARM/basic-arm-instructions.s
index a51b00be53..4ae1ac76f3 100644
--- a/test/MC/ARM/basic-arm-instructions.s
+++ b/test/MC/ARM/basic-arm-instructions.s
@@ -388,9 +388,9 @@ Lforward:
blx #16212288
@ CHECK: bl _bar @ encoding: [A,A,A,0xeb]
-@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
+@ CHECK: @ fixup A - offset: 0, value: _bar, kind: fixup_arm_bl
@ CHECK: blx _bar @ encoding: [A,A,A,0xfa]
- @ fixup A - offset: 0, value: _bar, kind: fixup_arm_uncondbranch
+ @ fixup A - offset: 0, value: _bar, kind: fixup_arm_blx
@ CHECK: blls #28634268 @ encoding: [0x27,0x3b,0x6d,0x9b]
@ CHECK: blx #32424576 @ encoding: [0xa0,0xb0,0x7b,0xfa]
@ CHECK: blx #16212288 @ encoding: [0x50,0xd8,0x3d,0xfa]