diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2017-06-23 22:52:36 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2017-06-23 22:52:36 +0000 |
commit | 801b42de3132c4927b2e4a66baefbbce9143f66a (patch) | |
tree | 86100627c3fd311bbbee1176f41cc6ffab89de64 /llvm/lib/Target/ARM | |
parent | f6242c3e90023baf746bca765f843e6c7f0d5660 (diff) | |
download | bcm5719-llvm-801b42de3132c4927b2e4a66baefbbce9143f66a.tar.gz bcm5719-llvm-801b42de3132c4927b2e4a66baefbbce9143f66a.zip |
ARM: move some logic from processFixupValue to applyFixup.
processFixupValue is called on every relaxation iteration. applyFixup
is only called once at the very end. applyFixup is then the correct
place to do last minute changes and value checks.
While here, do proper range checks again for fixup_arm_thumb_bl. We
used to do it, but dropped because of thumb2. We now do it again, but
use the thumb2 range.
llvm-svn: 306177
Diffstat (limited to 'llvm/lib/Target/ARM')
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h | 6 |
2 files changed, 35 insertions, 23 deletions
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index e06f23a91f5..46fb6caa0d2 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -358,11 +358,27 @@ static uint32_t joinHalfWords(uint32_t FirstHalf, uint32_t SecondHalf, return Value; } -unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, +unsigned ARMAsmBackend::adjustFixupValue(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target, uint64_t Value, bool IsPCRel, MCContext &Ctx, bool IsLittleEndian, bool IsResolved) const { unsigned Kind = Fixup.getKind(); + + // MachO tries to make .o files that look vaguely pre-linked, so for MOVW/MOVT + // and .word relocations they put the Thumb bit into the addend if possible. + // Other relocation types don't want this bit though (branches couldn't encode + // it if it *was* present, and no other relocations exist) and it can + // interfere with checking valid expressions. + if (const MCSymbolRefExpr *A = Target.getSymA()) { + if (A->hasSubsectionsViaSymbols() && Asm.isThumbFunc(&A->getSymbol()) && + (Kind == FK_Data_4 || Kind == ARM::fixup_arm_movw_lo16 || + Kind == ARM::fixup_arm_movt_hi16 || Kind == ARM::fixup_t2_movw_lo16 || + Kind == ARM::fixup_t2_movt_hi16)) + Value |= 1; + } + switch (Kind) { default: Ctx.reportError(Fixup.getLoc(), "bad relocation fixup type"); @@ -505,6 +521,13 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return swapHalfWords(out, IsLittleEndian); } case ARM::fixup_arm_thumb_bl: { + // FIXME: We get both thumb1 and thumb2 in here, so we can only check for + // the less strict thumb2 value. + if (!isInt<26>(Value - 4)) { + Ctx.reportError(Fixup.getLoc(), "Relocation out of range"); + return 0; + } + // The value doesn't encode the low bit (always zero) and is offset by // four. The 32-bit immediate value is encoded as // imm32 = SignExtend(S:I1:I2:imm10:imm11:0) @@ -724,21 +747,6 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, const MCSymbolRefExpr *A = Target.getSymA(); const MCSymbol *Sym = A ? &A->getSymbol() : nullptr; const unsigned FixupKind = Fixup.getKind() ; - // MachO (the only user of "Value") tries to make .o files that look vaguely - // pre-linked, so for MOVW/MOVT and .word relocations they put the Thumb bit - // into the addend if possible. Other relocation types don't want this bit - // though (branches couldn't encode it if it *was* present, and no other - // relocations exist) and it can interfere with checking valid expressions. - if (FixupKind == FK_Data_4 || - FixupKind == ARM::fixup_arm_movw_lo16 || - FixupKind == ARM::fixup_arm_movt_hi16 || - FixupKind == ARM::fixup_t2_movw_lo16 || - FixupKind == ARM::fixup_t2_movt_hi16) { - if (Sym) { - if (Asm.isThumbFunc(Sym)) - Value |= 1; - } - } if (IsResolved && (unsigned)Fixup.getKind() == ARM::fixup_arm_thumb_bl) { assert(Sym && "How did we resolve this?"); @@ -747,7 +755,7 @@ void ARMAsmBackend::processFixupValue(const MCAssembler &Asm, // If the symbol is out of range, produce a relocation and hope the // linker can handle it. GNU AS produces an error in this case. - if (Sym->isExternal() || Value >= 0x400004) + if (Sym->isExternal()) IsResolved = false; } // Create relocations for unconditional branches to function symbols with @@ -876,11 +884,13 @@ static unsigned getFixupKindContainerSizeBytes(unsigned Kind) { } } -void ARMAsmBackend::applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data, - uint64_t Value, bool IsPCRel, - MCContext &Ctx) const { +void ARMAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, + MutableArrayRef<char> Data, uint64_t Value, + bool IsPCRel, MCContext &Ctx) const { unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind()); - Value = adjustFixupValue(Fixup, Value, IsPCRel, Ctx, IsLittleEndian, true); + Value = adjustFixupValue(Asm, Fixup, Target, Value, IsPCRel, Ctx, + IsLittleEndian, true); if (!Value) return; // Doesn't change encoding. diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h index cb5e6e2eaef..54cb162ee11 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -45,11 +45,13 @@ public: const MCValue &Target, uint64_t &Value, bool &IsResolved) override; - unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, bool IsPCRel, + unsigned adjustFixupValue(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, uint64_t Value, bool IsPCRel, MCContext &Ctx, bool IsLittleEndian, bool IsResolved) const; - void applyFixup(const MCFixup &Fixup, MutableArrayRef<char> Data, + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, bool IsPCRel, MCContext &Ctx) const override; unsigned getRelaxedOpcode(unsigned Op) const; |