[llvm-commits] [lld] r147903 - in /lld/trunk: include/lld/Core/ include/lld/Platform/ lib/Core/ test/ tools/lld-core/

Nick Kledzik kledzik at apple.com
Tue Jan 10 17:06:19 PST 2012


Author: kledzik
Date: Tue Jan 10 19:06:19 2012
New Revision: 147903

URL: http://llvm.org/viewvc/llvm-project?rev=147903&view=rev
Log:
A couple of big refactorings: 1) Move most attributes of Atom down to DefinedAtom, so only atoms representing definitions need to implement them. 2) Remove definitionTentative, definitionWeak, mergeDuplicates, and autoHide.  Replace with merge and interposable attributes. 3) Make all methods on Atom be virtual so that future object file readers can lazily generated attributes

Added:
    lld/trunk/include/lld/Core/DefinedAtom.h
Removed:
    lld/trunk/lib/Core/Atom.cpp
Modified:
    lld/trunk/include/lld/Core/Atom.h
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/SymbolTable.h
    lld/trunk/include/lld/Core/UndefinedAtom.h
    lld/trunk/include/lld/Platform/Platform.h
    lld/trunk/lib/Core/CMakeLists.txt
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Core/SymbolTable.cpp
    lld/trunk/lib/Core/YamlKeyValues.cpp
    lld/trunk/lib/Core/YamlKeyValues.h
    lld/trunk/lib/Core/YamlReader.cpp
    lld/trunk/lib/Core/YamlWriter.cpp
    lld/trunk/test/auto-hide-coalesce.objtxt
    lld/trunk/test/cstring-coalesce.objtxt
    lld/trunk/test/inline-coalesce.objtxt
    lld/trunk/test/multiple-def-error.objtxt
    lld/trunk/test/tent-merge.objtxt
    lld/trunk/test/weak-coalesce.objtxt
    lld/trunk/tools/lld-core/lld-core.cpp

Modified: lld/trunk/include/lld/Core/Atom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Atom.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Atom.h (original)
+++ lld/trunk/include/lld/Core/Atom.h Tue Jan 10 19:06:19 2012
@@ -12,173 +12,32 @@
 
 #include <assert.h>
 
-#include "lld/Core/Reference.h"
-
 namespace llvm {
-  template <typename T>
-  class ArrayRef;
-
   class StringRef;
 }
 
 namespace lld {
 
 class File;
+class DefinedAtom;
 
-/// An atom is the fundamental unit of linking.  A C function or global variable
-/// is an atom.  An atom has content and attributes. The content of a function
-/// atom is the instructions that implement the function.  The content of a
-/// global variable atom is its initial bytes.
-///
-/// Here are some example attribute sets for common atoms. If a particular
-/// attribute is not listed, the default values are:  definition=regular,
-/// sectionChoice=basedOnContent, scope=translationUnit, mergeDupes=false, 
-/// autoHide=false, internalName=false, deadStrip=normal
-///
-///  C function:  void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global
-///
-///  C static function:  staic void func() {} <br>
-///    name=func, type=code, perm=r_x
-///
-///  C global variable:  int count = 1; <br>
-///    name=count, type=data, perm=rw_, scope=global
-///
-///  C tentative definition:  int bar; <br>
-///    name=bar, type=data, perm=rw_, scope=global, definition=tentative
-///
-///  Uninitialized C static variable:  static int stuff; <br>
-///    name=stuff, type=zerofill, perm=rw_
-///
-///  Weak C function:  __attribute__((weak)) void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global, definition=weak
-///
-///  Hidden C function:  __attribute__((visibility("hidden"))) void foo() {}<br>
-///    name=foo, type=code, perm=r_x, scope=linkageUnit
-///
-///  No-dead-strip function:  __attribute__((used)) void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global, deadStrip=never
-///
-///  Non-inlined C++ inline method:  inline void Foo::doit() {} <br>
-///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, 
-///    mergeDupes=true, autoHide=true
-///
-///  Non-inlined C++ inline method whose address is taken:  
-///     inline void Foo::doit() {} <br>
-///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, mergeDupes=true
-///
-///  literal c-string:  "hello" <br>
-///    name=L0, internalName=true, type=cstring, perm=r__, 
-///    scope=linkageUnit, mergeDupes=true
 ///
-///  literal double:  1.234 <br>
-///    name=L0, internalName=true, type=literal8, perm=r__, 
-///    scope=linkageUnit, mergeDupes=true
-///
-///  constant:  { 1,2,3 } <br>
-///    name=L0, internalName=true, type=constant, perm=r__, 
-///    scope=linkageUnit, mergeDupes=true
-///
-///  Pointer to initializer function:  <br>
-///    name=_init, internalName=true, type=initializer, perm=rw_l,
-///    sectionChoice=customRequired
-///
-///  C function place in custom section:  __attribute__((section("__foo"))) 
-///                                       void foo() {} <br>
-///    name=foo, type=code, perm=r_x, scope=global, 
-///    sectionChoice=customRequired, sectionName=__foo
+/// The linker has a Graph Theory model of linking. An object file is seen
+/// as a set of Atoms with References to other Atoms.  Each Atom is a node
+/// and each Reference is an edge. An Atom can be a DefinedAtom which has
+/// content or a UndefinedAtom which is a placeholder and represents an 
+/// undefined symbol (extern declaration).
 ///
 class Atom {
 public:
-  /// The scope in which this atom is acessible to other atoms.
-  enum Scope {
-    scopeTranslationUnit,  ///< Accessible only to atoms in the same translation
-                           ///  unit (e.g. a C static).
-    scopeLinkageUnit,      ///< Accessible to atoms being linked but not visible  
-                           ///  to runtime loader (e.g. visibility=hidden).
-    scopeGlobal            ///< Accessible to all atoms and visible to runtime
-                           ///  loader (e.g. visibility=default) .
-  };
-
   /// Whether this atom is defined or a proxy for an undefined symbol
   enum Definition {
     definitionRegular,      ///< Normal C/C++ function or global variable.
-    definitionWeak,         ///< Can be silently overridden by definitionRegular
-    definitionTentative,    ///< C-only pre-ANSI support aka common.
     definitionAbsolute,     ///< Asm-only (foo = 10). Not tied to any content.
     definitionUndefined,    ///< Only in .o files to model reference to undef.
     definitionSharedLibrary ///< Only in shared libraries to model export.
   };
 
-  enum ContentType {
-    typeUnknown,            // for use with definitionUndefined
-    typeCode,               // executable code
-    typeResolver,           // function which returns address of target
-    typeBranchIsland,       // linker created for large binaries
-    typeBranchShim,         // linker created to switch thumb mode
-    typeStub,               // linker created for calling external function
-    typeStubHelper,         // linker created for initial stub binding
-    typeConstant,           // a read-only constant
-    typeCString,            // a zero terminated UTF8 C string
-    typeUTF16String,        // a zero terminated UTF16 string
-    typeCFI,                // a FDE or CIE from dwarf unwind info
-    typeLSDA,               // extra unwinding info
-    typeLiteral4,           // a four-btye read-only constant
-    typeLiteral8,           // an eight-btye read-only constant
-    typeLiteral16,          // a sixteen-btye read-only constant
-    typeData,               // read-write data
-    typeZeroFill,           // zero-fill data
-    typeObjC1Class,         // ObjC1 class [Darwin]
-    typeLazyPointer,        // pointer through which a stub jumps
-    typeLazyDylibPointer,   // pointer through which a stub jumps [Darwin]
-    typeCFString,           // NS/CFString object [Darwin]
-    typeGOT,                // pointer to external symbol
-    typeInitializerPtr,     // pointer to initializer function
-    typeTerminatorPtr,      // pointer to terminator function
-    typeCStringPtr,         // pointer to UTF8 C string [Darwin]
-    typeObjCClassPtr,       // pointer to ObjC class [Darwin]
-    typeObjC2CategoryList,  // pointers to ObjC category [Darwin]
-    typeDTraceDOF,          // runtime data for Dtrace [Darwin]
-    typeTempLTO,            // temporary atom for bitcode reader
-    typeCompactUnwindInfo,  // runtime data for unwinder [Darwin]
-    typeThunkTLV,           // thunk used to access a TLV [Darwin]
-    typeTLVInitialData,     // initial data for a TLV [Darwin]
-    typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
-    typeTLVInitializerPtr,  // pointer to thread local initializer [Darwin]
-    typeFirstInSection,     // label for boundary of section [Darwin]
-    typeLastInSection,      // label for boundary of section [Darwin]
-  };
-
-  enum ContentPermissions {
-    perm___  = 0,           // mapped as unacessible
-    permR__  = 8,           // mapped read-only
-    permR_X  = 8 + 2,       // mapped readable and executable
-    permRW_  = 8 + 4,       // mapped readable and writable
-    permRW_L = 8 + 4 + 1,   // initially mapped r/w, then made read-only
-                            // loader writable
-  };
-
-  enum SectionChoice {
-    sectionBasedOnContent,  // linker infers final section based on content
-    sectionCustomPreferred, // linker may place in specific section
-    sectionCustomRequired   // linker must place in specific section
-  };
-
-  enum DeadStripKind {
-    deadStripNormal,        // linker may dead strip this atom
-    deadStripNever,         // linker must never dead strip this atom
-    deadStripAlways         // linker must remove this atom if unused
-  };
-
-  struct Alignment {
-    Alignment(int p2, int m = 0)
-      : powerOf2(p2)
-      , modulus(m) {}
-
-    uint16_t powerOf2;
-    uint16_t modulus;
-  };
-
   /// file - returns the File that produced/owns this Atom
   virtual const class File& file() const = 0;
 
@@ -186,204 +45,23 @@
   /// name of the function. 
   virtual llvm::StringRef name() const = 0;
   
-  /// internalName - If the name is just a temporary label that should
-  /// not show up in the final linked image.
-  bool internalName() const { 
-    return _internalName; 
-  }
-
-  /// size - the number of bytes of space this atom's content will occupy
-  /// in the final linked image.  For a function atom, it is the number
-  /// of bytes of code in the function.
-  virtual uint64_t size() const = 0;
-
-  /// scope - The visibility of this atom to other atoms.  C static functions
-  /// have scope scopeTranslationUnit.  Regular C functions have scope 
-  /// scopeGlobal.  Functions compiled with visibility=hidden have scope
-  /// scopeLinkageUnit so they can be see by other atoms being linked but not
-  /// by the OS loader.
-  Scope scope() const { 
-    return _scope; 
-  }
-  
   /// definition - Whether this atom is a definition or represents an undefined
-  /// or tentative symbol.
-  Definition definition() const { 
-    return _definition; 
-  }
-  
-  /// mergeDuplicates - For definitionRegular atoms, this means the
-  /// atom can be silently coalesced with another atom that has the 
-  /// same name or content.
-  bool mergeDuplicates() const { 
-    return _mergeDuplicates; 
-  }
-  
-  /// contentType - The type of this atom, such as code or data.
-  ContentType contentType() const { 
-    return _contentType; 
-  }
-  
-  /// alignment - The alignment constraints on how this atom must be laid out 
-  /// in the final linked image (e.g. 16-byte aligned).
-  Alignment alignment() const {
-    return Alignment(_alignmentPowerOf2, _alignmentModulus);
-  }
-
-  /// sectionChoice - Whether this atom must be in a specially named section
-  /// in the final linked image, or if the linker can infer the section 
-  /// based on the contentType().
-  SectionChoice sectionChoice() const { 
-    return _sectionChoice; 
-  }
-  
-  /// customSectionName - If sectionChoice() != sectionBasedOnContent, then
-  /// this return the name of the section the atom should be placed into.
-  virtual llvm::StringRef customSectionName() const;
-    
-  /// deadStrip - constraints on whether the linker may dead strip away 
-  /// this atom.
-  DeadStripKind deadStrip() const { 
-    return _deadStrip; 
-  }
-  
-  /// autoHide - Whether it is ok for the linker to change the scope of this 
-  /// atom to hidden as long as all other duplicates are also autoHide.
-  bool autoHide() const {
-    return _autoHide;
-  }
-
-  /// permissions - Returns the OS memory protections required for this atom's
-  /// content at runtime.  A function atom is R_X, a global variable is RW_,
-  /// and a read-only constant is R__.
-  virtual ContentPermissions permissions() const;
-  
-  /// isThumb - only applicable to ARM code. Tells the linker if the code
-  /// uses thumb or arm instructions.  The linker needs to know this to
-  /// set the low bit of pointers to thumb functions.
-  bool isThumb() const { 
-    return _thumb; 
-  }
-  
-  /// isAlias - means this is a zero size atom that exists to provide an
-  /// alternate name for another atom.  Alias atoms must have a special
-  /// Reference to the atom they alias which the layout engine recognizes
-  /// and forces the alias atom to layout right before the target atom.
-  bool isAlias() const { 
-    return _alias; 
-  }
-
-  /// rawContent - returns a reference to the raw (unrelocated) bytes of 
-  /// this Atom's content.
-  virtual llvm::ArrayRef<uint8_t> rawContent() const;
-
-  /// referencesBegin - used to start iterating this Atom's References
-  virtual Reference::iterator referencesBegin() const;
-
-  /// referencesEnd - used to end iterating this Atom's References
-  virtual Reference::iterator referencesEnd() const;
-
-  /// setLive - sets or clears the liveness bit.  Used by linker to do 
-  /// dead code stripping.
-  void setLive(bool l) { _live = l; }
-  
-  /// live - returns the liveness bit. Used by linker to do 
-  /// dead code stripping.
-  bool live() const { return _live; }
-
-  /// ordinal - returns a value for the order of this Atom within its file.
-  /// This is used by the linker to order the layout of Atoms so that
-  /// the resulting image is stable and reproducible.
-  uint64_t ordinal() const {
-    assert(_mode == modeOrdinal);
-    return _address;
-  }
-  
-  /// sectionOffset - returns the section offset assigned to this Atom within
-  /// its final section. 
-  uint64_t sectionOffset() const {
-    assert(_mode == modeSectionOffset);
-    return _address;
-  }
-
-  /// finalAddress - returns the address assigned to Atom within the final
-  /// linked image. 
-  uint64_t finalAddress() const {
-    assert(_mode == modeFinalAddress);
-    return _address;
-  }
-
-  /// setSectionOffset - assigns an offset within a section in the final
-  /// linked image.
-  void setSectionOffset(uint64_t off) { 
-    assert(_mode != modeFinalAddress); 
-    _address = off; 
-    _mode = modeSectionOffset; 
-  }
+  /// symbol.
+  virtual Definition definition() const = 0;
   
-  /// setSectionOffset - assigns an offset within a section in the final
-  /// linked image.
-  void setFinalAddress(uint64_t addr) { 
-    assert(_mode == modeSectionOffset); 
-    _address = addr; 
-    _mode = modeFinalAddress; 
-  }
+  /// definedAtom - like dynamic_cast, if atom is definitionRegular
+  /// returns atom cast to DefinedAtom*, else returns NULL;
+  virtual const DefinedAtom* definedAtom() const { return NULL; }
   
-  /// constructor
-  Atom( uint64_t ord
-      , Definition d
-      , Scope s
-      , ContentType ct
-      , SectionChoice sc
-      , bool internalName
-      , bool mergeDupes
-      , bool autoHide
-      , DeadStripKind ds
-      , bool IsThumb
-      , bool IsAlias
-      , Alignment a)
-    : _address(ord)
-    , _alignmentModulus(a.modulus)
-    , _alignmentPowerOf2(a.powerOf2)
-    , _contentType(ct)
-    , _definition(d)
-    , _scope(s)
-    , _sectionChoice(sc) 
-    , _internalName(internalName)
-    , _deadStrip(ds)
-    , _mode(modeOrdinal)
-    , _mergeDuplicates(mergeDupes)
-    , _thumb(IsThumb)
-	, _autoHide(autoHide)
-    , _alias(IsAlias)
-    {}
-
-
 protected:
+  /// Atom is an abstract base class.  Only subclasses can access constructor.
+  Atom() {}
+  
   /// The memory for Atom objects is always managed by the owning File
   /// object.  Therefore, no one but the owning File object should call
   /// delete on an Atom.  In fact, some File objects may bulk allocate
   /// an array of Atoms, so they cannot be individually deleted by anyone.
-  virtual ~Atom();
-
-  /// The __address field has different meanings throughout the life of an Atom.
-	enum AddressMode { modeOrdinal, modeSectionOffset, modeFinalAddress };
-
-  uint64_t      _address;
-  uint16_t      _alignmentModulus;
-  uint8_t       _alignmentPowerOf2;
-  ContentType   _contentType : 8;
-  Definition    _definition : 3;
-  Scope         _scope : 2;
-  SectionChoice _sectionChoice: 2;
-  bool          _internalName : 1;
-  DeadStripKind _deadStrip : 2;
-  AddressMode   _mode : 2;
-  bool          _mergeDuplicates : 1;
-  bool          _thumb : 1;
-  bool          _autoHide : 1;
-  bool          _alias : 1;
-  bool          _live : 1;
+  virtual ~Atom() {}
 };
 
 } // namespace lld

Added: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=147903&view=auto
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (added)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Jan 10 19:06:19 2012
@@ -0,0 +1,287 @@
+//===- Core/DefinedAtom.h - The Fundimental Unit of Linking ---------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_CORE_DEFINED_ATOM_H_
+#define LLD_CORE_DEFINED_ATOM_H_
+
+#include <assert.h>
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/Reference.h"
+
+namespace llvm {
+  template <typename T>
+  class ArrayRef;
+
+  class StringRef;
+}
+
+namespace lld {
+
+class File;
+
+/// An atom is the fundamental unit of linking.  A C function or global variable
+/// is an atom.  An atom has content and attributes. The content of a function
+/// atom is the instructions that implement the function.  The content of a
+/// global variable atom is its initial bytes.
+///
+/// Here are some example attribute sets for common atoms. If a particular
+/// attribute is not listed, the default values are:  definition=regular,
+/// sectionChoice=basedOnContent, scope=translationUnit, merge=no, 
+/// internalName=false, deadStrip=normal, interposable=no
+///
+///  C function:  void foo() {} <br>
+///    name=foo, type=code, perm=r_x, scope=global
+///
+///  C static function:  staic void func() {} <br>
+///    name=func, type=code, perm=r_x
+///
+///  C global variable:  int count = 1; <br>
+///    name=count, type=data, perm=rw_, scope=global
+///
+///  C tentative definition:  int bar; <br>
+///    name=bar, type=zerofill, perm=rw_, scope=global, 
+///    merge=asTentative, interposable=yesAndRuntimeWeak
+///
+///  Uninitialized C static variable:  static int stuff; <br>
+///    name=stuff, type=zerofill, perm=rw_
+///
+///  Weak C function:  __attribute__((weak)) void foo() {} <br>
+///    name=foo, type=code, perm=r_x, scope=global, merge=asWeak
+///
+///  Hidden C function:  __attribute__((visibility("hidden"))) void foo() {}<br>
+///    name=foo, type=code, perm=r_x, scope=linkageUnit
+///
+///  No-dead-strip function:  __attribute__((used)) void foo() {} <br>
+///    name=foo, type=code, perm=r_x, scope=global, deadStrip=never
+///
+///  Non-inlined C++ inline method:  inline void Foo::doit() {} <br>
+///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, 
+///    mergeDupes=asWeak
+///
+///  Non-inlined C++ inline method whose address is taken:  
+///     inline void Foo::doit() {} <br>
+///    name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, 
+///    mergeDupes=asAddressedWeak
+///
+///  literal c-string:  "hello" <br>
+///    name=L0, internalName=true, type=cstring, perm=r__, scope=linkageUnit
+///
+///  literal double:  1.234 <br>
+///    name=L0, internalName=true, type=literal8, perm=r__, scope=linkageUnit
+///
+///  constant:  { 1,2,3 } <br>
+///    name=L0, internalName=true, type=constant, perm=r__, scope=linkageUnit
+///
+///  Pointer to initializer function:  <br>
+///    name=_init, internalName=true, type=initializer, perm=rw_l,
+///    sectionChoice=customRequired
+///
+///  C function place in custom section:  __attribute__((section("__foo"))) 
+///                                       void foo() {} <br>
+///    name=foo, type=code, perm=r_x, scope=global, 
+///    sectionChoice=customRequired, sectionName=__foo
+///
+class DefinedAtom : public Atom {
+public:
+  /// Whether this atom is defined or a proxy for an undefined symbol
+  virtual Definition definition() const {
+    return Atom::definitionRegular;
+  }
+
+  virtual const DefinedAtom* definedAtom() const { 
+    return this; 
+  }
+
+  /// The scope in which this atom is acessible to other atoms.
+  enum Scope {
+    scopeTranslationUnit,  ///< Accessible only to atoms in the same translation
+                           ///  unit (e.g. a C static).
+    scopeLinkageUnit,      ///< Accessible to atoms being linked but not visible  
+                           ///  to runtime loader (e.g. visibility=hidden).
+    scopeGlobal            ///< Accessible to all atoms and visible to runtime
+                           ///  loader (e.g. visibility=default).
+  };
+
+  enum Interposable {
+    interposeNo,            // linker can directly bind uses of this atom
+    interposeYes,           // linker must indirect (through GOT) uses
+    interposeYesAndRuntimeWeak // must indirect and mark symbol weak in final 
+                               // linked image
+  };
+
+  enum Merge {
+    mergeNo,                // Another atom with same name is error
+    mergeAsTentative,       // Is ANSI C tentative defintion, can be coalesced
+    mergeAsWeak,            // is C++ inline definition that was not inlined,  
+                            // but address was not taken, so atom can be hidden
+                            // by linker
+    mergeAsWeakAndAddressUsed // is C++ definition inline definition whose 
+                              // address was taken.
+  };
+
+  enum ContentType {
+    typeUnknown,            // for use with definitionUndefined
+    typeCode,               // executable code
+    typeResolver,           // function which returns address of target
+    typeBranchIsland,       // linker created for large binaries
+    typeBranchShim,         // linker created to switch thumb mode
+    typeStub,               // linker created for calling external function
+    typeStubHelper,         // linker created for initial stub binding
+    typeConstant,           // a read-only constant
+    typeCString,            // a zero terminated UTF8 C string
+    typeUTF16String,        // a zero terminated UTF16 string
+    typeCFI,                // a FDE or CIE from dwarf unwind info
+    typeLSDA,               // extra unwinding info
+    typeLiteral4,           // a four-btye read-only constant
+    typeLiteral8,           // an eight-btye read-only constant
+    typeLiteral16,          // a sixteen-btye read-only constant
+    typeData,               // read-write data
+    typeZeroFill,           // zero-fill data
+    typeObjC1Class,         // ObjC1 class [Darwin]
+    typeLazyPointer,        // pointer through which a stub jumps
+    typeLazyDylibPointer,   // pointer through which a stub jumps [Darwin]
+    typeCFString,           // NS/CFString object [Darwin]
+    typeGOT,                // pointer to external symbol
+    typeInitializerPtr,     // pointer to initializer function
+    typeTerminatorPtr,      // pointer to terminator function
+    typeCStringPtr,         // pointer to UTF8 C string [Darwin]
+    typeObjCClassPtr,       // pointer to ObjC class [Darwin]
+    typeObjC2CategoryList,  // pointers to ObjC category [Darwin]
+    typeDTraceDOF,          // runtime data for Dtrace [Darwin]
+    typeTempLTO,            // temporary atom for bitcode reader
+    typeCompactUnwindInfo,  // runtime data for unwinder [Darwin]
+    typeThunkTLV,           // thunk used to access a TLV [Darwin]
+    typeTLVInitialData,     // initial data for a TLV [Darwin]
+    typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin]
+    typeTLVInitializerPtr,  // pointer to thread local initializer [Darwin]
+    typeFirstInSection,     // label for boundary of section [Darwin]
+    typeLastInSection,      // label for boundary of section [Darwin]
+  };
+
+  enum ContentPermissions {
+    perm___  = 0,           // mapped as unaccessible
+    permR__  = 8,           // mapped read-only
+    permR_X  = 8 + 2,       // mapped readable and executable
+    permRW_  = 8 + 4,       // mapped readable and writable
+    permRW_L = 8 + 4 + 1,   // initially mapped r/w, then made read-only
+                            // loader writable
+  };
+
+  enum SectionChoice {
+    sectionBasedOnContent,  // linker infers final section based on content
+    sectionCustomPreferred, // linker may place in specific section
+    sectionCustomRequired   // linker must place in specific section
+  };
+
+  enum DeadStripKind {
+    deadStripNormal,        // linker may dead strip this atom
+    deadStripNever,         // linker must never dead strip this atom
+    deadStripAlways         // linker must remove this atom if unused
+  };
+
+  struct Alignment {
+    Alignment(int p2, int m = 0)
+      : powerOf2(p2)
+      , modulus(m) {}
+
+    uint16_t powerOf2;
+    uint16_t modulus;
+  };
+
+  /// ordinal - returns a value for the order of this Atom within its file.
+  /// This is used by the linker to order the layout of Atoms so that
+  /// the resulting image is stable and reproducible.
+  virtual uint64_t ordinal() const = 0;
+    
+  /// internalName - If the name is just a temporary label that should
+  /// not show up in the final linked image.
+  virtual bool internalName() const = 0;
+  
+  /// size - the number of bytes of space this atom's content will occupy
+  /// in the final linked image.  For a function atom, it is the number
+  /// of bytes of code in the function.
+  virtual uint64_t size() const = 0;
+
+  /// scope - The visibility of this atom to other atoms.  C static functions
+  /// have scope scopeTranslationUnit.  Regular C functions have scope 
+  /// scopeGlobal.  Functions compiled with visibility=hidden have scope
+  /// scopeLinkageUnit so they can be see by other atoms being linked but not
+  /// by the OS loader.
+  virtual Scope scope() const = 0;
+  
+  /// interposable - Whether the linker should use direct or indirect
+  /// access to this atom.
+  virtual Interposable interposable() const = 0;
+  
+  /// merge - how the linker should handle if multiple atoms have 
+  /// the same name.
+  virtual Merge merge() const = 0;
+  
+  /// contentType - The type of this atom, such as code or data.
+  virtual ContentType contentType() const = 0;
+    
+  /// alignment - The alignment constraints on how this atom must be laid out 
+  /// in the final linked image (e.g. 16-byte aligned).
+  virtual Alignment alignment() const = 0;
+  
+  /// sectionChoice - Whether this atom must be in a specially named section
+  /// in the final linked image, or if the linker can infer the section 
+  /// based on the contentType().
+  virtual SectionChoice sectionChoice() const = 0;
+    
+  /// customSectionName - If sectionChoice() != sectionBasedOnContent, then
+  /// this return the name of the section the atom should be placed into.
+  virtual llvm::StringRef customSectionName() const = 0;
+    
+  /// deadStrip - constraints on whether the linker may dead strip away 
+  /// this atom.
+  virtual DeadStripKind deadStrip() const = 0;
+    
+  /// permissions - Returns the OS memory protections required for this atom's
+  /// content at runtime.  A function atom is R_X, a global variable is RW_,
+  /// and a read-only constant is R__.
+  virtual ContentPermissions permissions() const = 0;
+  
+  /// isThumb - only applicable to ARM code. Tells the linker if the code
+  /// uses thumb or arm instructions.  The linker needs to know this to
+  /// set the low bit of pointers to thumb functions.
+  virtual bool isThumb() const = 0;
+    
+  /// isAlias - means this is a zero size atom that exists to provide an
+  /// alternate name for another atom.  Alias atoms must have a special
+  /// Reference to the atom they alias which the layout engine recognizes
+  /// and forces the alias atom to layout right before the target atom.
+  virtual bool isAlias() const = 0; 
+  
+  /// rawContent - returns a reference to the raw (unrelocated) bytes of 
+  /// this Atom's content.
+  virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;
+
+  /// referencesBegin - used to start iterating this Atom's References
+  virtual Reference::iterator referencesBegin() const = 0;
+
+  /// referencesEnd - used to end iterating this Atom's References
+  virtual Reference::iterator referencesEnd() const = 0;
+
+protected:
+  /// DefinedAtom is an abstract base class.  
+  /// Only subclasses can access constructor.
+  DefinedAtom() { }
+  
+  /// The memory for DefinedAtom objects is always managed by the owning File
+  /// object.  Therefore, no one but the owning File object should call
+  /// delete on an Atom.  In fact, some File objects may bulk allocate
+  /// an array of Atoms, so they cannot be individually deleted by anyone.
+  virtual ~DefinedAtom() {}
+};
+
+} // namespace lld
+
+#endif // LLD_CORE_DEFINED_ATOM_H_

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Tue Jan 10 19:06:19 2012
@@ -12,6 +12,9 @@
 
 #include "llvm/ADT/StringRef.h"
 
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+
 namespace lld {
 
 class File {
@@ -22,7 +25,8 @@
   class AtomHandler {
   public:
     virtual ~AtomHandler() {}
-    virtual void doAtom(const class Atom &) = 0;
+    virtual void doDefinedAtom(const class DefinedAtom &) = 0;
+    virtual void doUndefinedAtom(const class UndefinedAtom &) = 0;
     virtual void doFile(const class File &) = 0;
   };
 

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Jan 10 19:06:19 2012
@@ -13,6 +13,8 @@
 #include "lld/Core/File.h"
 #include "lld/Core/SymbolTable.h"
 
+#include "llvm/ADT/DenseSet.h"
+
 #include <vector>
 #include <set>
 
@@ -39,8 +41,9 @@
     , _completedInitialObjectFiles(false) {}
 
   // AtomHandler methods
-  virtual void doAtom(const Atom &);
-  virtual void doFile(const File &);
+  virtual void doDefinedAtom(const class DefinedAtom&);
+  virtual void doUndefinedAtom(const class UndefinedAtom&);
+  virtual void doFile(const File&);
 
   /// @brief do work of merging and resolving and return list
   std::vector<const Atom *> &resolve();
@@ -65,7 +68,7 @@
 
   const Atom *entryPoint();
   void markLive(const Atom &atom, WhyLiveBackChain *previous);
-  void addAtoms(const std::vector<const Atom *>&);
+  void addAtoms(const std::vector<const DefinedAtom *>&);
 
   Platform &_platform;
   const InputFiles &_inputFiles;
@@ -73,6 +76,7 @@
   std::vector<const Atom *> _atoms;
   std::set<const Atom *> _deadStripRoots;
   std::vector<const Atom *> _atomsWithUnresolvedReferences;
+  llvm::DenseSet<const Atom *> _liveAtoms;
   bool _haveLLVMObjs;
   bool _addToFinalSection;
   bool _completedInitialObjectFiles;

Modified: lld/trunk/include/lld/Core/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SymbolTable.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SymbolTable.h (original)
+++ lld/trunk/include/lld/Core/SymbolTable.h Tue Jan 10 19:06:19 2012
@@ -21,6 +21,8 @@
 namespace lld {
 
 class Atom;
+class DefinedAtom;
+class UndefinedAtom;
 class Platform;
 
 /// The SymbolTable class is responsible for coalescing atoms.
@@ -33,7 +35,10 @@
       SymbolTable(Platform& plat);
 
   /// @brief add atom to symbol table
-  void add(const Atom &);
+  void add(const DefinedAtom &);
+
+  /// @brief add atom to symbol table
+  void add(const UndefinedAtom &);
 
   /// @brief checks if name is in symbol table and if so atom is not
   ///        UndefinedAtom
@@ -55,15 +60,16 @@
   typedef std::map<llvm::StringRef, const Atom *> NameToAtom;
   typedef std::map<const Atom *, const Atom *> AtomToAtom;
   struct MyMappingInfo {
-    static const Atom * getEmptyKey() { return NULL; }
-    static const Atom * getTombstoneKey() { return (Atom*)(-1); }
-    static unsigned getHashValue(const Atom * const Val);
-    static bool isEqual(const Atom * const LHS, const Atom * const RHS);
+    static const DefinedAtom * getEmptyKey() { return NULL; }
+    static const DefinedAtom * getTombstoneKey() { return (DefinedAtom*)(-1); }
+    static unsigned getHashValue(const DefinedAtom * const Val);
+    static bool isEqual(const DefinedAtom * const LHS, 
+                        const DefinedAtom * const RHS);
   };
-  typedef llvm::DenseSet<const Atom*, MyMappingInfo> AtomContentSet;
+  typedef llvm::DenseSet<const DefinedAtom*, MyMappingInfo> AtomContentSet;
 
   void addByName(const Atom &);
-  void addByContent(const Atom &);
+  void addByContent(const DefinedAtom &);
 
   Platform&  _platform;
   AtomToAtom _replacedAtoms;

Modified: lld/trunk/include/lld/Core/UndefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/UndefinedAtom.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/UndefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/UndefinedAtom.h Tue Jan 10 19:06:19 2012
@@ -20,22 +20,9 @@
 /// It exists as a place holder for a future atom.
 class UndefinedAtom : public Atom {
 public:
-  UndefinedAtom(llvm::StringRef nm, const File& f)
-    : Atom( 0,
-            Atom::definitionUndefined
-          , Atom::scopeLinkageUnit
-          , Atom::typeUnknown
-          , Atom::sectionBasedOnContent
-          , false
-          , false
-		  , false
-          , deadStripNormal
-          , false
-          , false
-          , Atom::Alignment(0))
-    , _name(nm), _file(f) {}
+  UndefinedAtom(llvm::StringRef nm, bool weakImport, const File& f)
+          : _name(nm), _file(f), _weakImport(weakImport) {}
 
-  // overrides of Atom
   virtual const File& file() const {
     return _file;
   }
@@ -43,21 +30,21 @@
   virtual llvm::StringRef name() const {
     return _name;
   }
-  virtual uint64_t size() const {
-    return 0;
+
+  virtual Definition definition() const {
+    return Atom::definitionUndefined;
   }
-  virtual uint64_t objectAddress() const {
-    return 0;
+
+  virtual bool weakImport() const {
+    return _weakImport;
   }
-  virtual void copyRawContent(uint8_t buffer[]) const { }
-  virtual void setScope(Scope) { }
-  bool weakImport();
 
 protected:
   virtual ~UndefinedAtom() {}
 
   llvm::StringRef _name;
   const File&     _file;
+  bool            _weakImport;
 };
 
 } // namespace lld

Modified: lld/trunk/include/lld/Platform/Platform.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Platform/Platform.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/include/lld/Platform/Platform.h (original)
+++ lld/trunk/include/lld/Platform/Platform.h Tue Jan 10 19:06:19 2012
@@ -14,6 +14,7 @@
 
 namespace lld {
 class Atom;
+class DefinedAtom;
 
 /// The Platform class encapsulated plaform specific linking knowledge.
 ///
@@ -29,15 +30,15 @@
   virtual void atomAdded(const Atom &file) = 0;
 
   /// @brief give platform a chance to change each atom's scope
-  virtual void adjustScope(const Atom &atom) = 0;
+  virtual void adjustScope(const DefinedAtom &atom) = 0;
 
   /// @brief if specified atom needs alternate names, return AliasAtom(s)
   virtual bool getAliasAtoms(const Atom &atom,
-                             std::vector<const Atom *>&) = 0;
+                             std::vector<const DefinedAtom *>&) = 0;
 
   /// @brief give platform a chance to resolve platform-specific undefs
   virtual bool getPlatformAtoms(llvm::StringRef undefined,
-                                std::vector<const Atom *>&) = 0;
+                                std::vector<const DefinedAtom *>&) = 0;
 
   /// @brief resolver should remove unreferenced atoms
   virtual bool deadCodeStripping() = 0;
@@ -46,7 +47,7 @@
   virtual bool isDeadStripRoot(const Atom &atom) = 0;
 
   /// @brief if target must have some atoms, denote here
-  virtual bool getImplicitDeadStripRoots(std::vector<const Atom *>&) = 0;
+  virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) = 0;
 
   /// @brief return entry point for output file (e.g. "main") or NULL
   virtual llvm::StringRef entryPointName() = 0;

Removed: lld/trunk/lib/Core/Atom.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Atom.cpp?rev=147902&view=auto
==============================================================================
--- lld/trunk/lib/Core/Atom.cpp (original)
+++ lld/trunk/lib/Core/Atom.cpp (removed)
@@ -1,44 +0,0 @@
-//===- Core/Atom.cpp - The Fundimental Unit of Linking --------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Atom.h"
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace lld {
-
-  Atom::~Atom() {}
-
-  llvm::StringRef Atom::name() const {
-    return llvm::StringRef();
-  }
-
-  llvm::StringRef Atom::customSectionName() const {
-    return llvm::StringRef();
-  }
-
-  llvm::ArrayRef<uint8_t> Atom::rawContent() const {
-    return llvm::ArrayRef<uint8_t>();
-  }
-
-  Atom::ContentPermissions Atom::permissions() const { 
-    return perm___; 
-  }
-
-  Reference::iterator Atom::referencesBegin() const {
-    return 0;
-  }
-
-  Reference::iterator Atom::referencesEnd() const{
-    return 0;
-  }
-
-
-} // namespace lld

Modified: lld/trunk/lib/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/CMakeLists.txt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/CMakeLists.txt (original)
+++ lld/trunk/lib/Core/CMakeLists.txt Tue Jan 10 19:06:19 2012
@@ -1,5 +1,4 @@
 add_lld_library(lldCore
-  Atom.cpp
   File.cpp
   Resolver.cpp
   SymbolTable.cpp

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Jan 10 19:06:19 2012
@@ -19,17 +19,35 @@
 
 #include <algorithm>
 #include <cassert>
+
 #include <vector>
 
 namespace lld {
 
+/// This is used as a filter function to std::remove_if to dead strip atoms.  
 class NotLive {
 public:
+       NotLive(const llvm::DenseSet<const Atom*>& la) : _liveAtoms(la) { }
+  
   bool operator()(const Atom *atom) const {
-    return !(atom->live() || !atom->deadStrip());
+    // don't remove if live
+    if ( _liveAtoms.count(atom) )
+      return false;
+	// don't remove if marked never-dead-strip
+    if ( const DefinedAtom* defAtom = atom->definedAtom() ) {
+      if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
+        return false;
+    }
+    // do remove this atom
+    return true;
   }
+  
+private:
+  const llvm::DenseSet<const Atom*> _liveAtoms;
 };
 
+
+/// This is used as a filter function to std::remove_if to coalesced atoms.  
 class AtomCoalescedAway {
 public:
   AtomCoalescedAway(SymbolTable &sym) : _symbolTable(sym) {}
@@ -43,6 +61,9 @@
   SymbolTable &_symbolTable;
 };
 
+
+
+
 void Resolver::initializeState() {
   _platform.initialize();
 }
@@ -68,24 +89,34 @@
   _platform.fileAdded(file);
 }
 
+
+void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
+  // add to list of known atoms
+  _atoms.push_back(&atom);
+  
+  // tell symbol table
+  _symbolTable.add(atom);
+}
+
+
 // called on each atom when a file is added
-void Resolver::doAtom(const Atom &atom) {
+void Resolver::doDefinedAtom(const DefinedAtom &atom) {
   // notify platform
   _platform.atomAdded(atom);
 
   // add to list of known atoms
   _atoms.push_back(&atom);
-
+  
   // adjust scope (e.g. force some globals to be hidden)
   _platform.adjustScope(atom);
 
   // non-static atoms need extra handling
-  if (atom.scope() != Atom::scopeTranslationUnit) {
+  if (atom.scope() != DefinedAtom::scopeTranslationUnit) {
     // tell symbol table about non-static atoms
     _symbolTable.add(atom);
 
     // platform can add aliases for any symbol
-    std::vector<const Atom *> aliases;
+    std::vector<const DefinedAtom *> aliases;
     if (_platform.getAliasAtoms(atom, aliases))
       this->addAtoms(aliases);
   }
@@ -104,10 +135,10 @@
 }
 
 // utility to add a vector of atoms
-void Resolver::addAtoms(const std::vector<const Atom *> &newAtoms) {
-  for (std::vector<const Atom *>::const_iterator it = newAtoms.begin();
+void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
+  for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();
        it != newAtoms.end(); ++it) {
-    this->doAtom(**it);
+    this->doDefinedAtom(**it);
   }
 }
 
@@ -135,7 +166,7 @@
         // give platform a chance to instantiate platform
         // specific atoms (e.g. section boundary)
         if (!_symbolTable.isDefined(undefName)) {
-          std::vector<const Atom *> platAtoms;
+          std::vector<const DefinedAtom *> platAtoms;
           if (_platform.getPlatformAtoms(undefName, platAtoms))
             this->addAtoms(platAtoms);
         }
@@ -146,9 +177,10 @@
       std::vector<const Atom *> tents;
       for (std::vector<const Atom *>::iterator ait = _atoms.begin();
            ait != _atoms.end(); ++ait) {
-        const Atom *atom = *ait;
-        if (atom->definition() == Atom::definitionTentative)
-          tents.push_back(atom);
+        if ( const DefinedAtom* defAtom = (*ait)->definedAtom() ) {
+          if ( defAtom->merge() == DefinedAtom::mergeAsTentative )
+            tents.push_back(defAtom);
+        }
       }
       for (std::vector<const Atom *>::iterator dit = tents.begin();
            dit != tents.end(); ++dit) {
@@ -157,9 +189,10 @@
         llvm::StringRef tentName = (*dit)->name();
         const Atom *curAtom = _symbolTable.findByName(tentName);
         assert(curAtom != NULL);
-        if (curAtom->definition() == Atom::definitionTentative) {
-          _inputFiles.searchLibraries(tentName, searchDylibs, true, true,
-                                      *this);
+        if ( const DefinedAtom* curDefAtom = curAtom->definedAtom() ) {
+          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative )
+            _inputFiles.searchLibraries(tentName, searchDylibs, 
+                                        true, true, *this);
         }
       }
     }
@@ -171,10 +204,11 @@
 void Resolver::updateReferences() {
   for (std::vector<const Atom *>::iterator it = _atoms.begin();
        it != _atoms.end(); ++it) {
-    const Atom *atom = *it;
-    for (Reference::iterator rit = atom->referencesBegin(),
-         end = atom->referencesEnd(); rit != end; ++rit) {
-      rit->target = _symbolTable.replacement(rit->target);
+    if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {
+      for (Reference::iterator rit = defAtom->referencesBegin(),
+         end = defAtom->referencesEnd(); rit != end; ++rit) {
+        rit->target = _symbolTable.replacement(rit->target);
+      }
     }
   }
 }
@@ -195,19 +229,21 @@
   }
 
   // if already marked live, then done (stop recursion)
-  if (atom.live())
+  if ( _liveAtoms.count(&atom) )
     return;
 
   // mark this atom is live
-  const_cast<Atom *>(&atom)->setLive(true);
+  _liveAtoms.insert(&atom);
 
   // mark all atoms it references as live
   WhyLiveBackChain thisChain;
   thisChain.previous = previous;
   thisChain.referer = &atom;
-  for (Reference::iterator rit = atom.referencesBegin(),
-       end = atom.referencesEnd(); rit != end; ++rit) {
-    this->markLive(*(rit->target), &thisChain);
+  if ( const DefinedAtom* defAtom = atom.definedAtom() ) {
+    for (Reference::iterator rit = defAtom->referencesBegin(),
+        end = defAtom->referencesEnd(); rit != end; ++rit) {
+      this->markLive(*(rit->target), &thisChain);
+    }
   }
 }
 
@@ -218,11 +254,7 @@
     return;
 
   // clear liveness on all atoms
-  for (std::vector<const Atom *>::iterator it = _atoms.begin();
-       it != _atoms.end(); ++it) {
-    const Atom *atom = *it;
-    const_cast<Atom *>(atom)->setLive(0);
-  }
+  _liveAtoms.clear();
 
   // add entry point (main) to live roots
   const Atom *entry = this->entryPoint();
@@ -239,7 +271,7 @@
   }
 
   // add platform specific helper atoms
-  std::vector<const Atom *> platRootAtoms;
+  std::vector<const DefinedAtom *> platRootAtoms;
   if (_platform.getImplicitDeadStripRoots(platRootAtoms))
     this->addAtoms(platRootAtoms);
 
@@ -254,7 +286,7 @@
 
   // now remove all non-live atoms from _atoms
   _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
-                              NotLive()), _atoms.end());
+                              NotLive(_liveAtoms)), _atoms.end());
 }
 
 // error out if some undefines remain
@@ -270,7 +302,7 @@
     // when dead code stripping we don't care if dead atoms are undefined
     undefinedAtoms.erase(std::remove_if(
                            undefinedAtoms.begin(), undefinedAtoms.end(),
-                           NotLive()), undefinedAtoms.end());
+                           NotLive(_liveAtoms)), undefinedAtoms.end());
   }
 
   // let platform make error message about missing symbols
@@ -289,15 +321,16 @@
 void Resolver::checkDylibSymbolCollisions() {
   for (std::vector<const Atom *>::const_iterator it = _atoms.begin();
        it != _atoms.end(); ++it) {
-    const Atom *atom = *it;
-    if (atom->scope() == Atom::scopeGlobal) {
-      if (atom->definition() == Atom::definitionTentative) {
-        // See if any shared library also has symbol which
-        // collides with the tentative definition.
-        // SymbolTable will warn if needed.
-        _inputFiles.searchLibraries(atom->name(), true, false, false, *this);
-      }
-    }
+    const DefinedAtom* defAtom = (*it)->definedAtom();
+    if ( defAtom == NULL ) 
+      continue;
+    if ( defAtom->merge() != DefinedAtom::mergeAsTentative ) 
+      continue;
+    assert(defAtom->scope() != DefinedAtom::scopeTranslationUnit);
+    // See if any shared library also has symbol which
+    // collides with the tentative definition.
+    // SymbolTable will warn if needed.
+    _inputFiles.searchLibraries(defAtom->name(), true, false, false, *this);
   }
 }
 

Modified: lld/trunk/lib/Core/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/SymbolTable.cpp (original)
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue Jan 10 19:06:19 2012
@@ -9,6 +9,8 @@
 
 #include "lld/Core/SymbolTable.h"
 #include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
 #include "lld/Core/File.h"
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/Resolver.h"
@@ -30,12 +32,16 @@
   : _platform(plat) {
 }
 
-void SymbolTable::add(const Atom &atom) {
-  assert(atom.scope() != Atom::scopeTranslationUnit);
+void SymbolTable::add(const UndefinedAtom &atom) {
+  this->addByName(atom);
+}
+
+void SymbolTable::add(const DefinedAtom &atom) {
+  assert(atom.scope() != DefinedAtom::scopeTranslationUnit);
   if ( !atom.internalName() ) {
     this->addByName(atom);
   }
-  else if ( atom.mergeDuplicates() ) {
+  else {
     this->addByContent(atom);
   }
 }
@@ -43,37 +49,27 @@
 enum NameCollisionResolution {
   NCR_First,
   NCR_Second,
-  NCR_Weak,
-  NCR_Larger,
   NCR_Dup,
   NCR_Error
 };
 
-static NameCollisionResolution cases[6][6] = {
-  //regular     weak         tentative   absolute    undef      sharedLib
+static NameCollisionResolution cases[4][4] = {
+  //regular     absolute    undef      sharedLib
   {
     // first is regular
-    NCR_Dup,    NCR_First,   NCR_First,  NCR_Error,  NCR_First, NCR_First
-  },
-  {
-    // first is weak
-    NCR_Second, NCR_Weak,   NCR_Larger, NCR_Error,  NCR_First, NCR_First
-  },
-  {
-    // first is tentative
-    NCR_Second, NCR_Second, NCR_Larger, NCR_Error,  NCR_First, NCR_First
+    NCR_Dup,   NCR_Error,   NCR_First, NCR_First
   },
   {
     // first is absolute
-    NCR_Error,  NCR_Error,  NCR_Error,  NCR_Error,  NCR_First, NCR_First
+    NCR_Error,  NCR_Error,  NCR_First, NCR_First
   },
   {
     // first is undef
-    NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_Second
+    NCR_Second, NCR_Second, NCR_First, NCR_Second
   },
   {
     // first is sharedLib
-    NCR_Second, NCR_Second, NCR_Second, NCR_Second, NCR_First, NCR_First
+    NCR_Second, NCR_Second, NCR_First, NCR_First
   }
 };
 
@@ -82,6 +78,40 @@
   return cases[first][second];
 }
 
+
+enum MergeResolution {
+  MCR_First,
+  MCR_Second,
+  MCR_Largest,
+  MCR_Error
+};
+
+static MergeResolution mergeCases[4][4] = {
+  // no        tentative     weak       weakAddressUsed
+  {
+    // first is no
+    MCR_Error,  MCR_First,   MCR_First, MCR_First
+  },
+  {
+    // first is tentative
+    MCR_Second, MCR_Largest, MCR_Second, MCR_Second
+  },
+  {
+    // first is weak
+    MCR_Second, MCR_First,   MCR_First, MCR_Second
+  },
+  {
+    // first is weakAddressUsed
+    MCR_Second, MCR_First,   MCR_First, MCR_First
+  }
+};
+
+static MergeResolution mergeSelect(DefinedAtom::Merge first, 
+                                   DefinedAtom::Merge second) {
+  return mergeCases[first][second];
+}
+
+
 void SymbolTable::addByName(const Atom & newAtom) {
   llvm::StringRef name = newAtom.name();
   const Atom *existing = this->findByName(name);
@@ -93,31 +123,33 @@
     // Name is already in symbol table and associated with another atom.
     bool useNew = true;
     switch (collide(existing->definition(), newAtom.definition())) {
-    case NCR_First:
-      useNew = false;
-      break;
-    case NCR_Second:
-      useNew = true;
-      break;
-    case NCR_Dup:
-      if ( existing->mergeDuplicates() && newAtom.mergeDuplicates() ) {
-        // Both mergeable.  Use auto-hide bit as tie breaker
-        if ( existing->autoHide() != newAtom.autoHide() ) {
-          // They have different autoHide values, keep non-autohide one
-          useNew = existing->autoHide();
-        }
-        else {
-          // They have same autoHide, so just keep using existing
-          useNew = false;
+      case NCR_First:
+        useNew = false;
+        break;
+      case NCR_Second:
+        useNew = true;
+        break;
+      case NCR_Dup:
+        assert(existing->definition() == Atom::definitionRegular);
+        assert(newAtom.definition() == Atom::definitionRegular);
+        switch ( mergeSelect(((DefinedAtom*)existing)->merge(), 
+                            ((DefinedAtom*)(&newAtom))->merge()) ) {
+          case MCR_First:
+            useNew = false;
+            break;
+          case MCR_Second:
+            useNew = true;
+            break;
+          case MCR_Largest:
+            useNew = true;
+            break;
+          case MCR_Error:
+            llvm::report_fatal_error("duplicate symbol error");
+            break;
         }
-      }
-      else {
-        const Atom& use = _platform.handleMultipleDefinitions(*existing, newAtom);
-        useNew = ( &use != existing ); 
-      }
-      break;
-    default:
-      llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
+        break;
+      default:
+        llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause");
     }
     if ( useNew ) {
       // Update name table to use new atom.
@@ -133,9 +165,9 @@
 }
 
 
-unsigned SymbolTable::MyMappingInfo::getHashValue(const Atom * const atom) {
+unsigned SymbolTable::MyMappingInfo::getHashValue(const DefinedAtom * const atom) {
   unsigned hash = atom->size();
-  if ( atom->contentType() != Atom::typeZeroFill ) {
+  if ( atom->contentType() != DefinedAtom::typeZeroFill ) {
     llvm::ArrayRef<uint8_t> content = atom->rawContent();
     for (unsigned int i=0; i < content.size(); ++i) {
       hash = hash * 33 + content[i];
@@ -148,8 +180,8 @@
 }
 
 
-bool SymbolTable::MyMappingInfo::isEqual(const Atom * const l, 
-                                         const Atom * const r) {
+bool SymbolTable::MyMappingInfo::isEqual(const DefinedAtom * const l, 
+                                         const DefinedAtom * const r) {
   if ( l == r )
     return true;
   if ( l == getEmptyKey() )
@@ -171,7 +203,7 @@
 }
 
 
-void SymbolTable::addByContent(const Atom & newAtom) {
+void SymbolTable::addByContent(const DefinedAtom & newAtom) {
   AtomContentSet::iterator pos = _contentTable.find(&newAtom);
   if ( pos == _contentTable.end() ) {
     _contentTable.insert(&newAtom);

Modified: lld/trunk/lib/Core/YamlKeyValues.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Tue Jan 10 19:06:19 2012
@@ -18,61 +18,33 @@
 
 
 const char* const KeyValues::nameKeyword            = "name";
-const char* const KeyValues::scopeKeyword           = "scope";
 const char* const KeyValues::definitionKeyword      = "definition";
+const char* const KeyValues::scopeKeyword           = "scope";
 const char* const KeyValues::contentTypeKeyword     = "type";
 const char* const KeyValues::deadStripKindKeyword   = "dead-strip";
 const char* const KeyValues::sectionChoiceKeyword   = "section-choice";
 const char* const KeyValues::internalNameKeyword    = "internal-name";
-const char* const KeyValues::mergeDuplicatesKeyword = "merge-duplicates";
-const char* const KeyValues::autoHideKeyword        = "auto-hide";
+const char* const KeyValues::interposableKeyword    = "interposable";
+const char* const KeyValues::mergeKeyword           = "merge";
 const char* const KeyValues::isThumbKeyword         = "is-thumb";
 const char* const KeyValues::isAliasKeyword         = "is-alias";
 const char* const KeyValues::sectionNameKeyword     = "section-name";
 const char* const KeyValues::contentKeyword         = "content";
 const char* const KeyValues::sizeKeyword            = "size";
+const char* const KeyValues::permissionsKeyword      = "permissions";
 
 
-const Atom::Scope         KeyValues::scopeDefault = Atom::scopeTranslationUnit;
-const Atom::Definition    KeyValues::definitionDefault = Atom::definitionRegular;
-const Atom::ContentType   KeyValues::contentTypeDefault = Atom::typeData;
-const Atom::DeadStripKind KeyValues::deadStripKindDefault = Atom::deadStripNormal;
-const Atom::SectionChoice KeyValues::sectionChoiceDefault = Atom::sectionBasedOnContent;
-const bool                KeyValues::internalNameDefault = false;
-const bool                KeyValues::mergeDuplicatesDefault = false;
-const bool                KeyValues::autoHideDefault = false;
-const bool                KeyValues::isThumbDefault = false;
-const bool                KeyValues::isAliasDefault = false;
-
-
-struct ScopeMapping {
-	const char* string;
-	Atom::Scope value;
-};
-
-static const ScopeMapping scopeMappings[] = {
-	{ "global", Atom::scopeGlobal },
-	{ "hidden", Atom::scopeLinkageUnit },
-	{ "static", Atom::scopeTranslationUnit },
-  { NULL,     Atom::scopeGlobal }
-};
-  
-Atom::Scope KeyValues::scope(const char* s)
-{
-	for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
-    if ( strcmp(p->string, s) == 0 )
-      return p->value;
-  }
-  llvm::report_fatal_error("bad scope value");
-}
-
-const char* KeyValues::scope(Atom::Scope s) {
-	for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
-    if ( p->value == s )
-      return p->string;
-  }
-  llvm::report_fatal_error("bad scope value");
-}
+const DefinedAtom::Definition         KeyValues::definitionDefault = Atom::definitionRegular;
+const DefinedAtom::Scope              KeyValues::scopeDefault = DefinedAtom::scopeTranslationUnit;
+const DefinedAtom::ContentType        KeyValues::contentTypeDefault = DefinedAtom::typeData;
+const DefinedAtom::DeadStripKind      KeyValues::deadStripKindDefault = DefinedAtom::deadStripNormal;
+const DefinedAtom::SectionChoice      KeyValues::sectionChoiceDefault = DefinedAtom::sectionBasedOnContent;
+const DefinedAtom::Interposable       KeyValues::interposableDefault = DefinedAtom::interposeNo;
+const DefinedAtom::Merge              KeyValues::mergeDefault = DefinedAtom::mergeNo;
+const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;
+const bool                            KeyValues::internalNameDefault = false;
+const bool                            KeyValues::isThumbDefault = false;
+const bool                            KeyValues::isAliasDefault = false;
 
 
 
@@ -85,8 +57,6 @@
 
 static const DefinitionMapping defMappings[] = {
 	{ "regular",        Atom::definitionRegular },
-	{ "weak",           Atom::definitionWeak },
-	{ "tentative",      Atom::definitionTentative },
 	{ "absolute",       Atom::definitionAbsolute },
 	{ "undefined",      Atom::definitionUndefined },
 	{ "shared-library", Atom::definitionSharedLibrary },
@@ -114,40 +84,76 @@
 
 
 
+struct ScopeMapping {
+	const char* string;
+	DefinedAtom::Scope value;
+};
+
+static const ScopeMapping scopeMappings[] = {
+	{ "global", DefinedAtom::scopeGlobal },
+	{ "hidden", DefinedAtom::scopeLinkageUnit },
+	{ "static", DefinedAtom::scopeTranslationUnit },
+  { NULL,     DefinedAtom::scopeGlobal }
+};
+  
+DefinedAtom::Scope KeyValues::scope(const char* s)
+{
+	for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
+    if ( strcmp(p->string, s) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad scope value");
+}
+
+const char* KeyValues::scope(DefinedAtom::Scope s) {
+	for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad scope value");
+}
+
+
+
+
+
+
+
+
 struct ContentTypeMapping {
 	const char*       string;
-	Atom::ContentType  value;
+	DefinedAtom::ContentType  value;
 };
 
 static const ContentTypeMapping typeMappings[] = {
-	{ "unknown",        Atom::typeUnknown },
-	{ "code",           Atom::typeCode },
-	{ "resolver",       Atom::typeResolver },
-	{ "constant",       Atom::typeConstant },
-	{ "c-string",       Atom::typeCString },
-	{ "utf16-string",   Atom::typeUTF16String },
-	{ "CFI",            Atom::typeCFI },
-	{ "LSDA",           Atom::typeLSDA },
-	{ "literal-4",      Atom::typeLiteral4 },
-	{ "literal-8",      Atom::typeLiteral8 },
-	{ "literal-16",     Atom::typeLiteral16 },
-	{ "data",           Atom::typeData },
-	{ "zero-fill",      Atom::typeZeroFill },
-	{ "cf-string",      Atom::typeCFString },
-	{ "initializer-ptr",Atom::typeInitializerPtr },
-	{ "terminator-ptr", Atom::typeTerminatorPtr },
-	{ "c-string-ptr",   Atom::typeCStringPtr },
-	{ "objc1-class",    Atom::typeObjC1Class },
-	{ "objc1-class-ptr",Atom::typeObjCClassPtr },
-	{ "objc2-cat-ptr",  Atom::typeObjC2CategoryList },
-	{ "tlv-thunk",      Atom::typeThunkTLV },
-	{ "tlv-data",       Atom::typeTLVInitialData },
-	{ "tlv-zero-fill",  Atom::typeTLVInitialZeroFill },
-	{ "tlv-init-ptr",   Atom::typeTLVInitializerPtr },
-  { NULL,             Atom::typeUnknown }
+	{ "unknown",        DefinedAtom::typeUnknown },
+	{ "code",           DefinedAtom::typeCode },
+	{ "resolver",       DefinedAtom::typeResolver },
+	{ "constant",       DefinedAtom::typeConstant },
+	{ "c-string",       DefinedAtom::typeCString },
+	{ "utf16-string",   DefinedAtom::typeUTF16String },
+	{ "CFI",            DefinedAtom::typeCFI },
+	{ "LSDA",           DefinedAtom::typeLSDA },
+	{ "literal-4",      DefinedAtom::typeLiteral4 },
+	{ "literal-8",      DefinedAtom::typeLiteral8 },
+	{ "literal-16",     DefinedAtom::typeLiteral16 },
+	{ "data",           DefinedAtom::typeData },
+	{ "zero-fill",      DefinedAtom::typeZeroFill },
+	{ "cf-string",      DefinedAtom::typeCFString },
+	{ "initializer-ptr",DefinedAtom::typeInitializerPtr },
+	{ "terminator-ptr", DefinedAtom::typeTerminatorPtr },
+	{ "c-string-ptr",   DefinedAtom::typeCStringPtr },
+	{ "objc1-class",    DefinedAtom::typeObjC1Class },
+	{ "objc1-class-ptr",DefinedAtom::typeObjCClassPtr },
+	{ "objc2-cat-ptr",  DefinedAtom::typeObjC2CategoryList },
+	{ "tlv-thunk",      DefinedAtom::typeThunkTLV },
+	{ "tlv-data",       DefinedAtom::typeTLVInitialData },
+	{ "tlv-zero-fill",  DefinedAtom::typeTLVInitialZeroFill },
+	{ "tlv-init-ptr",   DefinedAtom::typeTLVInitializerPtr },
+  { NULL,             DefinedAtom::typeUnknown }
 };
 
-Atom::ContentType KeyValues::contentType(const char* s)
+DefinedAtom::ContentType KeyValues::contentType(const char* s)
 {
 	for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
     if ( strcmp(p->string, s) == 0 )
@@ -156,7 +162,7 @@
   llvm::report_fatal_error("bad content type value");
 }
 
-const char* KeyValues::contentType(Atom::ContentType s) {
+const char* KeyValues::contentType(DefinedAtom::ContentType s) {
 	for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
     if ( p->value == s )
       return p->string;
@@ -172,17 +178,17 @@
 
 struct DeadStripMapping {
 	const char*           string;
-	Atom::DeadStripKind   value;
+	DefinedAtom::DeadStripKind   value;
 };
 
 static const DeadStripMapping deadStripMappings[] = {
-	{ "normal",         Atom::deadStripNormal },
-	{ "never",          Atom::deadStripNever },
-	{ "always",         Atom::deadStripAlways },
-  { NULL,             Atom::deadStripNormal }
+	{ "normal",         DefinedAtom::deadStripNormal },
+	{ "never",          DefinedAtom::deadStripNever },
+	{ "always",         DefinedAtom::deadStripAlways },
+  { NULL,             DefinedAtom::deadStripNormal }
 };
 
-Atom::DeadStripKind KeyValues::deadStripKind(const char* s)
+DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s)
 {
 	for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
     if ( strcmp(p->string, s) == 0 )
@@ -191,7 +197,7 @@
   llvm::report_fatal_error("bad dead strip value");
 }
 
-const char* KeyValues::deadStripKind(Atom::DeadStripKind dsk) {
+const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
 	for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
     if ( p->value == dsk )
       return p->string;
@@ -203,34 +209,33 @@
 
 
 
-
-struct SectionChoiceMapping {
+struct InterposableMapping {
 	const char*           string;
-	Atom::SectionChoice   value;
+	DefinedAtom::Interposable   value;
 };
 
-static const SectionChoiceMapping sectMappings[] = {
-	{ "content",         Atom::sectionBasedOnContent },
-	{ "custom",          Atom::sectionCustomPreferred },
-	{ "custom-required", Atom::sectionCustomRequired },
-  { NULL,              Atom::sectionBasedOnContent }
+static const InterposableMapping interMappings[] = {
+	{ "no",           DefinedAtom::interposeNo },
+	{ "yes",          DefinedAtom::interposeYes },
+	{ "yesAndWeak",   DefinedAtom::interposeYesAndRuntimeWeak },
+  { NULL,           DefinedAtom::interposeNo }
 };
 
-Atom::SectionChoice KeyValues::sectionChoice(const char* s)
+DefinedAtom::Interposable KeyValues::interposable(const char* s)
 {
-	for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
+	for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
     if ( strcmp(p->string, s) == 0 )
       return p->value;
   }
-  llvm::report_fatal_error("bad dead strip value");
+  llvm::report_fatal_error("bad interposable value");
 }
 
-const char* KeyValues::sectionChoice(Atom::SectionChoice s) {
-	for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
-    if ( p->value == s )
+const char* KeyValues::interposable(DefinedAtom::Interposable in) {
+	for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
+    if ( p->value == in )
       return p->string;
   }
-  llvm::report_fatal_error("bad dead strip value");
+  llvm::report_fatal_error("bad interposable value");
 }
 
 
@@ -238,18 +243,34 @@
 
 
 
+struct MergeMapping {
+	const char*          string;
+	DefinedAtom::Merge   value;
+};
 
-bool KeyValues::internalName(const char* s)
+static const MergeMapping mergeMappings[] = {
+	{ "no",             DefinedAtom::mergeNo },
+	{ "asTentative",    DefinedAtom::mergeAsTentative },
+	{ "asWeak",         DefinedAtom::mergeAsWeak },
+	{ "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed },
+  { NULL,             DefinedAtom::mergeNo }
+};
+
+DefinedAtom::Merge KeyValues::merge(const char* s)
 {
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad internal-name value");
+	for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
+    if ( strcmp(p->string, s) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad merge value");
 }
 
-const char* KeyValues::internalName(bool b) {
-  return b ? "true" : "false";
+const char* KeyValues::merge(DefinedAtom::Merge in) {
+	for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
+    if ( p->value == in )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad merge value");
 }
 
 
@@ -257,17 +278,33 @@
 
 
 
-bool KeyValues::mergeDuplicates(const char* s)
+struct SectionChoiceMapping {
+	const char*                 string;
+	DefinedAtom::SectionChoice  value;
+};
+
+static const SectionChoiceMapping sectMappings[] = {
+	{ "content",         DefinedAtom::sectionBasedOnContent },
+	{ "custom",          DefinedAtom::sectionCustomPreferred },
+	{ "custom-required", DefinedAtom::sectionCustomRequired },
+  { NULL,              DefinedAtom::sectionBasedOnContent }
+};
+
+DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s)
 {
-  if ( strcmp(s, "true") == 0 )
-    return true;
-  else if ( strcmp(s, "false") == 0 )
-    return false;
-  llvm::report_fatal_error("bad merge-duplicates value");
+	for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
+    if ( strcmp(p->string, s) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad dead strip value");
 }
 
-const char* KeyValues::mergeDuplicates(bool b) {
-  return b ? "true" : "false";
+const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
+	for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad dead strip value");
 }
 
 
@@ -275,23 +312,60 @@
 
 
 
-bool KeyValues::autoHide(const char* s)
+
+struct PermissionsMapping {
+	const char*                      string;
+	DefinedAtom::ContentPermissions  value;
+};
+
+static const PermissionsMapping permMappings[] = {
+	{ "content",         DefinedAtom::perm___ },
+	{ "custom",          DefinedAtom::permR__ },
+	{ "custom-required", DefinedAtom::permR_X },
+	{ "custom-required", DefinedAtom::permRW_ },
+	{ "custom-required", DefinedAtom::permRW_L },
+  { NULL,              DefinedAtom::perm___ }
+};
+
+DefinedAtom::ContentPermissions KeyValues::permissions(const char* s)
+{
+	for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) {
+    if ( strcmp(p->string, s) == 0 )
+      return p->value;
+  }
+  llvm::report_fatal_error("bad permissions value");
+}
+
+const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
+	for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) {
+    if ( p->value == s )
+      return p->string;
+  }
+  llvm::report_fatal_error("bad permissions value");
+}
+
+
+
+
+
+
+
+bool KeyValues::internalName(const char* s)
 {
   if ( strcmp(s, "true") == 0 )
     return true;
   else if ( strcmp(s, "false") == 0 )
     return false;
-  llvm::report_fatal_error("bad auto-hide value");
+  llvm::report_fatal_error("bad internal-name value");
 }
 
-const char* KeyValues::autoHide(bool b) {
+const char* KeyValues::internalName(bool b) {
   return b ? "true" : "false";
 }
 
 
 
 
-
 bool KeyValues::isThumb(const char* s)
 {
   if ( strcmp(s, "true") == 0 )

Modified: lld/trunk/lib/Core/YamlKeyValues.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlKeyValues.h (original)
+++ lld/trunk/lib/Core/YamlKeyValues.h Tue Jan 10 19:06:19 2012
@@ -11,6 +11,7 @@
 #define LLD_CORE_YAML_KEY_VALUES_H_
 
 #include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
 
 
 namespace lld {
@@ -18,61 +19,65 @@
 
 class KeyValues {
 public:
-  static const char* const          nameKeyword;
-  static const char* const          sectionNameKeyword;
-  static const char* const          contentKeyword;
-  static const char* const          sizeKeyword;
+  static const char* const                nameKeyword;
+  static const char* const                sectionNameKeyword;
+  static const char* const                contentKeyword;
+  static const char* const                sizeKeyword;
   
-
-  static const char* const          scopeKeyword;
-  static const Atom::Scope          scopeDefault;
-  static Atom::Scope                scope(const char*);
-  static const char*                scope(Atom::Scope);
+  static const char* const                definitionKeyword;
+  static const Atom::Definition           definitionDefault;
+  static Atom::Definition                 definition(const char*);
+  static const char*                      definition(Atom::Definition);
+
+  static const char* const                scopeKeyword;
+  static const DefinedAtom::Scope         scopeDefault;
+  static DefinedAtom::Scope               scope(const char*);
+  static const char*                      scope(DefinedAtom::Scope);
   
-  static const char* const          definitionKeyword;
-  static const Atom::Definition     definitionDefault;
-  static Atom::Definition           definition(const char*);
-  static const char*                definition(Atom::Definition);
-
-  static const char* const          contentTypeKeyword;
-  static const Atom::ContentType    contentTypeDefault;
-  static Atom::ContentType          contentType(const char*);
-  static const char*                contentType(Atom::ContentType);
-
-  static const char* const          deadStripKindKeyword;
-  static const Atom::DeadStripKind  deadStripKindDefault;
-  static Atom::DeadStripKind        deadStripKind(const char*);
-  static const char*                deadStripKind(Atom::DeadStripKind);
-
-  static const char* const          sectionChoiceKeyword;
-  static const Atom::SectionChoice  sectionChoiceDefault;
-  static Atom::SectionChoice        sectionChoice(const char*);
-  static const char*                sectionChoice(Atom::SectionChoice);
-
-  static const char* const          internalNameKeyword;
-  static const bool                 internalNameDefault;
-  static bool                       internalName(const char*);
-  static const char*                internalName(bool);
-
-  static const char* const          mergeDuplicatesKeyword;
-  static const bool                 mergeDuplicatesDefault;
-  static bool                       mergeDuplicates(const char*);
-  static const char*                mergeDuplicates(bool);
-
-  static const char* const          autoHideKeyword;
-  static const bool                 autoHideDefault;
-  static bool                       autoHide(const char*);
-  static const char*                autoHide(bool);
-
-  static const char* const          isThumbKeyword;
-  static const bool                 isThumbDefault;
-  static bool                       isThumb(const char*);
-  static const char*                isThumb(bool);
-
-  static const char* const          isAliasKeyword;
-  static const bool                 isAliasDefault;
-  static bool                       isAlias(const char*);
-  static const char*                isAlias(bool);
+  static const char* const                contentTypeKeyword;
+  static const DefinedAtom::ContentType   contentTypeDefault;
+  static DefinedAtom::ContentType         contentType(const char*);
+  static const char*                      contentType(DefinedAtom::ContentType);
+
+  static const char* const                deadStripKindKeyword;
+  static const DefinedAtom::DeadStripKind deadStripKindDefault;
+  static DefinedAtom::DeadStripKind       deadStripKind(const char*);
+  static const char*                      deadStripKind(DefinedAtom::DeadStripKind);
+
+  static const char* const                sectionChoiceKeyword;
+  static const DefinedAtom::SectionChoice sectionChoiceDefault;
+  static DefinedAtom::SectionChoice       sectionChoice(const char*);
+  static const char*                      sectionChoice(DefinedAtom::SectionChoice);
+
+  static const char* const                interposableKeyword;
+  static const DefinedAtom::Interposable  interposableDefault;
+  static DefinedAtom::Interposable        interposable(const char*);
+  static const char*                      interposable(DefinedAtom::Interposable);
+
+  static const char* const                mergeKeyword;
+  static const DefinedAtom::Merge         mergeDefault;
+  static DefinedAtom::Merge               merge(const char*);
+  static const char*                      merge(DefinedAtom::Merge);
+
+  static const char* const                      permissionsKeyword;
+  static const DefinedAtom::ContentPermissions  permissionsDefault;
+  static DefinedAtom::ContentPermissions        permissions(const char*);
+  static const char*                            permissions(DefinedAtom::ContentPermissions);
+
+  static const char* const                internalNameKeyword;
+  static const bool                       internalNameDefault;
+  static bool                             internalName(const char*);
+  static const char*                      internalName(bool);
+
+  static const char* const                isThumbKeyword;
+  static const bool                       isThumbDefault;
+  static bool                             isThumb(const char*);
+  static const char*                      isThumb(bool);
+
+  static const char* const                isAliasKeyword;
+  static const bool                       isAliasDefault;
+  static bool                             isAlias(const char*);
+  static const char*                      isAlias(bool);
 
 };
 

Modified: lld/trunk/lib/Core/YamlReader.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlReader.cpp (original)
+++ lld/trunk/lib/Core/YamlReader.cpp Tue Jan 10 19:06:19 2012
@@ -289,16 +289,17 @@
   virtual bool justInTimeforEachAtom(llvm::StringRef name,
                                      File::AtomHandler &) const;
 
-  std::vector<Atom *> _atoms;
+  std::vector<DefinedAtom*> _definedAtoms;
+  std::vector<UndefinedAtom*> _undefinedAtoms;
   std::vector<Reference> _references;
   unsigned int _lastRefIndex;
 };
 
 bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
   handler.doFile(*this);
-  for (std::vector<Atom *>::const_iterator it = _atoms.begin();
-       it != _atoms.end(); ++it) {
-    handler.doAtom(**it);
+  for (std::vector<DefinedAtom *>::const_iterator it = _definedAtoms.begin();
+       it != _definedAtoms.end(); ++it) {
+    handler.doDefinedAtom(**it);
   }
   return true;
 }
@@ -309,90 +310,153 @@
 }
 
 
-class YAMLAtom : public Atom {
+class YAMLDefinedAtom : public DefinedAtom {
 public:
-  YAMLAtom( uint64_t ord
-          , Definition d
-          , Scope s
-          , ContentType ct
-          , SectionChoice sc
-          , bool intn
-          , bool md
-          , bool ah
-          , DeadStripKind dsk
-          , bool tb
-          , bool al
-          , Alignment a
-          , YAMLFile& f
-          , const char *n
-          , const char* sn
-          , uint64_t sz
-          , std::vector<uint8_t>* c)
-    : Atom(ord, d, s, ct, sc, intn, md, ah, dsk, tb, al, a)
-    , _file(f)
-    , _name(n)
-    , _sectionName(sn)
-    , _content(c)
-    , _size(sz)
-    , _refStartIndex(f._lastRefIndex)
-    , _refEndIndex(f._references.size()) {
-    f._lastRefIndex = _refEndIndex;
+  YAMLDefinedAtom( uint32_t ord
+          , YAMLFile& file
+          , DefinedAtom::Scope scope
+          , DefinedAtom::ContentType type
+          , DefinedAtom::SectionChoice sectionChoice
+          , DefinedAtom::Interposable interpose
+          , DefinedAtom::Merge merge
+          , DefinedAtom::DeadStripKind deadStrip
+          , DefinedAtom::ContentPermissions perms
+          , bool internalName
+          , bool isThumb
+          , bool isAlias
+          , DefinedAtom::Alignment alignment
+          , const char* name
+          , const char* sectionName
+          , uint64_t size
+          , std::vector<uint8_t>* content)
+    : _file(file)
+    , _name(name)
+    , _sectionName(sectionName)
+    , _size(size)
+    , _ord(ord)
+    , _content(content)
+    , _alignment(alignment)
+    , _scope(scope)
+    , _type(type)
+    , _sectionChoice(sectionChoice)
+    , _interpose(interpose)
+    , _merge(merge)
+    , _deadStrip(deadStrip)
+    , _permissions(perms)
+    , _internalName(internalName)
+    , _isThumb(isThumb)
+    , _isAlias(isAlias)
+    , _refStartIndex(file._lastRefIndex)
+    , _refEndIndex(file._references.size()) {
+    file._lastRefIndex = _refEndIndex;
   }
 
   virtual const class File& file() const {
     return _file;
   }
 
-  virtual bool translationUnitSource(const char* *dir, const char* *name) const{
-    return false;
-  }
-
   virtual llvm::StringRef name() const {
     return _name;
   }
+
+  virtual bool internalName() const {
+    return _internalName;
+  }
   
-  virtual llvm::StringRef customSectionName() const {
-    return (_sectionName ? _sectionName : llvm::StringRef());
+ virtual uint64_t size() const {
+    return (_content ? _content->size() : _size);
   }
 
-  virtual uint64_t objectAddress() const {
-    return 0;
+  virtual DefinedAtom::Scope scope() const {
+    return _scope;
+  }
+  
+  virtual DefinedAtom::Interposable interposable() const {
+    return _interpose;
+  }
+  
+  virtual DefinedAtom::Merge merge() const {
+    return _merge;
   }
 
-  virtual uint64_t size() const {
-    return (_content ? _content->size() : _size);
+  virtual DefinedAtom::ContentType contentType() const {
+    return _type;
+  }
+    
+  virtual DefinedAtom::Alignment alignment() const {
+    return _alignment;
+  }
+  
+  virtual DefinedAtom::SectionChoice sectionChoice() const {
+    return _sectionChoice;
   }
 
-  llvm::ArrayRef<uint8_t> rawContent() const {
+  virtual llvm::StringRef customSectionName() const {
+    return _sectionName;
+  }
+    
+  virtual DefinedAtom::DeadStripKind deadStrip() const {
+    return _deadStrip;
+  }
+    
+  virtual DefinedAtom::ContentPermissions permissions() const {
+    return _permissions;
+  }
+  
+  virtual bool isThumb() const {
+    return _isThumb;
+  }
+    
+  virtual bool isAlias() const {
+    return _isAlias;
+  }
+  
+ llvm::ArrayRef<uint8_t> rawContent() const {
     if ( _content != NULL ) 
       return llvm::ArrayRef<uint8_t>(*_content);
     else
       return llvm::ArrayRef<uint8_t>();
   }
+ 
+  virtual uint64_t ordinal() const {
+    return _ord;
+  }
+
+  
+  virtual Reference::iterator referencesBegin() const {
+    if (_file._references.size() < _refStartIndex)
+      return (Reference::iterator)&_file._references[_refStartIndex];
+    return 0;
+  }
+  
+  virtual Reference::iterator referencesEnd() const {
+    if (_file._references.size() < _refEndIndex)
+      return (Reference::iterator)&_file._references[_refEndIndex];
+    return 0;
+  }
   
-  virtual Reference::iterator referencesBegin() const;
-  virtual Reference::iterator referencesEnd() const;
 private:
-  YAMLFile&             _file;
-  const char *          _name;
-  const char *          _sectionName;
-  std::vector<uint8_t>* _content;
-  unsigned long         _size;
-  unsigned int          _refStartIndex;
-  unsigned int          _refEndIndex;
+  YAMLFile&                   _file;
+  const char *                _name;
+  const char *                _sectionName;
+  unsigned long               _size;
+  uint32_t                    _ord;
+  std::vector<uint8_t>*       _content;
+  DefinedAtom::Alignment      _alignment;
+  DefinedAtom::Scope          _scope;
+  DefinedAtom::ContentType    _type;
+  DefinedAtom::SectionChoice  _sectionChoice;
+  DefinedAtom::Interposable   _interpose;
+  DefinedAtom::Merge          _merge;
+  DefinedAtom::DeadStripKind  _deadStrip;
+  DefinedAtom::ContentPermissions _permissions;
+  bool                        _internalName;
+  bool                        _isThumb;
+  bool                        _isAlias;
+  unsigned int                _refStartIndex;
+  unsigned int                _refEndIndex;
 };
 
-Reference::iterator YAMLAtom::referencesBegin() const {
-  if (_file._references.size() < _refStartIndex)
-    return (Reference::iterator)&_file._references[_refStartIndex];
-  return 0;
-}
-
-Reference::iterator YAMLAtom::referencesEnd() const {
-  if (_file._references.size() < _refEndIndex)
-    return (Reference::iterator)&_file._references[_refEndIndex];
-  return 0;
-}
 
 class YAMLAtomState {
 public:
@@ -408,42 +472,46 @@
 
   void makeAtom(YAMLFile&);
 
-  uint64_t  _ordinal;
-  long long _size;
-  const char *_name;
-  Atom::Alignment _align;
-  Atom::ContentType _type;
-  Atom::Scope _scope;
-  Atom::Definition _def;
-  Atom::SectionChoice _sectionChoice;
-  bool _internalName;
-  bool _mergeDuplicates;
-  Atom::DeadStripKind _deadStrip;
-  bool _thumb;
-  bool _alias;
-  bool _autoHide;
-  const char *_sectionName;
-  std::vector<uint8_t>* _content;
-  Reference _ref;
+  const char *                _name;
+  const char *                _sectionName;
+  unsigned long long          _size;
+  uint32_t                    _ordinal;
+  std::vector<uint8_t>*       _content;
+  DefinedAtom::Alignment      _alignment;
+  Atom::Definition            _definition;
+  DefinedAtom::Scope          _scope;
+  DefinedAtom::ContentType    _type;
+  DefinedAtom::SectionChoice  _sectionChoice;
+  DefinedAtom::Interposable   _interpose;
+  DefinedAtom::Merge          _merge;
+  DefinedAtom::DeadStripKind  _deadStrip;
+  DefinedAtom::ContentPermissions _permissions;
+  bool                        _internalName;
+  bool                        _isThumb;
+  bool                        _isAlias;
+  Reference                   _ref;
 };
 
+
 YAMLAtomState::YAMLAtomState()
-  : _ordinal(0)
+  : _name(NULL)
+  , _sectionName(NULL)
   , _size(0)
-  , _name(NULL)
-  , _align(0, 0)
-  , _type(KeyValues::contentTypeDefault)
+  , _ordinal(0)
+  , _content(NULL) 
+  , _alignment(0, 0)
+  , _definition(KeyValues::definitionDefault)
   , _scope(KeyValues::scopeDefault)
-  , _def(KeyValues::definitionDefault)
+  , _type(KeyValues::contentTypeDefault)
   , _sectionChoice(KeyValues::sectionChoiceDefault)
-  , _internalName(KeyValues::internalNameDefault)
-  , _mergeDuplicates(KeyValues::mergeDuplicatesDefault)
+  , _interpose(KeyValues::interposableDefault)
+  , _merge(KeyValues::mergeDefault)
   , _deadStrip(KeyValues::deadStripKindDefault)
-  , _thumb(KeyValues::isThumbDefault)
-  , _alias(KeyValues::isAliasDefault) 
-  , _autoHide(KeyValues::autoHideDefault)
-  , _sectionName(NULL)
-  , _content(NULL) {
+  , _permissions(KeyValues::permissionsDefault)
+  , _internalName(KeyValues::internalNameDefault)
+  , _isThumb(KeyValues::isThumbDefault)
+  , _isAlias(KeyValues::isAliasDefault) 
+  {
   _ref.target       = NULL;
   _ref.addend       = 0;
   _ref.offsetInAtom = 0;
@@ -451,31 +519,36 @@
   _ref.flags        = 0;
 }
 
+
 void YAMLAtomState::makeAtom(YAMLFile& f) {
-  Atom *a = new YAMLAtom(_ordinal, _def, _scope, _type, _sectionChoice,
-                         _internalName, _mergeDuplicates, _autoHide,  
-                         _deadStrip, _thumb, _alias, _align, f, 
-                         _name, _sectionName, _size, _content);
+  if ( _definition == Atom::definitionRegular ) {
+    DefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,
+                          _sectionChoice, _interpose, _merge, _deadStrip,
+                          _permissions,  _internalName, _isThumb, _isAlias, 
+                          _alignment, _name, _sectionName, _size, _content);
 
-  f._atoms.push_back(a);
-  ++_ordinal;
+    f._definedAtoms.push_back(a);
+    ++_ordinal;
+  }
   
   // reset state for next atom
   _name             = NULL;
-  _align.powerOf2   = 0;
-  _align.modulus    = 0;
-  _type             = KeyValues::contentTypeDefault;
+  _sectionName      = NULL;
+  _size             = 0;
+  _ordinal          = 0;
+  _content          = NULL;
+  _alignment.powerOf2= 0;
+  _alignment.modulus = 0;
+  _definition       = KeyValues::definitionDefault;
   _scope            = KeyValues::scopeDefault;
-  _def              = KeyValues::definitionDefault;
+  _type             = KeyValues::contentTypeDefault;
   _sectionChoice    = KeyValues::sectionChoiceDefault;
-  _internalName     = KeyValues::internalNameDefault;
-  _mergeDuplicates  = KeyValues::mergeDuplicatesDefault;
+  _interpose        = KeyValues::interposableDefault;
+  _merge            = KeyValues::mergeDefault;
   _deadStrip        = KeyValues::deadStripKindDefault;
-  _thumb            = KeyValues::isThumbDefault;
-  _alias            = KeyValues::isAliasDefault;
-  _autoHide         = KeyValues::autoHideDefault;
-  _sectionName      = NULL;
-  _content          = NULL;
+  _permissions      = KeyValues::permissionsDefault;
+  _isThumb          = KeyValues::isThumbDefault;
+  _isAlias          = KeyValues::isAliasDefault;
   _ref.target       = NULL;
   _ref.addend       = 0;
   _ref.offsetInAtom = 0;
@@ -492,7 +565,7 @@
   llvm::StringRef str(s);
   uint32_t res;
   str.getAsInteger(10, res);
-  _align.powerOf2 = static_cast<uint16_t>(res);
+  _alignment.powerOf2 = static_cast<uint16_t>(res);
 }
 
 
@@ -590,7 +663,7 @@
           haveAtom = true;
         }
         else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {
-          atomState._def = KeyValues::definition(entry->value);
+          atomState._definition = KeyValues::definition(entry->value);
           haveAtom = true;
         } 
         else if (strcmp(entry->key, KeyValues::scopeKeyword) == 0) {
@@ -609,20 +682,20 @@
           atomState._sectionChoice = KeyValues::sectionChoice(entry->value);
           haveAtom = true;
         }
-        else if (strcmp(entry->key, KeyValues::mergeDuplicatesKeyword) == 0) {
-          atomState._mergeDuplicates = KeyValues::mergeDuplicates(entry->value);
+        else if (strcmp(entry->key, KeyValues::mergeKeyword) == 0) {
+          atomState._merge = KeyValues::merge(entry->value);
           haveAtom = true;
         }
-        else if (strcmp(entry->key, KeyValues::autoHideKeyword) == 0) {
-          atomState._autoHide = KeyValues::autoHide(entry->value);
+        else if (strcmp(entry->key, KeyValues::interposableKeyword) == 0) {
+          atomState._interpose = KeyValues::interposable(entry->value);
           haveAtom = true;
         }
         else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) {
-          atomState._thumb = KeyValues::isThumb(entry->value);
+          atomState._isThumb = KeyValues::isThumb(entry->value);
           haveAtom = true;
         }
         else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) {
-          atomState._alias = KeyValues::isAlias(entry->value);
+          atomState._isAlias = KeyValues::isAlias(entry->value);
           haveAtom = true;
         }
         else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {

Modified: lld/trunk/lib/Core/YamlWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/lib/Core/YamlWriter.cpp (original)
+++ lld/trunk/lib/Core/YamlWriter.cpp Tue Jan 10 19:06:19 2012
@@ -32,7 +32,7 @@
 
   virtual void doFile(const class File &) { _firstAtom = true; }
   
-  virtual void doAtom(const class Atom &atom) {
+  virtual void doDefinedAtom(const class DefinedAtom &atom) {
       // add blank line between atoms for readability
       if ( !_firstAtom )
         _out << "\n";
@@ -72,6 +72,24 @@
             << "\n";
     }
     
+     if ( atom.interposable() != KeyValues::interposableDefault ) {
+      _out  << "      " 
+            << KeyValues::interposableKeyword 
+            << ":"
+            << spacePadding(KeyValues::interposableKeyword)
+            << KeyValues::interposable(atom.interposable()) 
+            << "\n";
+    }
+    
+	if ( atom.merge() != KeyValues::mergeDefault ) {
+      _out  << "      " 
+            << KeyValues::mergeKeyword 
+            << ":"
+            << spacePadding(KeyValues::mergeKeyword)
+            << KeyValues::merge(atom.merge()) 
+            << "\n";
+    }
+    
     if ( atom.contentType() != KeyValues::contentTypeDefault ) {
       _out  << "      " 
             << KeyValues::contentTypeKeyword 
@@ -106,25 +124,7 @@
             << "\n";
     }
 
-    if ( atom.mergeDuplicates() != KeyValues::mergeDuplicatesDefault ) {
-      _out  << "      " 
-            << KeyValues::mergeDuplicatesKeyword 
-            << ":"
-            << spacePadding(KeyValues::mergeDuplicatesKeyword)
-            << KeyValues::mergeDuplicates(atom.mergeDuplicates()) 
-            << "\n";
-    }
-
-    if ( atom.autoHide() != KeyValues::autoHideDefault ) {
-      _out  << "      " 
-            << KeyValues::autoHideKeyword 
-            << ":"
-            << spacePadding(KeyValues::autoHideKeyword)
-            << KeyValues::autoHide(atom.autoHide()) 
-            << "\n";
-    }
-
-    if ( atom.isThumb() != KeyValues::isThumbDefault ) {
+	if ( atom.isThumb() != KeyValues::isThumbDefault ) {
       _out  << "      " 
             << KeyValues::isThumbKeyword 
             << ":"
@@ -142,8 +142,7 @@
             << "\n";
     }
 
-     
-    if ( atom.contentType() != Atom::typeZeroFill ) {
+    if ( atom.contentType() != DefinedAtom::typeZeroFill ) {
       _out  << "      " 
             << KeyValues::contentKeyword 
             << ":"
@@ -172,6 +171,11 @@
 
   }
 
+	virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
+
+	}
+
+
 private:
   // return a string of the correct number of spaces to align value
   const char* spacePadding(const char* key) {

Modified: lld/trunk/test/auto-hide-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/auto-hide-coalesce.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/auto-hide-coalesce.objtxt (original)
+++ lld/trunk/test/auto-hide-coalesce.objtxt Tue Jan 10 19:06:19 2012
@@ -10,67 +10,59 @@
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         true
+      merge:             asWeak
      
     - name:              _inlineFunc2
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         true
+      merge:             asWeak
     
     - name:              _inlineFunc3
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         false
+      merge:             asAddressedWeak
     
     - name:              _inlineFunc4
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         false
+      merge:             asAddressedWeak
 ---
 atoms:
     - name:              _inlineFunc1
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         true
+      merge:             asWeak
     
     - name:              _inlineFunc2
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         false
+      merge:             asAddressedWeak
    
     - name:              _inlineFunc3
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         true
+      merge:             asWeak
   
     - name:              _inlineFunc4
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
-      auto-hide:         false
+      merge:             asAddressedWeak
 ...
 
 
 # CHECK:       name: _inlineFunc1
-# CHECK:       auto-hide: true
+# CHECK:       merge: asWeak
 # CHECK:       name: _inlineFunc3
-# CHECK-NOT:   auto-hide: true
+# CHECK:       merge: asAddressedWeak
 # CHECK:       name: _inlineFunc4
-# CHECK-NOT:   auto-hide: true
+# CHECK:       merge: asAddressedWeak
 # CHECK:       name: _inlineFunc2
-# CHECK-NOT:   auto-hide: true
+# CHECK:       merge: asAddressedWeak
 # CHECK:       ...

Modified: lld/trunk/test/cstring-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/cstring-coalesce.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/cstring-coalesce.objtxt (original)
+++ lld/trunk/test/cstring-coalesce.objtxt Tue Jan 10 19:06:19 2012
@@ -10,14 +10,12 @@
       internal-name:     true
       scope:             hidden
       type:              c-string
-      merge-duplicates:  true
       content:           [ 68, 65, 6c, 6c, 6f, 00 ]
       
     - name:              L1
       internal-name:     true
       scope:             hidden
       type:              c-string
-      merge-duplicates:  true
       content:           [ 74, 68, 65, 72, 65, 00 ]
 ---
 atoms:
@@ -25,7 +23,6 @@
       internal-name:     true
       scope:             hidden
       type:              c-string
-      merge-duplicates:  true
       content:           [ 68, 65, 6c, 6c, 6f, 00 ]
 ---
 atoms:
@@ -33,7 +30,6 @@
       internal-name:     true
       scope:             hidden
       type:              c-string
-      merge-duplicates:  true
       content:           [ 74, 68, 65, 72, 65, 00 ]
 ...
 

Modified: lld/trunk/test/inline-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/inline-coalesce.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/inline-coalesce.objtxt (original)
+++ lld/trunk/test/inline-coalesce.objtxt Tue Jan 10 19:06:19 2012
@@ -10,25 +10,25 @@
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
+      merge:             asWeak
 ---
 atoms:
     - name:              _inlineFunc
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
+      merge:             asWeak
 ---
 atoms:
     - name:              _inlineFunc
       scope:             global
       definition:        regular
       type:              code
-      merge-duplicates:  true
+      merge:             asWeak
 ...
 
 
 # CHECK:       name: _inlineFunc
-# CHECK:       merge-duplicates: true
+# CHECK:       merge: asWeak
 # CHECK-NOT:   name: _inlineFunc
 # CHECK:       ...

Modified: lld/trunk/test/multiple-def-error.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/multiple-def-error.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/multiple-def-error.objtxt (original)
+++ lld/trunk/test/multiple-def-error.objtxt Tue Jan 10 19:06:19 2012
@@ -1,4 +1,4 @@
-# RUN:  lld-core %s  2>&1  |  grep "multiply defined" 
+# RUN:  lld-core %s  2>&1  |  grep "duplicate symbol" 
 
 #
 # Test that multiple definitions cause an error

Modified: lld/trunk/test/tent-merge.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/tent-merge.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/tent-merge.objtxt (original)
+++ lld/trunk/test/tent-merge.objtxt Tue Jan 10 19:06:19 2012
@@ -8,7 +8,8 @@
 ---
 atoms:
     - name:         _foo
-      definition:   tentative
+      definition:   regular
+      merge:        asTentative
       scope:        global
       type:         zero-fill
       size:         4
@@ -23,4 +24,4 @@
 
 
 # CHECK:        name: _foo
-# CHECK-NOT:   definition: tentative
+# CHECK-NOT:   merge: asTentative

Modified: lld/trunk/test/weak-coalesce.objtxt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/weak-coalesce.objtxt?rev=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/test/weak-coalesce.objtxt (original)
+++ lld/trunk/test/weak-coalesce.objtxt Tue Jan 10 19:06:19 2012
@@ -7,7 +7,8 @@
 ---
 atoms:
     - name:         _foo
-      definition:   weak
+      definition:   regular
+      merge:        asWeak
       scope:        global
       type:         data
 ---
@@ -19,13 +20,14 @@
 ---
 atoms:
     - name:         _foo
-      definition:   weak
+      definition:   regular
+      merge:        asWeak
       scope:        global
       type:         data
 ...
 
 
 # CHECK:       name: _foo
-# CHECK-NOT:   definition: weak
+# CHECK-NOT:   merge: asWeak
 # CHECK-NOT:   name: _foo
 # CHECK:       ...

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=147903&r1=147902&r2=147903&view=diff
==============================================================================
--- lld/trunk/tools/lld-core/lld-core.cpp (original)
+++ lld/trunk/tools/lld-core/lld-core.cpp Tue Jan 10 19:06:19 2012
@@ -9,6 +9,8 @@
 
 #include "lld/Core/InputFiles.h"
 #include "lld/Core/Atom.h"
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
 #include "lld/Core/Resolver.h"
 #include "lld/Core/YamlReader.h"
 #include "lld/Core/YamlWriter.h"
@@ -58,17 +60,17 @@
   virtual void atomAdded(const Atom &file) { }
 
   // give platform a chance to change each atom's scope
-  virtual void adjustScope(const Atom &atom) { }
+  virtual void adjustScope(const DefinedAtom &atom) { }
 
   // if specified atom needs alternate names, return AliasAtom(s)
   virtual bool getAliasAtoms(const Atom &atom,
-                             std::vector<const Atom *>&) {
+                             std::vector<const DefinedAtom *>&) {
     return false;
   }
 
   // give platform a chance to resolve platform-specific undefs
   virtual bool getPlatformAtoms(llvm::StringRef undefined,
-                                std::vector<const Atom *>&) {
+                                std::vector<const DefinedAtom *>&) {
     return false;
   }
 
@@ -83,7 +85,7 @@
   }
 
   // if target must have some atoms, denote here
-  virtual bool getImplicitDeadStripRoots(std::vector<const Atom *>&) {
+  virtual bool getImplicitDeadStripRoots(std::vector<const DefinedAtom *>&) {
     return false;
   }
 
@@ -164,7 +166,18 @@
     handler.doFile(*this);
     for (std::vector<const Atom *>::iterator it = _atoms.begin();
          it != _atoms.end(); ++it) {
-      handler.doAtom(**it);
+      const Atom* atom = *it;
+      switch ( atom->definition() ) {
+        case Atom::definitionRegular:
+          handler.doDefinedAtom(*(DefinedAtom*)atom);
+          break;
+        case Atom::definitionUndefined:
+          handler.doUndefinedAtom(*(UndefinedAtom*)atom);
+          break;
+        default:
+          // TO DO
+          break;
+      }
     }
     return true;
   }





More information about the llvm-commits mailing list