diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index b841ddb9f5a..285e07c0d62 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -17,12 +17,15 @@ namespace llvm { class MCAsmLayout; +class MCAssembler; class MCELFObjectTargetWriter; class MCFixup; +class MCFragment; class MCInst; class MCInstFragment; class MCObjectWriter; class MCSection; +class MCValue; template class SmallVectorImpl; class raw_ostream; @@ -87,6 +90,13 @@ public: /// getFixupKindInfo - Get information on a fixup kind. virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; + /// processFixupValue - Target hook to adjust the literal value of a fixup + /// if necessary. The default does nothing. + virtual void processFixupValue(const MCAssembler &Asm, + const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value) {} + /// @} /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 1cb97ce61fc..e3cfae84ee0 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -273,13 +273,10 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, Value = Target.getConstant(); - bool IsThumb = false; if (const MCSymbolRefExpr *A = Target.getSymA()) { const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); if (Sym.isDefined()) Value += Layout.getSymbolOffset(&getSymbolData(Sym)); - if (isThumbFunc(&Sym)) - IsThumb = true; } if (const MCSymbolRefExpr *B = Target.getSymB()) { const MCSymbol &Sym = B->getSymbol().AliasedSymbol(); @@ -302,12 +299,8 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, Value -= Offset; } - // ARM fixups based from a thumb function address need to have the low - // bit set. The actual value is always at least 16-bit aligned, so the - // low bit is normally clear and available for use as an ISA flag for - // interworking. - if (IsThumb) - Value |= 1; + // Let the backend adjust the fixup value if necessary. + Backend.processFixupValue(*this, Layout, Fixup, DF, Target, Value); return IsResolved; } diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 7b3f966ea82..88fea5745d8 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -22,6 +22,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" @@ -101,6 +102,20 @@ public: return Infos[Kind - FirstTargetFixupKind]; } + /// processFixupValue - Target hook to process the literal value of a fixup + /// if necessary. + void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, + const MCFixup &Fixup, const MCFragment *DF, + MCValue &Target, uint64_t &Value) { + // Some fixups to thumb function symbols need the low bit (thumb bit) + // twiddled. + if (const MCSymbolRefExpr *A = Target.getSymA()) { + const MCSymbol &Sym = A->getSymbol().AliasedSymbol(); + if (Asm.isThumbFunc(&Sym)) + Value |= 1; + } + } + bool MayNeedRelaxation(const MCInst &Inst) const; bool fixupNeedsRelaxation(const MCFixup &Fixup,