summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/Core/Atom.h352
-rw-r--r--lld/include/lld/Core/DefinedAtom.h287
-rw-r--r--lld/include/lld/Core/File.h6
-rw-r--r--lld/include/lld/Core/Resolver.h10
-rw-r--r--lld/include/lld/Core/SymbolTable.h20
-rw-r--r--lld/include/lld/Core/UndefinedAtom.h31
-rw-r--r--lld/include/lld/Platform/Platform.h9
-rw-r--r--lld/lib/Core/Atom.cpp44
-rw-r--r--lld/lib/Core/CMakeLists.txt1
-rw-r--r--lld/lib/Core/Resolver.cpp115
-rw-r--r--lld/lib/Core/SymbolTable.cpp128
-rw-r--r--lld/lib/Core/YamlKeyValues.cpp304
-rw-r--r--lld/lib/Core/YamlKeyValues.h111
-rw-r--r--lld/lib/Core/YamlReader.cpp307
-rw-r--r--lld/lib/Core/YamlWriter.cpp48
-rw-r--r--lld/test/auto-hide-coalesce.objtxt32
-rw-r--r--lld/test/cstring-coalesce.objtxt4
-rw-r--r--lld/test/inline-coalesce.objtxt8
-rw-r--r--lld/test/multiple-def-error.objtxt2
-rw-r--r--lld/test/tent-merge.objtxt5
-rw-r--r--lld/test/weak-coalesce.objtxt8
-rw-r--r--lld/tools/lld-core/lld-core.cpp23
22 files changed, 1001 insertions, 854 deletions
diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h
index b413cdd2714..df5efeedbd8 100644
--- a/lld/include/lld/Core/Atom.h
+++ b/lld/include/lld/Core/Atom.h
@@ -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 @@ public:
/// 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
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h
new file mode 100644
index 00000000000..c151325cdcf
--- /dev/null
+++ b/lld/include/lld/Core/DefinedAtom.h
@@ -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_
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h
index 0eaa34cc7f1..b2f360149b4 100644
--- a/lld/include/lld/Core/File.h
+++ b/lld/include/lld/Core/File.h
@@ -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 @@ public:
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;
};
diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h
index 33a54799601..1bb2abea522 100644
--- a/lld/include/lld/Core/Resolver.h
+++ b/lld/include/lld/Core/Resolver.h
@@ -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 @@ public:
, _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 @@ private:
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 @@ private:
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;
diff --git a/lld/include/lld/Core/SymbolTable.h b/lld/include/lld/Core/SymbolTable.h
index 9888fa4414c..54202b7c87d 100644
--- a/lld/include/lld/Core/SymbolTable.h
+++ b/lld/include/lld/Core/SymbolTable.h
@@ -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 @@ public:
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 @@ private:
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;
diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h
index 8924d768d5a..11817b380db 100644
--- a/lld/include/lld/Core/UndefinedAtom.h
+++ b/lld/include/lld/Core/UndefinedAtom.h
@@ -20,22 +20,9 @@ namespace lld {
/// 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 @@ public:
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
diff --git a/lld/include/lld/Platform/Platform.h b/lld/include/lld/Platform/Platform.h
index c95c936ad52..2f3634b4b69 100644
--- a/lld/include/lld/Platform/Platform.h
+++ b/lld/include/lld/Platform/Platform.h
@@ -14,6 +14,7 @@
namespace lld {
class Atom;
+class DefinedAtom;
/// The Platform class encapsulated plaform specific linking knowledge.
///
@@ -29,15 +30,15 @@ public:
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 @@ public:
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;
diff --git a/lld/lib/Core/Atom.cpp b/lld/lib/Core/Atom.cpp
deleted file mode 100644
index 29aa1c805fa..00000000000
--- a/lld/lib/Core/Atom.cpp
+++ /dev/null
@@ -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
diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt
index aa08637db0f..eca024cf231 100644
--- a/lld/lib/Core/CMakeLists.txt
+++ b/lld/lib/Core/CMakeLists.txt
@@ -1,5 +1,4 @@
add_lld_library(lldCore
- Atom.cpp
File.cpp
Resolver.cpp
SymbolTable.cpp
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index c3b83756e1b..51f6a481a65 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -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 @@ private:
SymbolTable &_symbolTable;
};
+
+
+
void Resolver::initializeState() {
_platform.initialize();
}
@@ -68,24 +89,34 @@ void Resolver::doFile(const File &file) {
_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 @@ void Resolver::doAtom(const Atom &atom) {
}
// 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 @@ void Resolver::resolveUndefines() {
// 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 @@ void Resolver::resolveUndefines() {
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 @@ void Resolver::resolveUndefines() {
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::resolveUndefines() {
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 @@ void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {
}
// 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 @@ void Resolver::deadStripOptimize() {
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 @@ void Resolver::deadStripOptimize() {
}
// 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 @@ void Resolver::deadStripOptimize() {
// 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 @@ void Resolver::checkUndefines(bool final) {
// 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::removeCoalescedAwayAtoms() {
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);
}
}
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 740773843cd..f964fd8acf9 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -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 @@ SymbolTable::SymbolTable(Platform& plat)
: _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 @@ void SymbolTable::add(const Atom &atom) {
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 @@ static NameCollisionResolution collide(Atom::Definition first,
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 @@ void SymbolTable::addByName(const Atom & newAtom) {
// 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 @@ void SymbolTable::addByName(const Atom & newAtom) {
}
-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 @@ unsigned SymbolTable::MyMappingInfo::getHashValue(const Atom * const atom) {
}
-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 @@ bool SymbolTable::MyMappingInfo::isEqual(const Atom * const l,
}
-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);
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp
index 47729d684d8..4158e6d4e51 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/Core/YamlKeyValues.cpp
@@ -18,61 +18,33 @@ namespace yaml {
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 @@ struct DefinitionMapping {
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 @@ const char* KeyValues::definition(Atom::Definition s) {
+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 @@ Atom::ContentType KeyValues::contentType(const char* s)
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 @@ const char* KeyValues::contentType(Atom::ContentType s) {
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 @@ Atom::DeadStripKind KeyValues::deadStripKind(const char* s)
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 @@ const char* KeyValues::deadStripKind(Atom::DeadStripKind dsk) {
-
-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 @@ const char* KeyValues::sectionChoice(Atom::SectionChoice s) {
+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 @@ const char* KeyValues::internalName(bool b) {
-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 @@ const char* KeyValues::mergeDuplicates(bool b) {
-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 )
diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h
index c8890bd8f1e..b38a26cfaf3 100644
--- a/lld/lib/Core/YamlKeyValues.h
+++ b/lld/lib/Core/YamlKeyValues.h
@@ -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 @@ namespace yaml {
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);
};
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index 8fe7d507c6b..5ca8fbc8103 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -289,16 +289,17 @@ public:
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 @@ bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,
}
-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 @@ public:
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 @@ YAMLAtomState::YAMLAtomState()
_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);
- f._atoms.push_back(a);
- ++_ordinal;
+void YAMLAtomState::makeAtom(YAMLFile& f) {
+ 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._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 @@ void YAMLAtomState::setAlign2(const char *s) {
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 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
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 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
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) {
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp
index 5b015825d11..3e30c0a4260 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/Core/YamlWriter.cpp
@@ -32,7 +32,7 @@ public:
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 @@ public:
<< "\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 @@ public:
<< "\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 @@ public:
<< "\n";
}
-
- if ( atom.contentType() != Atom::typeZeroFill ) {
+ if ( atom.contentType() != DefinedAtom::typeZeroFill ) {
_out << " "
<< KeyValues::contentKeyword
<< ":"
@@ -172,6 +171,11 @@ public:
}
+ 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) {
diff --git a/lld/test/auto-hide-coalesce.objtxt b/lld/test/auto-hide-coalesce.objtxt
index 7ee563867cc..5471809491b 100644
--- a/lld/test/auto-hide-coalesce.objtxt
+++ b/lld/test/auto-hide-coalesce.objtxt
@@ -10,67 +10,59 @@ atoms:
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: ...
diff --git a/lld/test/cstring-coalesce.objtxt b/lld/test/cstring-coalesce.objtxt
index 70ee8830868..205af3721e9 100644
--- a/lld/test/cstring-coalesce.objtxt
+++ b/lld/test/cstring-coalesce.objtxt
@@ -10,14 +10,12 @@ atoms:
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 @@ atoms:
internal-name: true
scope: hidden
type: c-string
- merge-duplicates: true
content: [ 68, 65, 6c, 6c, 6f, 00 ]
---
atoms:
@@ -33,7 +30,6 @@ atoms:
internal-name: true
scope: hidden
type: c-string
- merge-duplicates: true
content: [ 74, 68, 65, 72, 65, 00 ]
...
diff --git a/lld/test/inline-coalesce.objtxt b/lld/test/inline-coalesce.objtxt
index 3974198077c..edd7f471f42 100644
--- a/lld/test/inline-coalesce.objtxt
+++ b/lld/test/inline-coalesce.objtxt
@@ -10,25 +10,25 @@ atoms:
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: ...
diff --git a/lld/test/multiple-def-error.objtxt b/lld/test/multiple-def-error.objtxt
index e57a017f163..068e257cdd2 100644
--- a/lld/test/multiple-def-error.objtxt
+++ b/lld/test/multiple-def-error.objtxt
@@ -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
diff --git a/lld/test/tent-merge.objtxt b/lld/test/tent-merge.objtxt
index bb8573e6b6d..4872b163ee6 100644
--- a/lld/test/tent-merge.objtxt
+++ b/lld/test/tent-merge.objtxt
@@ -8,7 +8,8 @@
---
atoms:
- name: _foo
- definition: tentative
+ definition: regular
+ merge: asTentative
scope: global
type: zero-fill
size: 4
@@ -23,4 +24,4 @@ atoms:
# CHECK: name: _foo
-# CHECK-NOT: definition: tentative
+# CHECK-NOT: merge: asTentative
diff --git a/lld/test/weak-coalesce.objtxt b/lld/test/weak-coalesce.objtxt
index f3640cee90c..48f088c2670 100644
--- a/lld/test/weak-coalesce.objtxt
+++ b/lld/test/weak-coalesce.objtxt
@@ -7,7 +7,8 @@
---
atoms:
- name: _foo
- definition: weak
+ definition: regular
+ merge: asWeak
scope: global
type: data
---
@@ -19,13 +20,14 @@ atoms:
---
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: ...
diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp
index 921bab913e4..3bd35c2538f 100644
--- a/lld/tools/lld-core/lld-core.cpp
+++ b/lld/tools/lld-core/lld-core.cpp
@@ -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 @@ public:
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 @@ public:
}
// 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 @@ public:
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;
}
OpenPOWER on IntegriCloud