mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-30 14:50:30 +00:00
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 llvm-svn: 151571
This commit is contained in:
parent
20ba865302
commit
02bf78f5ca
@ -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) {}
|
||||
|
||||
/// @}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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.
|
||||
@ -591,17 +593,22 @@ getARMBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
|
||||
return MO.getImm() >> 2;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user