mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-23 20:45:06 +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,
|
||||
bool &IsResolved) {
|
||||
const MCSymbolRefExpr *A = Target.getSymA();
|
||||
const MCSymbol *Sym = A ? &A->getSymbol() : nullptr;
|
||||
// Some fixups to thumb function symbols need the low bit (thumb bit)
|
||||
// twiddled.
|
||||
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_t2_adr_pcrel_12 &&
|
||||
(unsigned)Fixup.getKind() != ARM::fixup_arm_thumb_cp) {
|
||||
if (A) {
|
||||
const MCSymbol &Sym = A->getSymbol();
|
||||
if (Asm.isThumbFunc(&Sym))
|
||||
if (Sym) {
|
||||
if (Asm.isThumbFunc(Sym))
|
||||
Value |= 1;
|
||||
}
|
||||
}
|
||||
// For Thumb1 BL instruction, it is possible to be a long jump between
|
||||
// the basic blocks of the same function. Thus, we would like to resolve
|
||||
// the offset when the destination has the same MCFragment.
|
||||
if (A && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) {
|
||||
const MCSymbol &Sym = A->getSymbol();
|
||||
IsResolved = (Sym.getFragment() == DF);
|
||||
if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) {
|
||||
assert(Sym && "How did we resolve this?");
|
||||
|
||||
// If the symbol is external the linker will handle it.
|
||||
// FIXME: Should we handle it as an optimization?
|
||||
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
|
||||
// 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