Slightly saner handling of thumb branches.

The generic infrastructure already did a lot of work to decide if the
fixup value is know or not. It doesn't make sense to reimplement a very
basic case: same fragment.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252090 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2015-11-04 23:00:39 +00:00
parent aa1e5aa9df
commit dc486f1719
3 changed files with 42 additions and 9 deletions

View File

@ -620,6 +620,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm,
const MCValue &Target, uint64_t &Value, const MCValue &Target, uint64_t &Value,
bool &IsResolved) { bool &IsResolved) {
const MCSymbolRefExpr *A = Target.getSymA(); const MCSymbolRefExpr *A = Target.getSymA();
const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
// Some fixups to thumb function symbols need the low bit (thumb bit) // Some fixups to thumb function symbols need the low bit (thumb bit)
// twiddled. // twiddled.
if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 && if ((unsigned)Fixup.getKind() != ARM::fixup_arm_ldst_pcrel_12 &&
@ -628,18 +629,23 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm,
(unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 && (unsigned)Fixup.getKind() != ARM::fixup_thumb_adr_pcrel_10 &&
(unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 && (unsigned)Fixup.getKind() != ARM::fixup_t2_adr_pcrel_12 &&
(unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) { (unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) {
if (A) { if (Sym) {
const MCSymbol &Sym = A->getSymbol(); if (Asm.isThumbFunc(Sym))
if (Asm.isThumbFunc(&Sym))
Value |= 1; Value |= 1;
} }
} }
// For Thumb1 BL instruction, it is possible to be a long jump between if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) {
// the basic blocks of the same function. Thus, we would like to resolve assert(Sym && "How did we resolve this?");
// the offset when the destination has the same MCFragment.
if (A && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { // If the symbol is external the linker will handle it.
const MCSymbol &Sym = A->getSymbol(); // FIXME: Should we handle it as an optimization?
IsResolved = (Sym.getFragment() == DF); if (Sym->isExternal()) {
IsResolved = false;
} else {
if (Value >= 0x400004)
Asm.getContext().reportFatalError(Fixup.getLoc(),
"out of range for branch");
}
} }
// We must always generate a relocation for BL/BLX instructions if we have // 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 // a symbol to reference, as the linker relies on knowing the destination

View File

@ -0,0 +1,7 @@
@ RUN: not llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o %t 2>&1 | FileCheck %s
bl end
.space 0x400000
end:
@ CHECK: out of range for branch

View File

@ -0,0 +1,20 @@
@ RUN: llvm-mc < %s -triple thumbv5-linux-gnueabi -filetype=obj -o - \
@ RUN: | llvm-readobj -r | FileCheck %s
bl end
.space 0x3fffff
end:
bl end2
.space 0x3fffff
.global end2
end2:
bl end3
.space 0x400000
.global end3
end3:
@ CHECK: 0x400003 R_ARM_THM_CALL end2 0x0
@ CHECK: 0x800006 R_ARM_THM_CALL end3 0x0