MC: Move assembler-backend's fixup list into the fragment.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 11 Feb 2010 21:29:46 +0000 (21:29 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 11 Feb 2010 21:29:46 +0000 (21:29 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@95926 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 9d3efa7ee65cae0e02de56a03a80179ab02aab53..562a5210ad8287fa3874ba7ea5b01f142222ea8f 100644 (file)
@@ -31,9 +31,6 @@ class MCSymbol;
 /// which needs to be rewritten. This region will either be rewritten by the
 /// assembler or cause a relocation entry to be generated.
 struct MCAsmFixup {
-  /// Fragment - The fragment containing the fixup.
-  MCFragment *Fragment;
-  
   /// Offset - The offset inside the fragment which needs to be rewritten.
   uint64_t Offset;
 
@@ -49,16 +46,18 @@ struct MCAsmFixup {
   uint64_t FixedValue;
 
 public:
-  MCAsmFixup(MCFragment &_Fragment, uint64_t _Offset, const MCExpr &_Value,
-             unsigned _Size) 
-    : Fragment(&_Fragment), Offset(_Offset), Value(&_Value), Size(_Size),
-      FixedValue(0) {}
+  MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, unsigned _Size) 
+    : Offset(_Offset), Value(&_Value), Size(_Size), FixedValue(0) {}
 };
 
 class MCFragment : public ilist_node<MCFragment> {
   MCFragment(const MCFragment&);     // DO NOT IMPLEMENT
   void operator=(const MCFragment&); // DO NOT IMPLEMENT
 
+public:
+  typedef std::vector<MCAsmFixup>::const_iterator const_fixup_iterator;
+  typedef std::vector<MCAsmFixup>::iterator fixup_iterator;
+
 public:
   enum FragmentType {
     FT_Data,
@@ -86,6 +85,11 @@ private:
   /// FileSize - The file size of this section. This is ~0 until initialized.
   uint64_t FileSize;
 
+  /// Fixups - The list of fixups in this fragment.
+  //
+  // FIXME: This should be sunk into MCDataFragment.
+  std::vector<MCAsmFixup> Fixups;
+
   /// @}
 
 protected:
@@ -107,6 +111,39 @@ public:
     return 0;
   }
 
+  /// @name Fixup Access
+  /// @{
+
+  /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
+  /// Offset.
+  ///
+  /// If multiple fixups exist for the same fragment and offset it is undefined
+  /// which one is returned.
+  //
+  // FIXME: This isn't horribly slow in practice, but there are much nicer
+  // solutions to applying the fixups. This will be fixed by sinking fixups into
+  // data fragments exclusively.
+  const MCAsmFixup *LookupFixup(uint64_t Offset) const {
+    for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
+      if (Fixups[i].Offset == Offset)
+        return &Fixups[i];
+    return 0;
+  }
+
+  std::vector<MCAsmFixup> &getFixups() {
+    return Fixups;
+  }
+
+  fixup_iterator fixup_begin() {
+    return Fixups.begin();
+  }
+
+  fixup_iterator fixup_end() {
+    return Fixups.end();
+  }
+
+  size_t fixup_size() const { return Fixups.size(); }
+
   /// @name Assembler Backend Support
   /// @{
   //
@@ -313,14 +350,13 @@ class MCSectionData : public ilist_node<MCSectionData> {
   void operator=(const MCSectionData&); // DO NOT IMPLEMENT
 
 public:
-
   typedef iplist<MCFragment> FragmentListType;
 
   typedef FragmentListType::const_iterator const_iterator;
   typedef FragmentListType::iterator iterator;
 
-  typedef std::vector<MCAsmFixup>::const_iterator const_fixup_iterator;
-  typedef std::vector<MCAsmFixup>::iterator fixup_iterator;
+  typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
+  typedef FragmentListType::reverse_iterator reverse_iterator;
 
 private:
   iplist<MCFragment> Fragments;
@@ -345,12 +381,6 @@ private:
   /// initialized.
   uint64_t FileSize;
 
-  /// LastFixupLookup - Cache for the last looked up fixup.
-  mutable unsigned LastFixupLookup;
-
-  /// Fixups - The list of fixups in this section.
-  std::vector<MCAsmFixup> Fixups;
-
   /// HasInstructions - Whether this section has had instructions emitted into
   /// it.
   unsigned HasInstructions : 1;
@@ -379,27 +409,15 @@ public:
   iterator end() { return Fragments.end(); }
   const_iterator end() const { return Fragments.end(); }
 
-  size_t size() const { return Fragments.size(); }
-
-  bool empty() const { return Fragments.empty(); }
+  reverse_iterator rbegin() { return Fragments.rbegin(); }
+  const_reverse_iterator rbegin() const { return Fragments.rbegin(); }
 
-  /// @}
-  /// @name Fixup Access
-  /// @{
+  reverse_iterator rend() { return Fragments.rend(); }
+  const_reverse_iterator rend() const { return Fragments.rend(); }
 
-  std::vector<MCAsmFixup> &getFixups() {
-    return Fixups;
-  }
-
-  fixup_iterator fixup_begin() {
-    return Fixups.begin();
-  }
-
-  fixup_iterator fixup_end() {
-    return Fixups.end();
-  }
+  size_t size() const { return Fragments.size(); }
 
-  size_t fixup_size() const { return Fixups.size(); }
+  bool empty() const { return Fragments.empty(); }
 
   /// @}
   /// @name Assembler Backend Support
@@ -407,17 +425,6 @@ public:
   //
   // FIXME: This could all be kept private to the assembler implementation.
 
-  /// LookupFixup - Look up the fixup for the given \arg Fragment and \arg
-  /// Offset.
-  ///
-  /// If multiple fixups exist for the same fragment and offset it is undefined
-  /// which one is returned.
-  //
-  // FIXME: This isn't horribly slow in practice, but there are much nicer
-  // solutions to applying the fixups.
-  const MCAsmFixup *LookupFixup(const MCFragment *Fragment,
-                                uint64_t Offset) const;
-
   uint64_t getAddress() const { 
     assert(Address != ~UINT64_C(0) && "Address not set!");
     return Address;
index 682b505e3474b39bb08b815cc591af0e8ddfd364..9afc169fcf4a65d936d48429fe5591a4dde3aea9 100644 (file)
@@ -402,12 +402,12 @@ public:
     uint32_t Word0;
     uint32_t Word1;
   };
-  void ComputeScatteredRelocationInfo(MCAssembler &Asm,
+  void ComputeScatteredRelocationInfo(MCAssembler &Asm, MCFragment &Fragment,
                                       MCAsmFixup &Fixup,
                                       const MCValue &Target,
                              DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
                                      std::vector<MachRelocationEntry> &Relocs) {
-    uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+    uint32_t Address = Fragment.getOffset() + Fixup.Offset;
     unsigned IsPCRel = 0;
     unsigned Type = RIT_Vanilla;
 
@@ -453,7 +453,7 @@ public:
     }
   }
 
-  void ComputeRelocationInfo(MCAssembler &Asm,
+  void ComputeRelocationInfo(MCAssembler &Asm, MCFragment &Fragment,
                              MCAsmFixup &Fixup,
                              DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
                              std::vector<MachRelocationEntry> &Relocs) {
@@ -466,11 +466,11 @@ public:
     if (Target.getSymB() ||
         (Target.getSymA() && !Target.getSymA()->isUndefined() &&
          Target.getConstant()))
-      return ComputeScatteredRelocationInfo(Asm, Fixup, Target,
+      return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target,
                                             SymbolMap, Relocs);
 
     // See <reloc.h>.
-    uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
+    uint32_t Address = Fragment.getOffset() + Fixup.Offset;
     uint32_t Value = 0;
     unsigned Index = 0;
     unsigned IsPCRel = 0;
@@ -766,17 +766,19 @@ public:
     // is written.
     std::vector<MachRelocationEntry> RelocInfos;
     uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
-    for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
-         ++it) {
+    for (MCAssembler::iterator it = Asm.begin(),
+           ie = Asm.end(); it != ie; ++it) {
       MCSectionData &SD = *it;
 
       // The assembler writes relocations in the reverse order they were seen.
       //
       // FIXME: It is probably more complicated than this.
       unsigned NumRelocsStart = RelocInfos.size();
-      for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
-        ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
-                              RelocInfos);
+      for (MCSectionData::reverse_iterator it2 = SD.rbegin(),
+             ie2 = SD.rend(); it2 != ie2; ++it2)
+        for (unsigned i = 0, e = it2->fixup_size(); i != e; ++i)
+          ComputeRelocationInfo(Asm, *it2, it2->getFixups()[e - i - 1],
+                                SymbolMap, RelocInfos);
 
       unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
       uint64_t SectionStart = SectionDataStart + SD.getAddress();
@@ -905,35 +907,12 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
     Address(~UINT64_C(0)),
     Size(~UINT64_C(0)),
     FileSize(~UINT64_C(0)),
-    LastFixupLookup(~0),
     HasInstructions(false)
 {
   if (A)
     A->getSectionList().push_back(this);
 }
 
-const MCAsmFixup *MCSectionData::LookupFixup(const MCFragment *Fragment,
-                                             uint64_t Offset) const {
-  // Use a one level cache to turn the common case of accessing the fixups in
-  // order into O(1) instead of O(N).
-  unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
-  if (i >= End)
-    i = 0;
-  while (Count--) {
-    const MCAsmFixup &F = Fixups[i];
-    if (F.Fragment == Fragment && F.Offset == Offset) {
-      LastFixupLookup = i;
-      return &F;
-    }
-
-    ++i;
-    if (i == End)
-      i = 0;
-  }
-
-  return 0;
-}
-
 /* *** */
 
 MCSymbolData::MCSymbolData() : Symbol(0) {}
@@ -997,10 +976,13 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
         break;
 
       // Otherwise, add fixups for the values.
-      for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
-        MCAsmFixup Fix(F, i*FF.getValueSize(), FF.getValue(),FF.getValueSize());
-        SD.getFixups().push_back(Fix);
-      }
+      //
+      // FIXME: What we want to do here is lower this to a data fragment once we
+      // realize it will need relocations. This means that the only place we
+      // need to worry about relocations and fixing is on data fragments.
+      for (uint64_t i = 0, e = FF.getCount(); i != e; ++i)
+        FF.getFixups().push_back(MCAsmFixup(i*FF.getValueSize(), FF.getValue(),
+                                            FF.getValueSize()));
       break;
     }
 
@@ -1105,9 +1087,9 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
       if (!Target.isAbsolute()) {
         // Find the fixup.
         //
-        // FIXME: Find a better way to write in the fixes.
-        const MCAsmFixup *Fixup =
-          F.getParent()->LookupFixup(&F, i * FF.getValueSize());
+        // FIXME: Find a better way to write in the fixes (move to
+        // MCDataFragment).
+        const MCAsmFixup *Fixup = FF.LookupFixup(i * FF.getValueSize());
         assert(Fixup && "Missing fixup for fill value!");
         Value = Fixup->FixedValue;
       }