ARM Fixups relative to thumb functions need to have the low bit of the value
authorJim Grosbach <grosbach@apple.com>
Tue, 14 Dec 2010 18:46:57 +0000 (18:46 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 14 Dec 2010 18:46:57 +0000 (18:46 +0000)
set for interworking to work properly. rdar://8755956

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121778 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCAssembler.h
lib/MC/MCAssembler.cpp
lib/MC/MCMachOStreamer.cpp

index 87891489d5993e86985c9d2620457d466d6887b3..ea250045ad73bcf43210ef84d43a5ae2e5ad1d8b 100644 (file)
@@ -11,6 +11,7 @@
 #define LLVM_MC_MCASSEMBLER_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/ilist.h"
 #include "llvm/ADT/ilist_node.h"
@@ -662,6 +663,15 @@ private:
 
   std::vector<IndirectSymbolData> IndirectSymbols;
 
+  /// The set of function symbols for which a .thumb_func directive has
+  /// been seen.
+  //
+  // FIXME: We really would like this in target specific code rather than
+  // here. Maybe when the relocation stuff moves to target specific,
+  // this can go with it? The streamer would need some target specific
+  // refactoring too.
+  SmallPtrSet<const MCSymbol*, 64> ThumbFuncs;
+
   unsigned RelaxAll : 1;
   unsigned SubsectionsViaSymbols : 1;
 
@@ -738,6 +748,14 @@ public:
   void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout,
                         MCObjectWriter *OW) const;
 
+  /// Check whether a given symbol has been flagged with .thumb_func.
+  bool isThumbFunc(const MCSymbol *Func) const {
+    return ThumbFuncs.count(Func);
+  }
+
+  /// Flag a function symbol as the target of a .thumb_func directive.
+  void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); }
+
 public:
   /// Construct a new assembler instance.
   ///
index 319f04cfe707981409fb71909271977118dfa561..5bc477d7bccf73c30c196f699ef4169025a90475 100644 (file)
@@ -235,12 +235,15 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
   bool IsPCRel = Emitter.getFixupKindInfo(
     Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel;
   bool IsResolved = true;
+  bool IsThumb = false;
   if (const MCSymbolRefExpr *A = Target.getSymA()) {
     const MCSymbol &Sym = A->getSymbol().AliasedSymbol();
     if (Sym.isDefined())
       Value += Layout.getSymbolOffset(&getSymbolData(Sym));
     else
       IsResolved = false;
+    if (isThumbFunc(&Sym))
+      IsThumb = true;
   }
   if (const MCSymbolRefExpr *B = Target.getSymB()) {
     const MCSymbol &Sym = B->getSymbol().AliasedSymbol();
@@ -263,6 +266,13 @@ bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer,
       Value -= Layout.getFragmentOffset(DF) + Fixup.getOffset();
   }
 
+  // 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;
+
   return IsResolved;
 }
 
index df1e7d8e2b5ac35190d5b8977372694b4bb17897..0e21f4d00c14271f6ef19b9634747dda8c77dd1a 100644 (file)
@@ -142,6 +142,10 @@ void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
 
 void MCMachOStreamer::EmitThumbFunc(MCSymbol *Func) {
   // FIXME: Flag the function ISA as thumb with DW_AT_APPLE_isa.
+
+  // Remember that the function is a thumb function. Fixup and relocation
+  // values will need adjusted.
+  getAssembler().setIsThumbFunc(Func);
 }
 
 void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {