[lld] r174658 - add changes for layoutafter/layoutbefore/ingroup/layoutpass and test cases

Shankar Easwaran shankare at codeaurora.org
Thu Feb 7 12:16:13 PST 2013


Author: shankare
Date: Thu Feb  7 14:16:12 2013
New Revision: 174658

URL: http://llvm.org/viewvc/llvm-project?rev=174658&view=rev
Log:
add changes for layoutafter/layoutbefore/ingroup/layoutpass and test cases

Added:
    lld/trunk/include/lld/Passes/
    lld/trunk/include/lld/Passes/LayoutPass.h
    lld/trunk/lib/Passes/LayoutPass.cpp
    lld/trunk/test/ingroup-test-big.objtxt
    lld/trunk/test/ingroup-test-loop.objtxt
    lld/trunk/test/ingroup-test-with-layout-after.objtxt
    lld/trunk/test/ingroup-test.objtxt
    lld/trunk/test/layoutafter-test.objtxt
    lld/trunk/test/layoutbefore-test.objtxt
Removed:
    lld/trunk/lib/Passes/OrderPass.cpp
Modified:
    lld/trunk/include/lld/Core/Pass.h
    lld/trunk/include/lld/Core/Reference.h
    lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
    lld/trunk/lib/Passes/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/Atoms.h
    lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
    lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
    lld/trunk/lib/ReaderWriter/ELF/File.h
    lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
    lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
    lld/trunk/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
    lld/trunk/test/elf/phdr.objtxt
    lld/trunk/test/elf/rodata.objtxt
    lld/trunk/test/elf/sections.objtxt
    lld/trunk/test/section-position.objtxt
    lld/trunk/tools/lld-core/TestingHelpers.hpp
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/include/lld/Core/Pass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Pass.h?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Pass.h (original)
+++ lld/trunk/include/lld/Core/Pass.h Thu Feb  7 14:16:12 2013
@@ -11,6 +11,8 @@
 #define LLD_CORE_PASS_H_
 
 #include "lld/Core/Atom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/range.h"
 #include "lld/Core/Reference.h"
 
 #include <vector>
@@ -111,16 +113,6 @@ public:
   virtual const DefinedAtom *makeGOTEntry(const Atom &target) = 0;
 };
 
-/// Pass for sorting atoms.
-class OrderPass : public Pass {
-public:
-  OrderPass() : Pass() {}
-  
-  /// Sorts atoms in mergedFile by content type then by command line order.
-  virtual void perform(MutableFile &mergedFile);
-};
-
-
 } // namespace lld
 
 #endif // LLD_CORE_PASS_H_

Modified: lld/trunk/include/lld/Core/Reference.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Reference.h (original)
+++ lld/trunk/include/lld/Core/Reference.h Thu Feb  7 14:16:12 2013
@@ -11,6 +11,7 @@
 #define LLD_CORE_REFERENCES_H_
 
 #include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringSwitch.h"
 
 namespace lld {
 
@@ -33,6 +34,13 @@ public:
   /// Negative kind values are architecture independent.
   typedef int32_t Kind;
 
+  enum {
+    kindInGroup = -3,
+    kindLayoutAfter = -2,
+    kindLayoutBefore = -1,
+    kindTargetLow = 0
+  };
+
   // A value to be added to the value of a target
   typedef int64_t Addend;
 
@@ -43,6 +51,30 @@ public:
   /// hence the reference kind.
   virtual void setKind(Kind) = 0;
 
+  virtual StringRef kindToString() const {
+    switch (kind()) {
+    case kindLayoutBefore:
+      return "layout-before";
+    case kindLayoutAfter:
+      return "layout-after";
+    case kindInGroup:
+      return "in-group";
+    default:
+      return "unknown";
+    }
+  }
+
+  virtual int32_t stringToKind(StringRef kindString) const {
+    if (kindString == "in-group")
+      return kindInGroup;
+    else if (kindString == "layout-before")
+      return kindLayoutBefore;
+    else if (kindString == "layout-after")
+      return kindLayoutAfter;
+    assert(0 && "unknown relocation kind");
+    return -1;
+  }
+
   /// If the reference is a fixup in the Atom, then this returns the
   /// byte offset into the Atom's content to do the fix up.
   virtual uint64_t offsetInAtom() const = 0;
@@ -72,7 +104,6 @@ protected:
   virtual ~Reference() {}
 };
 
-
 } // namespace lld
 
 #endif // LLD_CORE_REFERENCES_H_

Added: lld/trunk/include/lld/Passes/LayoutPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Passes/LayoutPass.h?rev=174658&view=auto
==============================================================================
--- lld/trunk/include/lld/Passes/LayoutPass.h (added)
+++ lld/trunk/include/lld/Passes/LayoutPass.h Thu Feb  7 14:16:12 2013
@@ -0,0 +1,78 @@
+//===------ Passes/LayoutPass.h - Handles Layout of atoms ------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_PASSES_LAYOUT_PASS_H
+#define LLD_PASSES_LAYOUT_PASS_H
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Pass.h"
+#include "lld/Core/range.h"
+#include "lld/Core/Reference.h"
+
+#include "llvm/ADT/DenseMap.h"
+
+#include <map>
+#include <vector>
+
+namespace lld {
+class DefinedAtom;
+class MutableFile;
+
+/// This linker pass does the layout of the atoms. The pass is done after the 
+/// order their .o files were found on the command line, then by order of the
+/// atoms (address) in the .o file.  But some atoms have a prefered location
+/// in their section (such as pinned to the start or end of the section), so
+/// the sort must take that into account too.
+class LayoutPass : public Pass {
+public:
+
+  // Compare and Sort Atoms by their ordinals
+  class CompareAtoms {
+  public:
+    CompareAtoms(const LayoutPass &pass) : _layout(pass) {}
+    bool operator()(const DefinedAtom *left, const DefinedAtom *right);
+  private:
+    const LayoutPass &_layout;
+  };
+
+  LayoutPass() : Pass(), _compareAtoms(*this) {}
+
+  /// Sorts atoms in mergedFile by content type then by command line order.
+  virtual void perform(MutableFile &mergedFile);
+
+  virtual ~LayoutPass() {}
+
+private:
+  // Build the followOn atoms chain as specified by the kindLayoutAfter 
+  // reference type 
+  void buildFollowOnTable(MutableFile::DefinedAtomRange &range);
+
+  // Build the followOn atoms chain as specified by the kindInGroup
+  // reference type 
+  void buildInGroupTable(MutableFile::DefinedAtomRange &range);
+
+  // Build the PrecededBy Table as specified by the kindLayoutBefore
+  // reference type 
+  void buildPrecededByTable(MutableFile::DefinedAtomRange &range);
+
+  // Build a map of Atoms to ordinals for sorting the atoms 
+  void buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range);
+
+  typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
+  typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT;
+  AtomToAtomT _followOnNexts;
+  AtomToAtomT _followOnRoots;
+  AtomToOrdinalT _ordinalOverrideMap;
+  CompareAtoms _compareAtoms;
+};
+
+} // namespace lld
+
+#endif // LLD_PASSES_LAYOUT_PASS_H

Modified: lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFTargetInfo.h Thu Feb  7 14:16:12 2013
@@ -11,6 +11,8 @@
 #define LLD_READER_WRITER_ELF_TARGET_INFO_H
 
 #include "lld/Core/LinkerOptions.h"
+#include "lld/Core/PassManager.h"
+#include "lld/Core/Pass.h"
 #include "lld/Core/TargetInfo.h"
 #include "lld/ReaderWriter/Reader.h"
 #include "lld/ReaderWriter/Writer.h"
@@ -59,6 +61,8 @@ public:
     return static_cast<lld::elf::TargetHandler<ELFT> &>(*_targetHandler.get());
   }
 
+  virtual void addPasses(PassManager &pm) const;
+
 protected:
   std::unique_ptr<TargetHandlerBase> _targetHandler;
   mutable std::unique_ptr<Reader> _reader;

Modified: lld/trunk/lib/Passes/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/CMakeLists.txt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/Passes/CMakeLists.txt (original)
+++ lld/trunk/lib/Passes/CMakeLists.txt Thu Feb  7 14:16:12 2013
@@ -1,5 +1,5 @@
 add_lld_library(lldPasses
   GOTPass.cpp
-  OrderPass.cpp
   StubsPass.cpp
+  LayoutPass.cpp
   )

Added: lld/trunk/lib/Passes/LayoutPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/LayoutPass.cpp?rev=174658&view=auto
==============================================================================
--- lld/trunk/lib/Passes/LayoutPass.cpp (added)
+++ lld/trunk/lib/Passes/LayoutPass.cpp Thu Feb  7 14:16:12 2013
@@ -0,0 +1,386 @@
+//===- Passes/LayoutPass.cpp - Layout atoms -------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Passes/LayoutPass.h"
+
+using namespace lld;
+
+/// The function compares atoms by sorting atoms in the following order
+/// a) Sorts atoms with the same permissions
+/// b) Sorts atoms with the same content Type
+/// c) Sorts atoms by Section position preference
+/// d) Sorts atoms by how they follow / precede each atom
+/// e) Sorts atoms on how they appear using File Ordinality
+/// f) Sorts atoms on how they appear within the File
+bool LayoutPass::CompareAtoms::operator()(const DefinedAtom *left,
+                                          const DefinedAtom *right) {
+  if (left == right)
+    return false;
+
+  // Sort same permissions together.
+  DefinedAtom::ContentPermissions leftPerms = left->permissions();
+  DefinedAtom::ContentPermissions rightPerms = right->permissions();
+  if (leftPerms != rightPerms)
+    return leftPerms < rightPerms;
+
+  // Sort same content types together.
+  DefinedAtom::ContentType leftType = left->contentType();
+  DefinedAtom::ContentType rightType = right->contentType();
+  if (leftType != rightType)
+    return leftType < rightType;
+
+  // TO DO: Sort atoms in customs sections together.
+
+  // Sort by section position preference.
+  DefinedAtom::SectionPosition leftPos = left->sectionPosition();
+  DefinedAtom::SectionPosition rightPos = right->sectionPosition();
+  bool leftSpecialPos = (leftPos != DefinedAtom::sectionPositionAny);
+  bool rightSpecialPos = (rightPos != DefinedAtom::sectionPositionAny);
+  if (leftSpecialPos || rightSpecialPos) {
+    if (leftPos != rightPos)
+      return leftPos < rightPos;
+  }
+
+  AtomToOrdinalT::const_iterator lPos = _layout._ordinalOverrideMap.find(left);
+  AtomToOrdinalT::const_iterator rPos = _layout._ordinalOverrideMap.find(right);
+  AtomToOrdinalT::const_iterator end = _layout._ordinalOverrideMap.end();
+  if (lPos != end) {
+    if (rPos != end) {
+      // both left and right are overridden, so compare overridden ordinals
+      return lPos->second < rPos->second;
+    } else {
+      // left is overridden and right is not, so left < right
+      return true;
+    }
+  } else {
+    if (rPos != end) {
+      // right is overridden and left is not, so right < left
+      return false;
+    } else {
+      // neither are overridden, 
+      // fall into default sorting below
+    }
+  }
+
+  // Sort by .o order.
+  const File *leftFile = &left->file();
+  const File *rightFile = &right->file();
+  if (leftFile != rightFile)
+    return leftFile->ordinal() < rightFile->ordinal();
+
+  // Sort by atom order with .o file.
+  uint64_t leftOrdinal = left->ordinal();
+  uint64_t rightOrdinal = right->ordinal();
+  if (leftOrdinal != rightOrdinal)
+    return leftOrdinal < rightOrdinal;
+
+  return false;
+}
+
+/// This pass builds the followon tables described by two DenseMaps
+/// followOnRoots and followonNexts.
+/// The followOnRoots map contains a mapping of a DefinedAtom to its root
+/// The followOnNexts map contains a mapping of what DefinedAtom follows the
+/// current Atom
+/// The algorithm follows a very simple approach
+/// a) If the atom is first seen, then make that as the root atom
+/// b) The targetAtom which this Atom contains, has the root thats set to the 
+///    root of the current atom
+/// c) If the targetAtom is part of a different tree and the root of the
+///    targetAtom is itself, Chain all the atoms that are contained in the tree
+///    to the current Tree
+/// d) If the targetAtom is part of a different chain and the root of the
+///    targetAtom until the targetAtom has all atoms of size 0, then chain the
+///    targetAtoms and its tree to the current chain
+void LayoutPass::buildFollowOnTable(MutableFile::DefinedAtomRange &range) {
+  for (auto ai : range) {
+    for (const Reference *r : *ai) {
+      if (r->kind() == lld::Reference::kindLayoutAfter) {
+        const DefinedAtom *targetAtom = llvm::dyn_cast<DefinedAtom>(r->target());
+        _followOnNexts[ai] = targetAtom;
+        // If we find a followon for the first time, lets make that
+        // atom as the root atom
+        if (_followOnRoots.count(ai) == 0) {
+          _followOnRoots[ai] = ai;
+        }
+        // If the targetAtom is not a root of any chain, lets make 
+        // the root of the targetAtom to the root of the current chain
+        auto iter = _followOnRoots.find(targetAtom);
+        if (iter == _followOnRoots.end()) {
+          _followOnRoots[targetAtom] = _followOnRoots[ai];
+        } else {
+          // The followon is part of another chain
+          if (iter->second == targetAtom) {
+            const DefinedAtom *a = targetAtom;
+            while (true) {
+              _followOnRoots[a] = _followOnRoots[ai];
+              // Set all the follow on's for the targetAtom to be
+              // the current root
+              AtomToAtomT::iterator targetFollowOnAtomsIter =
+                  _followOnNexts.find(a);
+
+              if (targetFollowOnAtomsIter != _followOnNexts.end())
+                a = targetFollowOnAtomsIter->second;
+              else
+                break;
+            }      // while true
+          } else { // the atom could be part of chain already
+                   // Get to the root of the chain
+            const DefinedAtom *a = _followOnRoots[targetAtom];
+            // Lets add to the chain only if the atoms that 
+            // appear before the targetAtom in the chain 
+            // are of size 0
+            bool foundNonZeroSizeAtom = false;
+            while (true) {
+              // Set all the follow on's for the targetAtom to be
+              // the current root
+              AtomToAtomT::iterator targetFollowOnAtomsIter =
+                  _followOnNexts.find(a);
+
+              if (targetFollowOnAtomsIter != _followOnNexts.end())
+                a = targetFollowOnAtomsIter->second;
+              else
+                break;
+
+              if (a->size() != 0) {
+                foundNonZeroSizeAtom = true;
+                break;
+              }
+              if (a == targetAtom)
+                break;
+            } // while true
+            if (foundNonZeroSizeAtom) {
+              // TODO: print warning that an impossible layout 
+              // is being desired by the user
+              // Continue to the next atom 
+              break;
+            }
+
+            _followOnNexts[ai] = _followOnRoots[targetAtom];
+            // Set the root of all atoms in the 
+            a = _followOnRoots[targetAtom];
+            while (true) {
+              _followOnRoots[a] = _followOnRoots[ai];
+              // Set all the follow on's for the targetAtom to be
+              // the current root
+              AtomToAtomT::iterator targetFollowOnAtomsIter =
+                  _followOnNexts.find(a);
+              if (targetFollowOnAtomsIter != _followOnNexts.end())
+                a = targetFollowOnAtomsIter->second;
+              else
+                break;
+            } // while true
+          }   // end else
+        }     // else
+      }       // kindLayoutAfter
+    }         // Reference
+  }           // range
+}
+
+/// This pass builds the followon tables using InGroup relationships
+/// The algorithm follows a very simple approach
+/// a) If the rootAtom is not part of any root, create a new root with the
+///    as the head
+/// b) If the current Atom root is not found, then make the current atoms root
+///    point to the rootAtom
+/// c) If the root of the current Atom is itself a root of some other tree
+///    make all the atoms in the chain point to the ingroup reference
+/// d) Check to see if the current atom is part of the chain from the rootAtom
+///    if not add the atom to the chain, so that the current atom is part of the
+///    the chain where the rootAtom is in
+void LayoutPass::buildInGroupTable(MutableFile::DefinedAtomRange &range) {
+  // This table would convert precededby references to follow on 
+  // references so that we have only one table 
+  for (auto ai : range) {
+    for (const Reference *r : *ai) {
+      if (r->kind() == lld::Reference::kindInGroup) {
+        const DefinedAtom *rootAtom = llvm::dyn_cast<DefinedAtom>(r->target());
+        // If the root atom is not part of any root
+        // create a new root 
+        if (_followOnRoots.count(rootAtom) == 0) {
+          _followOnRoots[rootAtom] = rootAtom;
+        }
+        // If the current Atom has not been seen yet and there is no root 
+        // that has been set, set the root of the atom to the targetAtom 
+        // as the targetAtom points to the ingroup root
+        auto iter = _followOnRoots.find(ai);
+        if (iter == _followOnRoots.end()) {
+          _followOnRoots[ai] = rootAtom;
+        }
+        else if (iter->second == ai) {
+          if (iter->second != rootAtom) {
+            const DefinedAtom *a = iter->second;
+            // Change all the followon next references to the ingroup reference root
+            while (true) {
+              _followOnRoots[a] = rootAtom;
+              // Set all the follow on's for the targetAtom to be
+              // the current root
+              AtomToAtomT::iterator targetFollowOnAtomsIter =
+                  _followOnNexts.find(a);
+              if (targetFollowOnAtomsIter != _followOnNexts.end())
+                a = targetFollowOnAtomsIter->second;
+              else
+                break;
+            } // while true
+          }
+        }
+        else {
+          // TODO : Flag an error that the root of the tree
+          // is different, Here is an example
+          // Say there are atoms
+          // chain 1 : a->b->c
+          // chain 2 : d->e->f
+          // and e,f have their ingroup reference as a
+          // this could happen only if the root of e,f that is d
+          // has root as 'a'
+          continue;
+        }
+
+        // Check if the current atom is part of the chain
+        bool isAtomInChain = false;
+        const DefinedAtom *lastAtom = rootAtom;
+        while (true) {
+          AtomToAtomT::iterator followOnAtomsIter = 
+                  _followOnNexts.find(lastAtom);
+          if (followOnAtomsIter != _followOnNexts.end()) {
+            lastAtom = followOnAtomsIter->second;
+            if (lastAtom == ai) {
+              isAtomInChain = true;
+              break;
+            }
+          }
+          else 
+            break;
+        } // findAtomInChain
+
+        if (!isAtomInChain) 
+          _followOnNexts[lastAtom] = ai;
+      }
+    }
+  }
+}
+
+/// This pass builds the followon tables using Preceded By relationships
+/// The algorithm follows a very simple approach
+/// a) If the targetAtom is not part of any root and the current atom is not
+///    part of any root, create a chain with the current atom as root and 
+///    the targetAtom as following the current atom
+/// b) Chain the targetAtom to the current Atom if the targetAtom is not part 
+///    of any chain and the currentAtom has no followOn's
+/// c) If the targetAtom is part of a different tree and the root of the
+///    targetAtom is itself, and if the current atom is not part of any root
+///    chain all the atoms together 
+/// d) If the current atom has no followon and the root of the targetAtom is 
+///    not equal to the root of the current atom(the targetAtom is not in the 
+///    same chain), chain all the atoms that are lead by the targetAtom into 
+///    the current chain
+void LayoutPass::buildPrecededByTable(MutableFile::DefinedAtomRange &range) {
+  // This table would convert precededby references to follow on 
+  // references so that we have only one table 
+  for (auto ai : range) {
+    for (const Reference *r : *ai) {
+      if (r->kind() == lld::Reference::kindLayoutBefore) {
+        const DefinedAtom *targetAtom = llvm::dyn_cast<DefinedAtom>(r->target());
+        // Is the targetAtom not chained
+        if (_followOnRoots.count(targetAtom) == 0) {
+          // Is the current atom not part of any root ?
+          if (_followOnRoots.count(ai) == 0) {
+            _followOnRoots[ai] = ai;
+            _followOnNexts[ai] = targetAtom;
+            _followOnRoots[targetAtom] = _followOnRoots[ai];
+          } else if (_followOnNexts.count(ai) == 0) {
+            // Chain the targetAtom to the current Atom
+            // if the currentAtom has no followon references
+            _followOnNexts[ai] = targetAtom;
+            _followOnRoots[targetAtom] = _followOnRoots[ai];
+          }
+        } else if (_followOnRoots.find(targetAtom)->second == targetAtom) {
+          // Is the targetAtom in chain with the targetAtom as the root ?
+          bool changeRoots = false;
+          if (_followOnRoots.count(ai) == 0) {
+            _followOnRoots[ai] = ai;
+            _followOnNexts[ai] = targetAtom;
+            _followOnRoots[targetAtom] = _followOnRoots[ai];
+            changeRoots = true;
+          } else if (_followOnNexts.count(ai) == 0) {
+            // Chain the targetAtom to the current Atom
+            // if the currentAtom has no followon references
+            if (_followOnRoots[ai] != _followOnRoots[targetAtom]) {
+              _followOnNexts[ai] = targetAtom;
+              _followOnRoots[targetAtom] = _followOnRoots[ai];
+              changeRoots = true;
+            }
+          }
+          // Change the roots of the targetAtom and its chain to 
+          // the current atoms root
+          if (changeRoots) {
+            const DefinedAtom *a = _followOnRoots[targetAtom];
+            while (true) {
+              _followOnRoots[a] = _followOnRoots[ai];
+              // Set all the follow on's for the targetAtom to be
+              // the current root
+              AtomToAtomT::iterator targetFollowOnAtomsIter =
+                  _followOnNexts.find(a);
+              if (targetFollowOnAtomsIter != _followOnNexts.end())
+                a = targetFollowOnAtomsIter->second;
+              else
+                break;
+            }
+          } // changeRoots
+        }   // Is targetAtom root 
+      }     // kindLayoutBefore
+    }       //  Reference
+  }         // atom iteration
+}           // end function 
+
+
+/// Build an ordinal override map by traversing the followon chain, and
+/// assigning ordinals to each atom, if the atoms have their ordinals 
+/// already assigned skip the atom and move to the next. This is the 
+/// main map thats used to sort the atoms while comparing two atoms together
+void LayoutPass::buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range) {
+  uint64_t index = 0;
+  for (auto ai : range) {
+    const DefinedAtom *atom = ai;
+    AtomToAtomT::iterator start = _followOnRoots.find(atom);
+    if (start != _followOnRoots.end()) {
+      for (const DefinedAtom *nextAtom = start->second; nextAtom != NULL;
+           nextAtom = _followOnNexts[nextAtom]) {
+        AtomToOrdinalT::iterator pos = _ordinalOverrideMap.find(nextAtom);
+        if (pos == _ordinalOverrideMap.end()) {
+          _ordinalOverrideMap[nextAtom] = index++;
+        }
+      }
+    } else {
+      _ordinalOverrideMap[atom] = index;
+    }
+  }
+}
+
+/// Perform the actual pass 
+void LayoutPass::perform(MutableFile &mergedFile) {
+
+  MutableFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();
+
+  // Build follow on tables
+  buildFollowOnTable(atomRange);
+
+  // Build Ingroup reference table
+  buildInGroupTable(atomRange);
+
+  // Build preceded by tables
+  buildPrecededByTable(atomRange);
+
+  // Build override maps
+  buildOrdinalOverrideMap(atomRange);
+
+  // sort the atoms
+  std::sort(atomRange.begin(), atomRange.end(), _compareAtoms);
+}

Removed: lld/trunk/lib/Passes/OrderPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Passes/OrderPass.cpp?rev=174657&view=auto
==============================================================================
--- lld/trunk/lib/Passes/OrderPass.cpp (original)
+++ lld/trunk/lib/Passes/OrderPass.cpp (removed)
@@ -1,84 +0,0 @@
-//===- Passes/OrderPass.cpp - sort atoms ----------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This linker pass sorts atoms.  By default atoms are sort first by the
-// order their .o files were found on the command line, then by order of the
-// atoms (address) in the .o file.  But some atoms have a prefered location
-// in their section (such as pinned to the start or end of the section), so
-// the sort must take that into account too.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Reference.h"
-#include "llvm/ADT/DenseMap.h"
-
-
-namespace lld {
-
-static bool compare(const DefinedAtom *left, const DefinedAtom *right) {
-  if ( left == right )
-    return false;
-
-  // Sort same permissions together.
-  DefinedAtom::ContentPermissions leftPerms  = left->permissions();
-  DefinedAtom::ContentPermissions rightPerms = right->permissions();
-  if (leftPerms != rightPerms) 
-		return leftPerms < rightPerms;
-
-  
-  // Sort same content types together.
-  DefinedAtom::ContentType leftType  = left->contentType();
-  DefinedAtom::ContentType rightType = right->contentType();
-  if (leftType != rightType) 
-		return leftType < rightType;
-
-
-  // TO DO: Sort atoms in customs sections together.
-
-
-  // Sort by section position preference.
-  DefinedAtom::SectionPosition leftPos  = left->sectionPosition();
-  DefinedAtom::SectionPosition rightPos = right->sectionPosition();
-  bool leftSpecialPos  = (leftPos  != DefinedAtom::sectionPositionAny); 
-  bool rightSpecialPos = (rightPos != DefinedAtom::sectionPositionAny); 
-  if (leftSpecialPos || rightSpecialPos) {
-    if (leftPos != rightPos)
-      return leftPos < rightPos;
-  }
-  
-  // Sort by .o order.
-  const File *leftFile  = &left->file();
-  const File *rightFile = &right->file();
-  if ( leftFile != rightFile ) 
-		return leftFile->ordinal() < rightFile->ordinal();
-  
-  // Sort by atom order with .o file.
-  uint64_t leftOrdinal  = left->ordinal();
-  uint64_t rightOrdinal = right->ordinal();
-  if ( leftOrdinal != rightOrdinal ) 
-		return leftOrdinal < rightOrdinal;
- 
-  return false;
-}
-
-
-
-void OrderPass::perform(MutableFile &mergedFile) {
-
-  MutableFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();
-  
-  std::sort(atomRange.begin(), atomRange.end(), compare);
-}
-
-} // namespace

Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Thu Feb  7 14:16:12 2013
@@ -32,27 +32,25 @@ template <class ELFT> class ELFReference
 public:
 
   ELFReference(const Elf_Rela *rela, uint64_t offset, const Atom *target)
-    : _target(target)
-    , _targetSymbolIndex(rela->getSymbol())
-    , _offsetInAtom(offset)
-    , _addend(rela->r_addend)
-    , _kind(rela->getType()) {}
+      : _target(target), _targetSymbolIndex(rela->getSymbol()),
+        _offsetInAtom(offset), _addend(rela->r_addend),
+        _kind((Kind) rela->getType()) {
+  }
 
   ELFReference(const Elf_Rel *rel, uint64_t offset, const Atom *target)
-    : _target(target)
-    , _targetSymbolIndex(rel->getSymbol())
-    , _offsetInAtom(offset)
-    , _addend(0)
-    , _kind(rel->getType()) {}
-
-  virtual uint64_t offsetInAtom() const {
-    return _offsetInAtom;
+      : _target(target), _targetSymbolIndex(rel->getSymbol()),
+        _offsetInAtom(offset), _addend(0), _kind((Kind) rel->getType()) {
   }
 
-  virtual Kind kind() const {
-    return _kind;
+  ELFReference(Kind kind)
+      : _target(nullptr), _targetSymbolIndex(0), _offsetInAtom(0), _addend(0),
+        _kind(kind) {
   }
 
+  virtual uint64_t offsetInAtom() const { return _offsetInAtom; }
+
+  virtual Kind kind() const { return _kind; }
+
   virtual void setKind(Kind kind) {
     _kind = kind;
   }
@@ -74,15 +72,14 @@ public:
     _addend = A;
   }
 
-  virtual void setTarget(const Atom *newAtom) {
-    _target = newAtom;
-  }
+  virtual void setTarget(const Atom *newAtom) { _target = newAtom; }
+
 private:
-  const Atom  *_target;
-  uint64_t     _targetSymbolIndex;
-  uint64_t     _offsetInAtom;
-  Addend       _addend;
-  Kind         _kind;
+  const Atom *_target;
+  uint64_t _targetSymbolIndex;
+  uint64_t _offsetInAtom;
+  Addend _addend;
+  Kind _kind;
 };
 
 /// \brief These atoms store symbols that are fixed to a particular address.
@@ -416,10 +413,15 @@ public:
     return ((_referenceList)[index]);
   }
 
-  void incrementIterator(const void*& It) const {
+  void incrementIterator(const void *&It) const {
     uintptr_t index = reinterpret_cast<uintptr_t>(It);
     ++index;
-    It = reinterpret_cast<const void*>(index);
+    It = reinterpret_cast<const void *>(index);
+  }
+
+  void addReference(ELFReference<ELFT> *reference) {
+    _referenceList.push_back(reference);
+    _referenceEndIndex = _referenceList.size();
   }
 
 private:

Modified: lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt (original)
+++ lld/trunk/lib/ReaderWriter/ELF/CMakeLists.txt Thu Feb  7 14:16:12 2013
@@ -10,6 +10,7 @@ target_link_libraries(lldELF
   lldReaderWriter
   lldX86_64ELFTarget
   lldX86ELFTarget
+  lldPasses
   )
 
 include_directories(.)

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFTargetInfo.cpp Thu Feb  7 14:16:12 2013
@@ -13,6 +13,7 @@
 #include "Targets.h"
 
 #include "lld/Core/LinkerOptions.h"
+#include "lld/Passes/LayoutPass.h"
 
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/ELF.h"
@@ -39,6 +40,10 @@ uint16_t ELFTargetInfo::getOutputType()
   llvm_unreachable("Unhandled OutputKind");
 }
 
+void ELFTargetInfo::addPasses(PassManager &pm) const {
+  pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+}
+
 uint16_t ELFTargetInfo::getOutputMachine() const {
   switch (getTriple().getArch()) {
   case llvm::Triple::x86:

Modified: lld/trunk/lib/ReaderWriter/ELF/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/File.h?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/File.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/File.h Thu Feb  7 14:16:12 2013
@@ -232,6 +232,8 @@ public:
                                  content, 0, 0, _references));
       }
 
+      ELFDefinedAtom<ELFT> *previous_atom = nullptr;
+
       // i.first is the section the symbol lives in
       for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
         StringRef symbolName;
@@ -283,9 +285,38 @@ public:
         ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
             (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize);
 
+        // Check to see if we need to add the FollowOn Reference
+        // We dont want to do for symbols that are
+        // a) common symbols
+        // b) the atoms have the merge attribute set
+        // so, lets add a follow-on reference from the previous atom to the 
+        // current atom as well as lets add a preceded-by reference from the 
+        // current atom to the previous atom, so that the previous atom 
+        // is not removed in any case
+        ELFReference<ELFT> *followOn = nullptr;
+        if (!isCommon && previous_atom &&
+            previous_atom->merge() == DefinedAtom::mergeNo) {
+          followOn = new (_readerStorage)
+              ELFReference<ELFT>(lld::Reference::kindLayoutAfter);
+          previous_atom->addReference(followOn);
+        }
+
         auto newAtom = createDefinedAtomAndAssignRelocations(
             symbolName, sectionName, *si, i.first, symbolData);
 
+        // If we are inserting a followOn reference, lets add a precededBy 
+        // reference too
+        if (followOn) {
+          ELFReference<ELFT> *precededBy = nullptr;
+          followOn->setTarget(newAtom);
+          precededBy = new (_readerStorage)
+              ELFReference<ELFT>(lld::Reference::kindLayoutBefore);
+          precededBy->setTarget(previous_atom);
+          newAtom->addReference(precededBy);
+        }
+
+        previous_atom = newAtom;
+
         _definedAtoms._atoms.push_back(newAtom);
         _symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
         if (anonAtom)
@@ -296,8 +327,10 @@ public:
     // All the Atoms and References are created.  Now update each Reference's
     // target with the Atom pointer it refers to.
     for (auto &ri : _references) {
-      const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
-      ri->setTarget(findAtom(Symbol));
+      if (ri->kind() >= lld::Reference::kindTargetLow) {
+        const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
+        ri->setTarget(findAtom(Symbol));
+      }
     }
   }
 

Modified: lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp Thu Feb  7 14:16:12 2013
@@ -93,7 +93,11 @@ ErrorOr<void> HexagonTargetRelocationHan
   case R_HEX_32:
     reloc32(location, relocVAddress, targetVAddress, ref.addend());
     break;
-  default: {
+  case lld::Reference::kindLayoutAfter:
+  case lld::Reference::kindLayoutBefore:
+  case lld::Reference::kindInGroup:
+    break;
+  default : {
     std::string str;
     llvm::raw_string_ostream s(str);
     auto name = _targetInfo.stringFromRelocKind(ref.kind());

Modified: lld/trunk/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/PPC/PPCTargetHandler.cpp Thu Feb  7 14:16:12 2013
@@ -47,7 +47,13 @@ ErrorOr<void> PPCTargetRelocationHandler
   case R_PPC_REL24:
     relocB24PCREL(location, relocVAddress, targetVAddress, ref.addend());
     break;
-  default: {
+
+  case lld::Reference::kindLayoutAfter:
+  case lld::Reference::kindLayoutBefore:
+  case lld::Reference::kindInGroup:
+    break;
+
+  default : {
     std::string str;
     llvm::raw_string_ostream s(str);
     auto name = _targetInfo.stringFromRelocKind(ref.kind());

Modified: lld/trunk/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp Thu Feb  7 14:16:12 2013
@@ -48,7 +48,11 @@ ErrorOr<void> X86TargetRelocationHandler
   case R_386_PC32:
     relocPC32(location, relocVAddress, targetVAddress, ref.addend());
     break;
-  default: {
+  case lld::Reference::kindLayoutAfter:
+  case lld::Reference::kindLayoutBefore:
+  case lld::Reference::kindInGroup:
+    break;
+  default : {
     std::string str;
     llvm::raw_string_ostream s(str);
     auto name = _targetInfo.stringFromRelocKind(ref.kind());

Modified: lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp Thu Feb  7 14:16:12 2013
@@ -99,7 +99,13 @@ ErrorOr<void> X86_64TargetRelocationHand
   // Runtime only relocations. Ignore here.
   case R_X86_64_IRELATIVE:
     break;
-  default: {
+
+  case lld::Reference::kindLayoutAfter:
+  case lld::Reference::kindLayoutBefore:
+  case lld::Reference::kindInGroup:
+    break;
+
+  default : {
     std::string str;
     llvm::raw_string_ostream s(str);
     auto name = _targetInfo.stringFromRelocKind(ref.kind());

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOTargetInfo.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOTargetInfo.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOTargetInfo.cpp Thu Feb  7 14:16:12 2013
@@ -13,6 +13,7 @@
 
 #include "lld/Core/LinkerOptions.h"
 #include "lld/Core/PassManager.h"
+#include "lld/Passes/LayoutPass.h"
 
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/MachO.h"
@@ -78,7 +79,7 @@ public:
   virtual void addPasses(PassManager &pm) const {
     pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
     pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
-    pm.add(std::unique_ptr<Pass>(new OrderPass()));
+    pm.add(std::unique_ptr<Pass>(new LayoutPass()));
   }
 };
 

Modified: lld/trunk/test/elf/phdr.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/phdr.objtxt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/test/elf/phdr.objtxt (original)
+++ lld/trunk/test/elf/phdr.objtxt Thu Feb  7 14:16:12 2013
@@ -30,7 +30,7 @@ ED:   ('p_offset', 0x00004000)
 ED:   ('p_vaddr', 0x00004000)
 ED:   ('p_paddr', 0x00004000)
 ED:   ('p_filesz', 0x00000004)
-ED:   ('p_memsz', 0x00004005)
+ED:   ('p_memsz', 0x00004008)
 ED:   ('p_align', 0x00001000)
 ED:  ),
 ED:  # Program Header 3

Modified: lld/trunk/test/elf/rodata.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/rodata.objtxt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/test/elf/rodata.objtxt (original)
+++ lld/trunk/test/elf/rodata.objtxt Thu Feb  7 14:16:12 2013
@@ -4,6 +4,6 @@ RUN: lld-core -arch hexagon -reader ELF
 RUN:   %p/Inputs/rodata-test.hexagon
 RUN: llvm-objdump -section-headers %t2 |  FileCheck -check-prefix=hexagon %s
 
-i386: 2 .rodata       00000004
+i386: 1 .rodata       00000004 0000000000001000 DATA
 
-hexagon: 3 .rodata       00000004
+hexagon: 1 .rodata       00000004 0000000000001000 DATA

Modified: lld/trunk/test/elf/sections.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/sections.objtxt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/test/elf/sections.objtxt (original)
+++ lld/trunk/test/elf/sections.objtxt Thu Feb  7 14:16:12 2013
@@ -8,7 +8,7 @@ OBJDUMP:  1 .text         0000000a 00000
 OBJDUMP:  2 .data         00000004 0000000000001000 DATA
 OBJDUMP:  3 .special      00000004 0000000000001004 DATA
 OBJDUMP:  4 .anotherspecial 00000004 0000000000001008 DATA
-OBJDUMP:  5 .bss          00000001 000000000000100c BSS
+OBJDUMP:  5 .bss          00000004 000000000000100c BSS
 OBJDUMP:  6 .shstrtab     {{[0-9a-f]+}} 0000000000000000
 OBJDUMP:  7 .symtab       {{[0-9a-f]+}} 0000000000000000
 OBJDUMP:  8 .strtab       {{[0-9a-f]+}} 0000000000000000

Added: lld/trunk/test/ingroup-test-big.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ingroup-test-big.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/ingroup-test-big.objtxt (added)
+++ lld/trunk/test/ingroup-test-big.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,57 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            A
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          B
+  - name:            B
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+      - kind:            layout-after
+        offset:          0
+        target:          C
+  - name:            C
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+  - name:            E
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+      - kind:            layout-after
+        offset:          0
+        target:          F
+  - name:            F
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+  - name:            D
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+      - kind:            layout-after
+        offset:          0
+        target:          E
+...
+
+# CHKORDER:   - name:            A
+# CHKORDER:   - name:            B
+# CHKORDER:   - name:            C
+# CHKORDER:   - name:            D
+# CHKORDER:   - name:            E
+# CHKORDER:   - name:            F

Added: lld/trunk/test/ingroup-test-loop.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ingroup-test-loop.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/ingroup-test-loop.objtxt (added)
+++ lld/trunk/test/ingroup-test-loop.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,20 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            A
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          E
+  - name:            E
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+...
+
+# CHKORDER:   - name:            A
+# CHKORDER:   - name:            E

Added: lld/trunk/test/ingroup-test-with-layout-after.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ingroup-test-with-layout-after.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/ingroup-test-with-layout-after.objtxt (added)
+++ lld/trunk/test/ingroup-test-with-layout-after.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,50 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            A
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          B
+  - name:            B
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+      - kind:            layout-after
+        offset:          0
+        target:          E
+  - name:            F
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+      - kind:            layout-after
+        offset:          0
+        target:          G
+  - name:            G
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+  - name:            E
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+      - kind:            layout-after
+        offset:          0
+        target:          F
+...
+
+# CHKORDER:   - name:            A
+# CHKORDER:   - name:            B
+# CHKORDER:   - name:            E
+# CHKORDER:   - name:            F
+# CHKORDER:   - name:            G

Added: lld/trunk/test/ingroup-test.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ingroup-test.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/ingroup-test.objtxt (added)
+++ lld/trunk/test/ingroup-test.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,38 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            A
+    scope:           global
+
+  - name:            B
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+  - name:            F
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+  - name:            G
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          E
+  - name:            E
+    scope:           global
+    references:      
+      - kind:            in-group
+        offset:          0
+        target:          A
+...
+
+# CHKORDER:   - name:            A
+# CHKORDER:   - name:            B
+# CHKORDER:   - name:            E
+# CHKORDER:   - name:            F
+# CHKORDER:   - name:            G

Added: lld/trunk/test/layoutafter-test.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/layoutafter-test.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/layoutafter-test.objtxt (added)
+++ lld/trunk/test/layoutafter-test.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,30 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            fn
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          fn1
+  - name:            fn1
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          fn2
+  - name:            fn2
+    scope:           global
+    references:      
+      - kind:            layout-after
+        offset:          0
+        target:          fn3
+  - name:            fn3
+    scope:           global
+...
+
+# CHKORDER:   - name:            fn
+# CHKORDER:   - name:            fn1
+# CHKORDER:   - name:            fn2
+# CHKORDER:   - name:            fn3

Added: lld/trunk/test/layoutbefore-test.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/layoutbefore-test.objtxt?rev=174658&view=auto
==============================================================================
--- lld/trunk/test/layoutbefore-test.objtxt (added)
+++ lld/trunk/test/layoutbefore-test.objtxt Thu Feb  7 14:16:12 2013
@@ -0,0 +1,25 @@
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+
+---
+defined-atoms:   
+  - name:            fn
+    scope:           global
+
+  - name:            fn1
+    scope:           global
+    references:      
+      - kind:            layout-before
+        offset:          0
+        target:          fn
+  - name:            fn2
+    scope:           global
+    references:      
+      - kind:            layout-before
+        offset:          0
+        target:          fn1
+...
+
+
+# CHKORDER:  - name:            fn2
+# CHKORDER:  - name:            fn1
+# CHKORDER:  - name:            fn

Modified: lld/trunk/test/section-position.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/section-position.objtxt?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/test/section-position.objtxt (original)
+++ lld/trunk/test/section-position.objtxt Thu Feb  7 14:16:12 2013
@@ -1,5 +1,5 @@
-# RUN: lld-core -order-pass=true %s | FileCheck %s -check-prefix=CHKORDER
-# RUN: lld-core -order-pass=false %s | FileCheck %s -check-prefix=CHKUNORD
+# RUN: lld-core -layout-pass=true %s | FileCheck %s -check-prefix=CHKORDER
+# RUN: lld-core -layout-pass=false %s | FileCheck %s -check-prefix=CHKUNORD
 
 #
 # Test that atoms with section position requirements are sorted properly.

Modified: lld/trunk/tools/lld-core/TestingHelpers.hpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/TestingHelpers.hpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/TestingHelpers.hpp (original)
+++ lld/trunk/tools/lld-core/TestingHelpers.hpp Thu Feb  7 14:16:12 2013
@@ -270,12 +270,15 @@ struct TestingKindMapping {
 // Table of fixup kinds in YAML documents used for testing
 //
 const TestingKindMapping sKinds[] = {
-    {"call32",      2, true,  false, false},
-    {"pcrel32",     3, false, false, false},
-    {"gotLoad32",   7, false, true,  true},
-    {"gotUse32",    9, false, false, true},
-    {"lea32wasGot", 8, false, false, false},
-    {nullptr,       0, false, false, false}
+    {"in-group",      -3, false,  false, false},
+    {"layout-after",  -2, false,  false, false},
+    {"layout-before", -1, false,  false, false},
+    {"call32",         2, true,  false, false},
+    {"pcrel32",        3, false, false, false},
+    {"gotLoad32",      7, false, true,  true},
+    {"gotUse32",       9, false, false, true},
+    {"lea32wasGot",    8, false, false, false},
+    {nullptr,          0, false, false, false}
   };
 
 class TestingStubsPass : public StubsPass {

Modified: lld/trunk/tools/lld-core/lld-core.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=174658&r1=174657&r2=174658&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Thu Feb  7 14:16:12 2013
@@ -13,6 +13,7 @@
 #include "lld/Core/Pass.h"
 #include "lld/Core/PassManager.h"
 #include "lld/Core/Resolver.h"
+#include "lld/Passes/LayoutPass.h"
 #include "lld/ReaderWriter/ELFTargetInfo.h"
 #include "lld/ReaderWriter/MachOTargetInfo.h"
 #include "lld/ReaderWriter/Reader.h"
@@ -60,25 +61,21 @@ cmdLineOutputFilePath("o",
               llvm::cl::desc("Specify output filename"), 
               llvm::cl::value_desc("filename"));
 
-llvm::cl::opt<bool> 
-cmdLineDoStubsPass("stubs-pass", 
-          llvm::cl::desc("Run pass to create stub atoms"));
+llvm::cl::opt<bool> cmdLineDoStubsPass(
+    "stubs-pass", llvm::cl::desc("Run pass to create stub atoms"));
 
-llvm::cl::opt<bool> 
-cmdLineDoGotPass("got-pass", 
-          llvm::cl::desc("Run pass to create GOT atoms"));
+llvm::cl::opt<bool>
+cmdLineDoGotPass("got-pass", llvm::cl::desc("Run pass to create GOT atoms"));
 
-llvm::cl::opt<bool> 
-cmdLineDoOrderPass("order-pass", 
-          llvm::cl::desc("Run pass to sort atoms"));
+llvm::cl::opt<bool>
+cmdLineDoLayoutPass("layout-pass", llvm::cl::desc("Run pass to layout atoms"));
 
-llvm::cl::opt<bool> 
-cmdLineUndefinesIsError("undefines-are-errors", 
-          llvm::cl::desc("Any undefined symbols at end is an error"));
+llvm::cl::opt<bool> cmdLineUndefinesIsError(
+    "undefines-are-errors",
+    llvm::cl::desc("Any undefined symbols at end is an error"));
 
-llvm::cl::opt<bool> 
-cmdLineForceLoad("force-load", 
-          llvm::cl::desc("force load all members of the archive"));
+llvm::cl::opt<bool> cmdLineForceLoad(
+    "force-load", llvm::cl::desc("force load all members of the archive"));
 
 llvm::cl::opt<bool> 
 cmdLineCommonsSearchArchives("commons-search-archives", 
@@ -152,20 +149,17 @@ archSelected("arch",
 enum endianChoice {
   little, big
 };
-llvm::cl::opt<endianChoice>
-endianSelected("endian",
-  llvm::cl::desc("Select endianness of ELF output"),
-  llvm::cl::values(
-    clEnumValN(big, "big", 
-               "output big endian format"),
-    clEnumValN(little, "little", 
-               "output little endian format"),
-    clEnumValEnd));
-    
+llvm::cl::opt<endianChoice> endianSelected(
+    "endian", llvm::cl::desc("Select endianness of ELF output"),
+    llvm::cl::values(clEnumValN(big, "big", "output big endian format"),
+                     clEnumValN(little, "little",
+                                "output little endian format"), clEnumValEnd));
+
 class TestingTargetInfo : public TargetInfo {
 public:
-  TestingTargetInfo(const LinkerOptions &lo, bool stubs, bool got, bool order)
-      : TargetInfo(lo), _doStubs(stubs), _doGOT(got), _doOrder(order) {}
+  TestingTargetInfo(const LinkerOptions &lo, bool stubs, bool got, bool layout)
+      : TargetInfo(lo), _doStubs(stubs), _doGOT(got), _doLayout(layout) {
+  }
 
   virtual uint64_t getPageSize() const { return 0x1000; }
 
@@ -174,8 +168,8 @@ public:
       pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
     if (_doGOT)
       pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
-    if (_doOrder)
-      pm.add(std::unique_ptr<Pass>(new OrderPass));
+    if (_doLayout)
+      pm.add(std::unique_ptr<Pass>(new LayoutPass()));
   }
 
   virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const {
@@ -205,9 +199,9 @@ public:
   }
 
 private:
-  bool              _doStubs;
-  bool              _doGOT;
-  bool              _doOrder;
+  bool _doStubs;
+  bool _doGOT;
+  bool _doLayout;
 };
 
 int main(int argc, char *argv[]) {
@@ -252,8 +246,8 @@ int main(int argc, char *argv[]) {
     break;
   }
 
-  TestingTargetInfo tti(lo, cmdLineDoStubsPass, cmdLineDoGotPass, 
-                                                          cmdLineDoOrderPass);
+  TestingTargetInfo tti(lo, cmdLineDoStubsPass, cmdLineDoGotPass,
+                        cmdLineDoLayoutPass);
 
   std::unique_ptr<ELFTargetInfo> eti = ELFTargetInfo::create(lo);
   std::unique_ptr<MachOTargetInfo> mti = MachOTargetInfo::create(lo);





More information about the llvm-commits mailing list