mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-19 09:57:42 +00:00
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:
parent
aa1e5aa9df
commit
dc486f1719
@ -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
|
||||||
|
7
test/MC/ARM/thumb-branches-err.s
Normal file
7
test/MC/ARM/thumb-branches-err.s
Normal 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
|
20
test/MC/ARM/thumb-branches.s
Normal file
20
test/MC/ARM/thumb-branches.s
Normal 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
|
Loading…
Reference in New Issue
Block a user