<p>I know this is early stage stuff, but others are interested, so commit log messages would be good. ;)</p>
<div class="gmail_quote">On Feb 14, 2012 2:45 PM, "Nick Kledzik" <<a href="mailto:kledzik@apple.com">kledzik@apple.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Author: kledzik<br>
Date: Tue Feb 14 18:38:09 2012<br>
New Revision: 150539<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=150539&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=150539&view=rev</a><br>
Log:<br>
<br>
<br>
Added:<br>
lld/trunk/test/fixups-addend.objtxt<br>
lld/trunk/test/fixups-dup-named.objtxt<br>
lld/trunk/test/fixups-named.objtxt<br>
lld/trunk/test/fixups-unnamed.objtxt<br>
Removed:<br>
lld/trunk/test/internal-name-attributes.objtxt<br>
Modified:<br>
lld/trunk/include/lld/Core/DefinedAtom.h<br>
lld/trunk/include/lld/Core/Reference.h<br>
lld/trunk/include/lld/Core/Resolver.h<br>
lld/trunk/lib/Core/NativeFileFormat.h<br>
lld/trunk/lib/Core/NativeReader.cpp<br>
lld/trunk/lib/Core/NativeWriter.cpp<br>
lld/trunk/lib/Core/Resolver.cpp<br>
lld/trunk/lib/Core/SymbolTable.cpp<br>
lld/trunk/lib/Core/YamlKeyValues.cpp<br>
lld/trunk/lib/Core/YamlKeyValues.h<br>
lld/trunk/lib/Core/YamlReader.cpp<br>
lld/trunk/lib/Core/YamlWriter.cpp<br>
lld/trunk/test/cstring-coalesce.objtxt<br>
lld/trunk/tools/lld-core/lld-core.cpp<br>
<br>
Modified: lld/trunk/include/lld/Core/DefinedAtom.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)<br>
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Feb 14 18:38:09 2012<br>
@@ -34,7 +34,7 @@<br>
/// Here are some example attribute sets for common atoms. If a particular<br>
/// attribute is not listed, the default values are: definition=regular,<br>
/// sectionChoice=basedOnContent, scope=translationUnit, merge=no,<br>
-/// internalName=false, deadStrip=normal, interposable=no<br>
+/// deadStrip=normal, interposable=no<br>
///<br>
/// C function: void foo() {} <br><br>
/// name=foo, type=code, perm=r_x, scope=global<br>
@@ -71,16 +71,16 @@<br>
/// mergeDupes=asAddressedWeak<br>
///<br>
/// literal c-string: "hello" <br><br>
-/// name=L0, internalName=true, type=cstring, perm=r__, scope=linkageUnit<br>
+/// name="" type=cstring, perm=r__, scope=linkageUnit<br>
///<br>
/// literal double: 1.234 <br><br>
-/// name=L0, internalName=true, type=literal8, perm=r__, scope=linkageUnit<br>
+/// name="" type=literal8, perm=r__, scope=linkageUnit<br>
///<br>
/// constant: { 1,2,3 } <br><br>
-/// name=L0, internalName=true, type=constant, perm=r__, scope=linkageUnit<br>
+/// name="" type=constant, perm=r__, scope=linkageUnit<br>
///<br>
/// Pointer to initializer function: <br><br>
-/// name=_init, internalName=true, type=initializer, perm=rw_l,<br>
+/// name="" type=initializer, perm=rw_l,<br>
/// sectionChoice=customRequired<br>
///<br>
/// C function place in custom section: __attribute__((section("__foo")))<br>
@@ -195,15 +195,18 @@<br>
uint16_t modulus;<br>
};<br>
<br>
+ /// for use iterating over this Atom's References<br>
+ class ReferenceHandler {<br>
+ public:<br>
+ virtual ~ReferenceHandler() {}<br>
+ virtual void doReference(const Reference &) = 0;<br>
+ };<br>
+<br>
/// ordinal - returns a value for the order of this Atom within its file.<br>
/// This is used by the linker to order the layout of Atoms so that<br>
/// the resulting image is stable and reproducible.<br>
virtual uint64_t ordinal() const = 0;<br>
-<br>
- /// internalName - If the name is just a temporary label that should<br>
- /// not show up in the final linked image.<br>
- virtual bool internalName() const = 0;<br>
-<br>
+<br>
/// size - the number of bytes of space this atom's content will occupy<br>
/// in the final linked image. For a function atom, it is the number<br>
/// of bytes of code in the function.<br>
@@ -264,12 +267,9 @@<br>
/// this Atom's content.<br>
virtual llvm::ArrayRef<uint8_t> rawContent() const = 0;<br>
<br>
- /// referencesBegin - used to start iterating this Atom's References<br>
- virtual Reference::iterator referencesBegin() const = 0;<br>
-<br>
- /// referencesEnd - used to end iterating this Atom's References<br>
- virtual Reference::iterator referencesEnd() const = 0;<br>
-<br>
+ /// iterator over this Atom's References<br>
+ virtual void forEachReference(ReferenceHandler&) const = 0;<br>
+<br>
protected:<br>
/// DefinedAtom is an abstract base class.<br>
/// Only subclasses can access constructor.<br>
<br>
Modified: lld/trunk/include/lld/Core/Reference.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Reference.h?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/Core/Reference.h (original)<br>
+++ lld/trunk/include/lld/Core/Reference.h Tue Feb 14 18:38:09 2012<br>
@@ -12,22 +12,60 @@<br>
<br>
#include <stdint.h><br>
<br>
-<br>
namespace lld {<br>
<br>
-class Atom;<br>
-<br>
+///<br>
+/// The linker has a Graph Theory model of linking. An object file is seen<br>
+/// as a set of Atoms with References to other Atoms. Each Atom is a node<br>
+/// and each Reference is an edge.<br>
+///<br>
+/// For example if a function contains a call site to "malloc" 40 bytes into<br>
+/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40,<br>
+/// kind=callsite, target=malloc, addend=0.<br>
+///<br>
+/// Besides supporting traditional "relocations", References are also used<br>
+/// grouping atoms (group comdat), forcing layout (one atom must follow<br>
+/// another), marking data-in-code (jump tables or ARM constants), etc.<br>
+///<br>
class Reference {<br>
public:<br>
- typedef Reference *iterator;<br>
-<br>
- const Atom *target;<br>
- uint64_t addend;<br>
- uint32_t offsetInAtom;<br>
- uint16_t kind;<br>
- uint16_t flags;<br>
+ /// The meaning of positive kind values is architecture specific.<br>
+ /// Negative kind values are architecture independent.<br>
+ typedef int32_t Kind;<br>
+<br>
+ // A value to be added to the value of a target<br>
+ typedef int64_t Addend;<br>
+<br>
+ /// What sort of reference this is.<br>
+ virtual Kind kind() const = 0;<br>
+<br>
+ /// If the reference is a fixup in the Atom, then this returns the<br>
+ /// byte offset into the Atom's content to do the fix up.<br>
+ virtual uint64_t offsetInAtom() const = 0;<br>
+<br>
+ /// If the reference is an edge to another Atom, then this returns the<br>
+ /// other Atom. Otherwise, it returns NULL.<br>
+ virtual const class Atom * target() const = 0;<br>
+<br>
+ /// During linking, the linker may merge graphs which coalesces some nodes<br>
+ /// (i.e. Atoms). To switch the target of a reference, this method is called.<br>
+ virtual void setTarget(const class Atom *) = 0;<br>
+<br>
+ /// Some relocations require a symbol and a value (e.g. foo + 4).<br>
+ virtual Addend addend() const = 0;<br>
+<br>
+protected:<br>
+ /// Atom is an abstract base class. Only subclasses can access constructor.<br>
+ Reference() {}<br>
+<br>
+ /// The memory for Reference objects is always managed by the owning File<br>
+ /// object. Therefore, no one but the owning File object should call<br>
+ /// delete on an Reference. In fact, some File objects may bulk allocate<br>
+ /// an array of References, so they cannot be individually deleted by anyone.<br>
+ virtual ~Reference() {}<br>
};<br>
<br>
+<br>
} // namespace lld<br>
<br>
#endif // LLD_CORE_REFERENCES_H_<br>
<br>
Modified: lld/trunk/include/lld/Core/Resolver.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/include/lld/Core/Resolver.h (original)<br>
+++ lld/trunk/include/lld/Core/Resolver.h Tue Feb 14 18:38:09 2012<br>
@@ -70,6 +70,22 @@<br>
void markLive(const Atom &atom, WhyLiveBackChain *previous);<br>
void addAtoms(const std::vector<const DefinedAtom *>&);<br>
<br>
+<br>
+ // helper to update targets for use with forEachReference()<br>
+ class MarkLiveReferences : public DefinedAtom::ReferenceHandler {<br>
+ public:<br>
+ MarkLiveReferences(Resolver& resolver, WhyLiveBackChain* chain)<br>
+ : _resolver(resolver), _chain(chain) { }<br>
+<br>
+ virtual void doReference(const Reference& ref) {<br>
+ _resolver.markLive(*ref.target(), _chain);<br>
+ }<br>
+<br>
+ private:<br>
+ Resolver& _resolver;<br>
+ WhyLiveBackChain* _chain;<br>
+ };<br>
+<br>
Platform &_platform;<br>
const InputFiles &_inputFiles;<br>
SymbolTable _symbolTable;<br>
<br>
Modified: lld/trunk/lib/Core/NativeFileFormat.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeFileFormat.h?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/NativeFileFormat.h (original)<br>
+++ lld/trunk/lib/Core/NativeFileFormat.h Tue Feb 14 18:38:09 2012<br>
@@ -80,6 +80,7 @@<br>
uint32_t architecture;<br>
uint32_t fileSize;<br>
uint32_t chunkCount;<br>
+ // NativeChunk chunks[]<br>
};<br>
<br>
//<br>
@@ -90,8 +91,11 @@<br>
NCS_AttributesArrayV1 = 2,<br>
NCS_UndefinedAtomsV1 = 3,<br>
NCS_Strings = 4,<br>
- NCS_Content = 5,<br>
- NCS_ReferencesArray = 6,<br>
+ NCS_ReferencesArrayV1 = 5,<br>
+ NCS_ReferencesArrayV2 = 6,<br>
+ NCS_TargetsTable = 7,<br>
+ NCS_AddendsTable = 8,<br>
+ NCS_Content = 9,<br>
};<br>
<br>
//<br>
@@ -125,6 +129,8 @@<br>
struct NativeDefinedAtomIvarsV1 {<br>
uint32_t nameOffset;<br>
uint32_t attributesOffset;<br>
+ uint32_t referencesStartIndex;<br>
+ uint32_t referencesCount;<br>
uint32_t contentOffset;<br>
uint32_t contentSize;<br>
};<br>
@@ -137,7 +143,6 @@<br>
uint32_t sectionNameOffset;<br>
uint16_t align2;<br>
uint16_t alignModulus;<br>
- uint8_t internalName;<br>
uint8_t scope;<br>
uint8_t interposable;<br>
uint8_t merge;<br>
@@ -145,10 +150,7 @@<br>
uint8_t sectionChoice;<br>
uint8_t deadStrip;<br>
uint8_t permissions;<br>
- uint8_t thumb;<br>
uint8_t alias;<br>
- uint8_t pad1;<br>
- uint8_t pad2;<br>
};<br>
<br>
<br>
@@ -164,6 +166,51 @@<br>
<br>
<br>
<br>
+//<br>
+// The NCS_ReferencesArrayV1 chunk contains an array of these structs<br>
+//<br>
+struct NativeReferenceIvarsV1 {<br>
+ uint16_t offsetInAtom;<br>
+ int16_t kind;<br>
+ uint16_t targetIndex;<br>
+ uint16_t addendIndex;<br>
+};<br>
+<br>
+<br>
+<br>
+//<br>
+// The NCS_ReferencesArrayV2 chunk contains an array of these structs<br>
+//<br>
+struct NativeReferenceIvarsV2 {<br>
+ uint64_t offsetInAtom;<br>
+ int64_t addend;<br>
+ int32_t kind;<br>
+ uint32_t targetIndex;<br>
+};<br>
+<br>
+<br>
+//<br>
+// The NCS_TargetsTable chunk contains an array of uint32_t entries.<br>
+// The C++ class Reference has a target() method that returns a<br>
+// pointer to another Atom. We can't have pointers in object files,<br>
+// so instead NativeReferenceIvarsV1 contains an index to the target.<br>
+// The index is into this NCS_TargetsTable of uint32_t entries.<br>
+// The values in this table are the index of the (target) atom in this file.<br>
+// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.<br>
+// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to<br>
+// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.<br>
+//<br>
+<br>
+<br>
+//<br>
+// The NCS_AddendsTable chunk contains an array of int64_t entries.<br>
+// If we allocated space for addends directly in NativeReferenceIvarsV1<br>
+// it would double the size of that struct. But since addends are rare,<br>
+// we instead just keep a pool of addends and have NativeReferenceIvarsV1<br>
+// (if it needs an addend) just store the index (into the pool) of the<br>
+// addend it needs.<br>
+//<br>
+<br>
<br>
<br>
} // namespace lld<br>
<br>
Modified: lld/trunk/lib/Core/NativeReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeReader.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/NativeReader.cpp (original)<br>
+++ lld/trunk/lib/Core/NativeReader.cpp Tue Feb 14 18:38:09 2012<br>
@@ -44,10 +44,6 @@<br>
<br>
virtual llvm::StringRef name() const;<br>
<br>
- virtual bool internalName() const {<br>
- return attributes().internalName;<br>
- }<br>
-<br>
virtual uint64_t size() const {<br>
return _ivarData->contentSize;<br>
}<br>
@@ -88,23 +84,17 @@<br>
}<br>
<br>
virtual bool isThumb() const {<br>
- return (attributes().thumb != 0);<br>
+ return false; //(attributes().thumb != 0);<br>
}<br>
<br>
virtual bool isAlias() const {<br>
return (attributes().alias != 0);<br>
}<br>
<br>
- llvm::ArrayRef<uint8_t> rawContent() const;<br>
+ virtual llvm::ArrayRef<uint8_t> rawContent() const;<br>
<br>
- virtual Reference::iterator referencesBegin() const {<br>
- return 0;<br>
- }<br>
-<br>
- virtual Reference::iterator referencesEnd() const {<br>
- return 0;<br>
- }<br>
-<br>
+ virtual void forEachReference(ReferenceHandler&) const;<br>
+<br>
private:<br>
const NativeAtomAttributesV1& attributes() const;<br>
<br>
@@ -139,6 +129,35 @@<br>
<br>
<br>
//<br>
+// An object of this class is instantied for each NativeReferenceIvarsV1<br>
+// struct in the NCS_ReferencesArrayV1 chunk.<br>
+//<br>
+class NativeReferenceV1 : public Reference {<br>
+public:<br>
+ NativeReferenceV1(const NativeFile& f,<br>
+ const NativeReferenceIvarsV1* ivarData)<br>
+ : _file(&f), _ivarData(ivarData) { }<br>
+<br>
+ virtual uint64_t offsetInAtom() const {<br>
+ return _ivarData->offsetInAtom;<br>
+ }<br>
+<br>
+ virtual Kind kind() const {<br>
+ return _ivarData->kind;<br>
+ }<br>
+<br>
+ virtual const Atom* target() const;<br>
+ virtual Addend addend() const;<br>
+ virtual void setTarget(const Atom* newAtom);<br>
+<br>
+private:<br>
+ const NativeFile* _file;<br>
+ const NativeReferenceIvarsV1* _ivarData;<br>
+};<br>
+<br>
+<br>
+<br>
+//<br>
// lld::File object for native llvm object file<br>
//<br>
class NativeFile : public File {<br>
@@ -187,6 +206,15 @@<br>
case NCS_UndefinedAtomsV1:<br>
ec = file->processUndefinedAtomsV1(base, chunk);<br>
break;<br>
+ case NCS_ReferencesArrayV1:<br>
+ ec = file->processReferencesV1(base, chunk);<br>
+ break;<br>
+ case NCS_TargetsTable:<br>
+ ec = file->processTargetsTable(base, chunk);<br>
+ break;<br>
+ case NCS_AddendsTable:<br>
+ ec = file->processAddendsTable(base, chunk);<br>
+ break;<br>
case NCS_Content:<br>
ec = file->processContent(base, chunk);<br>
break;<br>
@@ -219,6 +247,8 @@<br>
// to just delete the memory.<br>
delete _definedAtoms.arrayStart;<br>
delete _undefinedAtoms.arrayStart;<br>
+ delete _references.arrayStart;<br>
+ delete _targetsTable;<br>
}<br>
<br>
// visits each atom in the file<br>
@@ -245,6 +275,7 @@<br>
private:<br>
friend class NativeDefinedAtomV1;<br>
friend class NativeUndefinedAtomV1;<br>
+ friend class NativeReferenceV1;<br>
<br>
// instantiate array of DefinedAtoms from v1 ivar data in file<br>
llvm::error_code processDefinedAtomsV1(const uint8_t* base,<br>
@@ -272,6 +303,7 @@<br>
this->_definedAtoms.arrayStart = atomsStart;<br>
this->_definedAtoms.arrayEnd = atomsEnd;<br>
this->_definedAtoms.elementSize = atomSize;<br>
+ this->_definedAtoms.elementCount = chunk->elementCount;<br>
return make_error_code(native_reader_error::success);<br>
}<br>
<br>
@@ -307,6 +339,77 @@<br>
this->_undefinedAtoms.arrayStart = atomsStart;<br>
this->_undefinedAtoms.arrayEnd = atomsEnd;<br>
this->_undefinedAtoms.elementSize = atomSize;<br>
+ this->_undefinedAtoms.elementCount = chunk->elementCount;<br>
+ return make_error_code(native_reader_error::success);<br>
+ }<br>
+<br>
+<br>
+ // instantiate array of Referemces from v1 ivar data in file<br>
+ llvm::error_code processReferencesV1(const uint8_t* base,<br>
+ const NativeChunk* chunk) {<br>
+ if ( chunk->elementCount == 0 )<br>
+ return make_error_code(native_reader_error::success);<br>
+ const size_t refSize = sizeof(NativeReferenceV1);<br>
+ size_t refsArraySize = chunk->elementCount * refSize;<br>
+ uint8_t* refsStart = reinterpret_cast<uint8_t*><br>
+ (operator new(refsArraySize, std::nothrow));<br>
+ if (refsStart == NULL )<br>
+ return make_error_code(native_reader_error::memory_error);<br>
+ const size_t ivarElementSize = chunk->fileSize<br>
+ / chunk->elementCount;<br>
+ if ( ivarElementSize != sizeof(NativeReferenceIvarsV1) )<br>
+ return make_error_code(native_reader_error::file_malformed);<br>
+ uint8_t* refsEnd = refsStart + refsArraySize;<br>
+ const NativeReferenceIvarsV1* ivarData =<br>
+ reinterpret_cast<const NativeReferenceIvarsV1*><br>
+ (base + chunk->fileOffset);<br>
+ for(uint8_t* s = refsStart; s != refsEnd; s += refSize) {<br>
+ NativeReferenceV1* atomAllocSpace =<br>
+ reinterpret_cast<NativeReferenceV1*>(s);<br>
+ new (atomAllocSpace) NativeReferenceV1(*this, ivarData);<br>
+ ++ivarData;<br>
+ }<br>
+ this->_references.arrayStart = refsStart;<br>
+ this->_references.arrayEnd = refsEnd;<br>
+ this->_references.elementSize = refSize;<br>
+ this->_references.elementCount = chunk->elementCount;<br>
+ return make_error_code(native_reader_error::success);<br>
+ }<br>
+<br>
+ // set up pointers to target table<br>
+ llvm::error_code processTargetsTable(const uint8_t* base,<br>
+ const NativeChunk* chunk) {<br>
+ const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*><br>
+ (base + chunk->fileOffset);<br>
+ this->_targetsTableCount = chunk->elementCount;<br>
+ this->_targetsTable = new const Atom*[chunk->elementCount];<br>
+ for (uint32_t i=0; i < chunk->elementCount; ++i) {<br>
+ const uint32_t index = targetIndexes[i];<br>
+ if ( index < _definedAtoms.elementCount ) {<br>
+ const uint8_t* p = _definedAtoms.arrayStart<br>
+ + index * _definedAtoms.elementSize;<br>
+ this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);<br>
+ continue;<br>
+ }<br>
+ const uint32_t undefIndex = index - _definedAtoms.elementCount;<br>
+ if ( undefIndex < _undefinedAtoms.elementCount ) {<br>
+ const uint8_t* p = _undefinedAtoms.arrayStart<br>
+ + undefIndex * _undefinedAtoms.elementSize;<br>
+ this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);<br>
+ continue;<br>
+ }<br>
+ return make_error_code(native_reader_error::file_malformed);<br>
+ }<br>
+ return make_error_code(native_reader_error::success);<br>
+ }<br>
+<br>
+<br>
+ // set up pointers to addend pool in file<br>
+ llvm::error_code processAddendsTable(const uint8_t* base,<br>
+ const NativeChunk* chunk) {<br>
+ this->_addends = reinterpret_cast<const Reference::Addend*><br>
+ (base + chunk->fileOffset);<br>
+ this->_addendsMaxIndex = chunk->elementCount;<br>
return make_error_code(native_reader_error::success);<br>
}<br>
<br>
@@ -331,9 +434,16 @@<br>
return llvm::StringRef(&_strings[offset]);<br>
}<br>
<br>
- const NativeAtomAttributesV1& attribute(uint32_t offset) const {<br>
- assert(offset < _attributesMaxOffset);<br>
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + offset);<br>
+ Reference::Addend addend(uint32_t index) const {<br>
+ if ( index == 0 )<br>
+ return 0; // addend index zero is used to mean "no addend"<br>
+ assert(index <= _addendsMaxIndex);<br>
+ return _addends[index-1]; // one-based indexing<br>
+ }<br>
+<br>
+ const NativeAtomAttributesV1& attribute(uint32_t off) const {<br>
+ assert(off < _attributesMaxOffset);<br>
+ return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);<br>
}<br>
<br>
const uint8_t* content(uint32_t offset, uint32_t size) const {<br>
@@ -342,44 +452,75 @@<br>
return result;<br>
}<br>
<br>
-<br>
+ void forEachReference(DefinedAtom::ReferenceHandler& handler,<br>
+ uint32_t start, uint32_t count) const {<br>
+ assert(start < _references.elementCount);<br>
+ assert(start+count <= _references.elementCount);<br>
+ const uint8_t* arrStart = _references.arrayStart<br>
+ + start * _references.elementSize;<br>
+ const uint8_t* arrEnd = arrStart + count * _references.elementSize;<br>
+ for(const uint8_t* p=arrStart; p != arrEnd; p += _references.elementSize) {<br>
+ const NativeReferenceV1* ref<br>
+ = reinterpret_cast<const NativeReferenceV1*>(p);<br>
+ handler.doReference(*ref);<br>
+ }<br>
+ }<br>
+<br>
+ const Atom* target(uint32_t index) const {<br>
+ assert(index < _targetsTableCount);<br>
+ return _targetsTable[index];<br>
+ }<br>
+<br>
+ void setTarget(uint32_t index, const Atom* newAtom) const {<br>
+ assert(index > _targetsTableCount);<br>
+ _targetsTable[index] = newAtom;<br>
+ }<br>
+<br>
+<br>
// private constructor, only called by make()<br>
NativeFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, llvm::StringRef path) :<br>
lld::File(path),<br>
_buffer(mb.take()), // NativeFile now takes ownership of buffer<br>
_header(NULL),<br>
+ _targetsTable(NULL),<br>
+ _targetsTableCount(0),<br>
_strings(NULL),<br>
_stringsMaxOffset(0),<br>
+ _addends(NULL),<br>
+ _addendsMaxIndex(0),<br>
_contentStart(NULL),<br>
_contentEnd(NULL)<br>
{<br>
_header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());<br>
- _definedAtoms.arrayStart = NULL;<br>
- _undefinedAtoms.arrayStart = NULL;<br>
}<br>
<br>
- struct AtomArray {<br>
- AtomArray() : arrayStart(NULL), arrayEnd(NULL),<br>
- elementSize(0) { }<br>
+ struct IvarArray {<br>
+ IvarArray() : arrayStart(NULL), arrayEnd(NULL),<br>
+ elementSize(0), elementCount(0) { }<br>
const uint8_t* arrayStart;<br>
const uint8_t* arrayEnd;<br>
uint32_t elementSize;<br>
- };<br>
+ uint32_t elementCount;<br>
+ };<br>
<br>
llvm::OwningPtr<llvm::MemoryBuffer> _buffer;<br>
const NativeFileHeader* _header;<br>
- AtomArray _definedAtoms;<br>
- AtomArray _undefinedAtoms;<br>
+ IvarArray _definedAtoms;<br>
+ IvarArray _undefinedAtoms;<br>
const uint8_t* _attributes;<br>
uint32_t _attributesMaxOffset;<br>
+ IvarArray _references;<br>
+ const Atom** _targetsTable;<br>
+ uint32_t _targetsTableCount;<br>
const char* _strings;<br>
uint32_t _stringsMaxOffset;<br>
+ const Reference::Addend* _addends;<br>
+ uint32_t _addendsMaxIndex;<br>
const uint8_t* _contentStart;<br>
const uint8_t* _contentEnd;<br>
};<br>
<br>
-<br>
-<br>
+<br>
inline const class File& NativeDefinedAtomV1::file() const {<br>
return *_file;<br>
}<br>
@@ -410,8 +551,12 @@<br>
return _file->string(offset);<br>
}<br>
<br>
-<br>
-<br>
+inline void NativeDefinedAtomV1::forEachReference(ReferenceHandler& hnd) const {<br>
+ if ( _ivarData->referencesCount == 0 )<br>
+ return;<br>
+ _file->forEachReference(hnd, _ivarData->referencesStartIndex,<br>
+ _ivarData->referencesCount);<br>
+}<br>
<br>
inline const class File& NativeUndefinedAtomV1::file() const {<br>
return *_file;<br>
@@ -422,6 +567,17 @@<br>
}<br>
<br>
<br>
+inline const Atom* NativeReferenceV1::target() const {<br>
+ return _file->target(_ivarData->targetIndex);<br>
+}<br>
+<br>
+inline Reference::Addend NativeReferenceV1::addend() const {<br>
+ return _file->addend(_ivarData->addendIndex);<br>
+}<br>
+<br>
+inline void NativeReferenceV1::setTarget(const Atom* newAtom) {<br>
+ return _file->setTarget(_ivarData->targetIndex, newAtom);<br>
+}<br>
<br>
<br>
//<br>
<br>
Modified: lld/trunk/lib/Core/NativeWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/NativeWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/NativeWriter.cpp (original)<br>
+++ lld/trunk/lib/Core/NativeWriter.cpp Tue Feb 14 18:38:09 2012<br>
@@ -12,6 +12,7 @@<br>
<br>
#include "llvm/ADT/StringRef.h"<br>
#include "llvm/ADT/ArrayRef.h"<br>
+#include "llvm/ADT/DenseMap.h"<br>
<br>
#include "lld/Core/File.h"<br>
#include "lld/Core/NativeWriter.h"<br>
@@ -25,10 +26,13 @@<br>
///<br>
/// Class for writing native object files.<br>
///<br>
-class NativeWriter : public File::AtomHandler {<br>
+class NativeWriter : public File::AtomHandler,<br>
+ public DefinedAtom::ReferenceHandler {<br>
public:<br>
/// construct writer for an lld::File object<br>
NativeWriter(const lld::File& file) : _file(file) {<br>
+ // reserve first byte for unnamed atoms<br>
+ _stringPool.push_back('\0');<br>
// visit all atoms<br>
_file.forEachAtom(*this);<br>
// construct file header based on atom information accumulated<br>
@@ -37,36 +41,73 @@<br>
<br>
// write the lld::File in native format to the specified stream<br>
void write(llvm::raw_ostream& out) {<br>
+ assert( out.tell() == 0 );<br>
out.write((char*)_headerBuffer, _headerBufferSize);<br>
- if (!_definedAtomIvars.empty())<br>
+<br>
+ if (!_definedAtomIvars.empty()) {<br>
+ assert( out.tell() == findChunk(NCS_DefinedAtomsV1).fileOffset );<br>
out.write((char*)&_definedAtomIvars[0],<br>
_definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1));<br>
- if (!_attributes.empty())<br>
+ }<br>
+<br>
+ if (!_attributes.empty()) {<br>
+ assert( out.tell() == findChunk(NCS_AttributesArrayV1).fileOffset );<br>
out.write((char*)&_attributes[0],<br>
_attributes.size()*sizeof(NativeAtomAttributesV1));<br>
- if ( !_undefinedAtomIvars.empty() )<br>
+ }<br>
+<br>
+ if ( !_undefinedAtomIvars.empty() ) {<br>
+ assert( out.tell() == findChunk(NCS_UndefinedAtomsV1).fileOffset );<br>
out.write((char*)&_undefinedAtomIvars[0],<br>
_undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));<br>
- if (!_stringPool.empty())<br>
+ }<br>
+<br>
+ if (!_stringPool.empty()) {<br>
+ assert( out.tell() == findChunk(NCS_Strings).fileOffset );<br>
out.write(&_stringPool[0], _stringPool.size());<br>
- if (!_contentPool.empty())<br>
+ }<br>
+<br>
+ if ( !_references.empty() ) {<br>
+ assert( out.tell() == findChunk(NCS_ReferencesArrayV1).fileOffset );<br>
+ out.write((char*)&_references[0],<br>
+ _references.size()*sizeof(NativeReferenceIvarsV1));<br>
+ }<br>
+<br>
+ if ( !_targetsTableIndex.empty() ) {<br>
+ assert( out.tell() == findChunk(NCS_TargetsTable).fileOffset );<br>
+ writeTargetTable(out);<br>
+ }<br>
+<br>
+ if ( !_addendsTableIndex.empty() ) {<br>
+ assert( out.tell() == findChunk(NCS_AddendsTable).fileOffset );<br>
+ writeAddendTable(out);<br>
+ }<br>
+<br>
+ if (!_contentPool.empty()) {<br>
+ assert( out.tell() == findChunk(NCS_Content).fileOffset );<br>
out.write((char*)&_contentPool[0], _contentPool.size());<br>
+ }<br>
}<br>
<br>
private:<br>
<br>
// visitor routine called by forEachAtom()<br>
- virtual void doDefinedAtom(const class DefinedAtom& atom) {<br>
+ virtual void doDefinedAtom(const DefinedAtom& atom) {<br>
+ _definedAtomIndex[&atom] = _definedAtomIvars.size();<br>
NativeDefinedAtomIvarsV1 ivar;<br>
+ unsigned refsCount;<br>
ivar.nameOffset = getNameOffset(atom);<br>
ivar.attributesOffset = getAttributeOffset(atom);<br>
+ ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);<br>
+ ivar.referencesCount = refsCount;<br>
ivar.contentOffset = getContentOffset(atom);<br>
ivar.contentSize = atom.size();<br>
_definedAtomIvars.push_back(ivar);<br>
}<br>
<br>
// visitor routine called by forEachAtom()<br>
- virtual void doUndefinedAtom(const class UndefinedAtom& atom) {<br>
+ virtual void doUndefinedAtom(const UndefinedAtom& atom) {<br>
+ _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();<br>
NativeUndefinedAtomIvarsV1 ivar;<br>
ivar.nameOffset = getNameOffset(atom);<br>
ivar.flags = (atom.weakImport() ? 1 : 0);<br>
@@ -74,13 +115,18 @@<br>
}<br>
<br>
// visitor routine called by forEachAtom()<br>
- virtual void doFile(const class File &) {<br>
+ virtual void doFile(const File &) {<br>
}<br>
<br>
// fill out native file header and chunk directory<br>
void makeHeader() {<br>
const bool hasUndefines = !_undefinedAtomIvars.empty();<br>
- const int chunkCount = hasUndefines ? 5 : 4;<br>
+ const bool hasTargetsTable = !_targetsTableIndex.empty();<br>
+ const bool hasAddendTable = !_addendsTableIndex.empty();<br>
+ int chunkCount = 5;<br>
+ if ( hasUndefines ) ++chunkCount;<br>
+ if ( hasTargetsTable ) ++chunkCount;<br>
+ if ( hasAddendTable ) ++chunkCount;<br>
_headerBufferSize = sizeof(NativeFileHeader)<br>
+ chunkCount*sizeof(NativeChunk);<br>
_headerBuffer = reinterpret_cast<NativeFileHeader*><br>
@@ -124,6 +170,9 @@<br>
}<br>
<br>
// create chunk for symbol strings<br>
+ // pad end of string pool to 4-bytes<br>
+ while ( (_stringPool.size() % 4) != 0 )<br>
+ _stringPool.push_back('\0');<br>
NativeChunk& chs = chunks[nextIndex++];<br>
chs.signature = NCS_Strings;<br>
chs.fileOffset = nextFileOffset;<br>
@@ -131,6 +180,34 @@<br>
chs.elementCount = _stringPool.size();<br>
nextFileOffset = chs.fileOffset + chs.fileSize;<br>
<br>
+ // create chunk for references<br>
+ NativeChunk& chr = chunks[nextIndex++];<br>
+ chr.signature = NCS_ReferencesArrayV1;<br>
+ chr.fileOffset = nextFileOffset;<br>
+ chr.fileSize = _references.size() * sizeof(NativeReferenceIvarsV1);<br>
+ chr.elementCount = _references.size();<br>
+ nextFileOffset = chr.fileOffset + chr.fileSize;<br>
+<br>
+ // create chunk for target table<br>
+ if ( hasTargetsTable ) {<br>
+ NativeChunk& cht = chunks[nextIndex++];<br>
+ cht.signature = NCS_TargetsTable;<br>
+ cht.fileOffset = nextFileOffset;<br>
+ cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);<br>
+ cht.elementCount = _targetsTableIndex.size();<br>
+ nextFileOffset = cht.fileOffset + cht.fileSize;<br>
+ }<br>
+<br>
+ // create chunk for addend table<br>
+ if ( hasAddendTable ) {<br>
+ NativeChunk& chad = chunks[nextIndex++];<br>
+ chad.signature = NCS_AddendsTable;<br>
+ chad.fileOffset = nextFileOffset;<br>
+ chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);<br>
+ chad.elementCount = _addendsTableIndex.size();<br>
+ nextFileOffset = chad.fileOffset + chad.fileSize;<br>
+ }<br>
+<br>
// create chunk for content<br>
NativeChunk& chc = chunks[nextIndex++];<br>
chc.signature = NCS_Content;<br>
@@ -142,6 +219,18 @@<br>
_headerBuffer->fileSize = nextFileOffset;<br>
}<br>
<br>
+ // scan header to find particular chunk<br>
+ NativeChunk& findChunk(uint32_t signature) {<br>
+ const uint32_t chunkCount = _headerBuffer->chunkCount;<br>
+ NativeChunk* chunks =<br>
+ reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)<br>
+ + sizeof(NativeFileHeader));<br>
+ for (uint32_t i=0; i < chunkCount; ++i) {<br>
+ if ( chunks[i].signature == signature )<br>
+ return chunks[i];<br>
+ }<br>
+ assert(0 && "findChunk() signature not found");<br>
+ }<br>
<br>
// append atom name to string pool and return offset<br>
uint32_t getNameOffset(const Atom& atom) {<br>
@@ -150,6 +239,8 @@<br>
<br>
// append atom name to string pool and return offset<br>
uint32_t getNameOffset(llvm::StringRef name) {<br>
+ if ( name.empty() )<br>
+ return 0;<br>
uint32_t result = _stringPool.size();<br>
_stringPool.insert(_stringPool.end(), name.size()+1, 0);<br>
strcpy(&_stringPool[result], name.data());<br>
@@ -206,7 +297,6 @@<br>
attrs.sectionNameOffset = sectionNameOffset(atom);<br>
attrs.align2 = atom.alignment().powerOf2;<br>
attrs.alignModulus = atom.alignment().modulus;<br>
- attrs.internalName = atom.internalName();<br>
attrs.scope = atom.scope();<br>
attrs.interposable = atom.interposable();<br>
attrs.merge = atom.merge();<br>
@@ -214,12 +304,99 @@<br>
attrs.sectionChoice = atom.sectionChoice();<br>
attrs.deadStrip = atom.deadStrip();<br>
attrs.permissions = atom.permissions();<br>
- attrs.thumb = atom.isThumb();<br>
+ //attrs.thumb = atom.isThumb();<br>
attrs.alias = atom.isAlias();<br>
}<br>
<br>
+ // add references for this atom in a contiguous block in NCS_ReferencesArrayV1<br>
+ uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& count) {<br>
+ count = 0;<br>
+ size_t startRefSize = _references.size();<br>
+ uint32_t result = startRefSize;<br>
+ atom.forEachReference(*this);<br>
+ count = _references.size() - startRefSize;<br>
+ if ( count == 0 )<br>
+ return 0;<br>
+ else<br>
+ return result;<br>
+ }<br>
+<br>
+ void doReference(const Reference& ref) {<br>
+ NativeReferenceIvarsV1 nref;<br>
+ nref.offsetInAtom = ref.offsetInAtom();<br>
+ nref.kind = ref.kind();<br>
+ nref.targetIndex = this->getTargetIndex(ref.target());<br>
+ nref.addendIndex = this->getAddendIndex(ref.addend());<br>
+ _references.push_back(nref);<br>
+ }<br>
+<br>
+ uint32_t getTargetIndex(const Atom* target) {<br>
+ TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);<br>
+ if ( pos != _targetsTableIndex.end() ) {<br>
+ return pos->second;<br>
+ }<br>
+ uint32_t result = _targetsTableIndex.size();<br>
+ _targetsTableIndex[target] = result;<br>
+ return result;<br>
+ }<br>
+<br>
+ void writeTargetTable(llvm::raw_ostream& out) {<br>
+ // Build table of target indexes<br>
+ uint32_t maxTargetIndex = _targetsTableIndex.size();<br>
+ uint32_t targetIndexes[maxTargetIndex];<br>
+ for (TargetToIndex::iterator it = _targetsTableIndex.begin();<br>
+ it != _targetsTableIndex.end(); ++it) {<br>
+ const Atom* atom = it->first;<br>
+ uint32_t targetIndex = it->second;<br>
+ assert(targetIndex < maxTargetIndex);<br>
+ uint32_t atomIndex = 0;<br>
+ TargetToIndex::iterator pos = _definedAtomIndex.find(atom);<br>
+ if ( pos != _definedAtomIndex.end() ) {<br>
+ atomIndex = pos->second;<br>
+ }<br>
+ else {<br>
+ pos = _undefinedAtomIndex.find(atom);<br>
+ assert(pos != _undefinedAtomIndex.end());<br>
+ atomIndex = pos->second + _definedAtomIvars.size();<br>
+ }<br>
+ targetIndexes[targetIndex] = atomIndex;<br>
+ }<br>
+ // write table<br>
+ out.write((char*)&targetIndexes[0], maxTargetIndex*sizeof(uint32_t));<br>
+ }<br>
+<br>
+ uint32_t getAddendIndex(Reference::Addend addend) {<br>
+ if ( addend == 0 )<br>
+ return 0; // addend index zero is used to mean "no addend"<br>
+ AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);<br>
+ if ( pos != _addendsTableIndex.end() ) {<br>
+ return pos->second;<br>
+ }<br>
+ uint32_t result = _addendsTableIndex.size() + 1; // one-based index<br>
+ _addendsTableIndex[addend] = result;<br>
+ return result;<br>
+ }<br>
+<br>
+ void writeAddendTable(llvm::raw_ostream& out) {<br>
+ // Build table of addends<br>
+ uint32_t maxAddendIndex = _addendsTableIndex.size();<br>
+ Reference::Addend addends[maxAddendIndex];<br>
+ for (AddendToIndex::iterator it = _addendsTableIndex.begin();<br>
+ it != _addendsTableIndex.end(); ++it) {<br>
+ Reference::Addend addend = it->first;<br>
+ uint32_t index = it->second;<br>
+ assert(index <= maxAddendIndex);<br>
+ addends[index-1] = addend;<br>
+ }<br>
+ // write table<br>
+ out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));<br>
+ }<br>
+<br>
typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector;<br>
<br>
+ typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;<br>
+ typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;<br>
+<br>
const lld::File& _file;<br>
NativeFileHeader* _headerBuffer;<br>
size_t _headerBufferSize;<br>
@@ -228,6 +405,11 @@<br>
std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;<br>
std::vector<NativeAtomAttributesV1> _attributes;<br>
std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;<br>
+ std::vector<NativeReferenceIvarsV1> _references;<br>
+ TargetToIndex _targetsTableIndex;<br>
+ TargetToIndex _definedAtomIndex;<br>
+ TargetToIndex _undefinedAtomIndex;<br>
+ AddendToIndex _addendsTableIndex;<br>
NameToOffsetVector _sectionNames;<br>
};<br>
<br>
<br>
Modified: lld/trunk/lib/Core/Resolver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/Resolver.cpp (original)<br>
+++ lld/trunk/lib/Core/Resolver.cpp Tue Feb 14 18:38:09 2012<br>
@@ -199,20 +199,34 @@<br>
}<br>
}<br>
<br>
+// helper to update targets for use with forEachReference()<br>
+class ReferenceUpdater : public DefinedAtom::ReferenceHandler {<br>
+public:<br>
+ ReferenceUpdater(SymbolTable& sym) : _symbolTable(sym) { }<br>
+<br>
+ virtual void doReference(const Reference& ref) {<br>
+ const Atom* newTarget = _symbolTable.replacement(ref.target());<br>
+ (const_cast<Reference*>(&ref))->setTarget(newTarget);<br>
+ }<br>
+<br>
+private:<br>
+ SymbolTable& _symbolTable;<br>
+};<br>
+<br>
+<br>
// switch all references to undefined or coalesced away atoms<br>
// to the new defined atom<br>
void Resolver::updateReferences() {<br>
+ ReferenceUpdater updater(_symbolTable);<br>
for (std::vector<const Atom *>::iterator it = _atoms.begin();<br>
it != _atoms.end(); ++it) {<br>
if ( const DefinedAtom* defAtom = (*it)->definedAtom() ) {<br>
- for (Reference::iterator rit = defAtom->referencesBegin(),<br>
- end = defAtom->referencesEnd(); rit != end; ++rit) {<br>
- rit->target = _symbolTable.replacement(rit->target);<br>
- }<br>
+ defAtom->forEachReference(updater);<br>
}<br>
}<br>
}<br>
<br>
+<br>
// for dead code stripping, recursively mark atom "live"<br>
void Resolver::markLive(const Atom &atom, WhyLiveBackChain *previous) {<br>
// if -why_live cares about this symbol, then dump chain<br>
@@ -240,10 +254,8 @@<br>
thisChain.previous = previous;<br>
thisChain.referer = &atom;<br>
if ( const DefinedAtom* defAtom = atom.definedAtom() ) {<br>
- for (Reference::iterator rit = defAtom->referencesBegin(),<br>
- end = defAtom->referencesEnd(); rit != end; ++rit) {<br>
- this->markLive(*(rit->target), &thisChain);<br>
- }<br>
+ MarkLiveReferences markRefs(*this, &thisChain);<br>
+ defAtom->forEachReference(markRefs);<br>
}<br>
}<br>
<br>
<br>
Modified: lld/trunk/lib/Core/SymbolTable.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/SymbolTable.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/SymbolTable.cpp (original)<br>
+++ lld/trunk/lib/Core/SymbolTable.cpp Tue Feb 14 18:38:09 2012<br>
@@ -38,7 +38,7 @@<br>
<br>
void SymbolTable::add(const DefinedAtom &atom) {<br>
assert(atom.scope() != DefinedAtom::scopeTranslationUnit);<br>
- if ( !atom.internalName() ) {<br>
+ if ( !<a href="http://atom.name" target="_blank">atom.name</a>().empty() ) {<br>
this->addByName(atom);<br>
}<br>
else {<br>
<br>
Modified: lld/trunk/lib/Core/YamlKeyValues.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/YamlKeyValues.cpp (original)<br>
+++ lld/trunk/lib/Core/YamlKeyValues.cpp Tue Feb 14 18:38:09 2012<br>
@@ -18,12 +18,12 @@<br>
<br>
<br>
const char* const KeyValues::nameKeyword = "name";<br>
+const char* const KeyValues::refNameKeyword = "ref-name";<br>
const char* const KeyValues::definitionKeyword = "definition";<br>
const char* const KeyValues::scopeKeyword = "scope";<br>
const char* const KeyValues::contentTypeKeyword = "type";<br>
const char* const KeyValues::deadStripKindKeyword = "dead-strip";<br>
const char* const KeyValues::sectionChoiceKeyword = "section-choice";<br>
-const char* const KeyValues::internalNameKeyword = "internal-name";<br>
const char* const KeyValues::interposableKeyword = "interposable";<br>
const char* const KeyValues::mergeKeyword = "merge";<br>
const char* const KeyValues::isThumbKeyword = "is-thumb";<br>
@@ -31,8 +31,14 @@<br>
const char* const KeyValues::sectionNameKeyword = "section-name";<br>
const char* const KeyValues::contentKeyword = "content";<br>
const char* const KeyValues::sizeKeyword = "size";<br>
+const char* const KeyValues::fixupsKeyword = "fixups";<br>
const char* const KeyValues::permissionsKeyword = "permissions";<br>
const char* const KeyValues::weakImportKeyword = "weak-import";<br>
+const char* const KeyValues::fixupsKindKeyword = "kind";<br>
+const char* const KeyValues::fixupsOffsetKeyword = "offset";<br>
+const char* const KeyValues::fixupsTargetKeyword = "target";<br>
+const char* const KeyValues::fixupsAddendKeyword = "addend";<br>
+<br>
<br>
<br>
const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular;<br>
@@ -43,7 +49,6 @@<br>
const DefinedAtom::Interposable KeyValues::interposableDefault = DefinedAtom::interposeNo;<br>
const DefinedAtom::Merge KeyValues::mergeDefault = DefinedAtom::mergeNo;<br>
const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAtom::permR__;<br>
-const bool KeyValues::internalNameDefault = false;<br>
const bool KeyValues::isThumbDefault = false;<br>
const bool KeyValues::isAliasDefault = false;<br>
const bool KeyValues::weakImportDefault = false;<br>
@@ -352,22 +357,6 @@<br>
<br>
<br>
<br>
-bool KeyValues::internalName(const char* s)<br>
-{<br>
- if ( strcmp(s, "true") == 0 )<br>
- return true;<br>
- else if ( strcmp(s, "false") == 0 )<br>
- return false;<br>
- llvm::report_fatal_error("bad internal-name value");<br>
-}<br>
-<br>
-const char* KeyValues::internalName(bool b) {<br>
- return b ? "true" : "false";<br>
-}<br>
-<br>
-<br>
-<br>
-<br>
bool KeyValues::isThumb(const char* s)<br>
{<br>
if ( strcmp(s, "true") == 0 )<br>
<br>
Modified: lld/trunk/lib/Core/YamlKeyValues.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlKeyValues.h?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/YamlKeyValues.h (original)<br>
+++ lld/trunk/lib/Core/YamlKeyValues.h Tue Feb 14 18:38:09 2012<br>
@@ -20,10 +20,12 @@<br>
class KeyValues {<br>
public:<br>
static const char* const nameKeyword;<br>
+ static const char* const refNameKeyword;<br>
static const char* const sectionNameKeyword;<br>
static const char* const contentKeyword;<br>
static const char* const sizeKeyword;<br>
-<br>
+ static const char* const fixupsKeyword;<br>
+<br>
static const char* const definitionKeyword;<br>
static const Atom::Definition definitionDefault;<br>
static Atom::Definition definition(const char*);<br>
@@ -64,11 +66,6 @@<br>
static DefinedAtom::ContentPermissions permissions(const char*);<br>
static const char* permissions(DefinedAtom::ContentPermissions);<br>
<br>
- static const char* const internalNameKeyword;<br>
- static const bool internalNameDefault;<br>
- static bool internalName(const char*);<br>
- static const char* internalName(bool);<br>
-<br>
static const char* const isThumbKeyword;<br>
static const bool isThumbDefault;<br>
static bool isThumb(const char*);<br>
@@ -84,6 +81,12 @@<br>
static bool weakImport(const char*);<br>
static const char* weakImport(bool);<br>
<br>
+<br>
+ static const char* const fixupsKindKeyword;<br>
+ static const char* const fixupsOffsetKeyword;<br>
+ static const char* const fixupsTargetKeyword;<br>
+ static const char* const fixupsAddendKeyword;<br>
+<br>
};<br>
<br>
} // namespace yaml<br>
<br>
Modified: lld/trunk/lib/Core/YamlReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlReader.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/YamlReader.cpp (original)<br>
+++ lld/trunk/lib/Core/YamlReader.cpp Tue Feb 14 18:38:09 2012<br>
@@ -7,6 +7,8 @@<br>
//<br>
//===----------------------------------------------------------------------===//<br>
<br>
+#include <string.h><br>
+<br>
#include "YamlKeyValues.h"<br>
<br>
#include "lld/Core/YamlReader.h"<br>
@@ -30,6 +32,8 @@<br>
namespace lld {<br>
namespace yaml {<br>
<br>
+namespace {<br>
+<br>
class YAML {<br>
public:<br>
struct Entry {<br>
@@ -214,7 +218,7 @@<br>
sequenceBytes->push_back(contentByte);<br>
state = inValueSequenceEnd;<br>
}<br>
- else if (c == ' ') {<br>
+ else if ( (c == ' ') || (c == '\n') ) {<br>
// eat white space<br>
}<br>
else if (c == ',') {<br>
@@ -245,6 +249,44 @@<br>
}<br>
}<br>
<br>
+<br>
+<br>
+class YAMLReference : public Reference {<br>
+public:<br>
+ YAMLReference() : _target(NULL), _targetName(NULL),<br>
+ _offsetInAtom(0), _addend(0), _kind(0) { }<br>
+<br>
+ virtual uint64_t offsetInAtom() const {<br>
+ return _offsetInAtom;<br>
+ }<br>
+<br>
+ virtual Kind kind() const {<br>
+ return _kind;<br>
+ }<br>
+<br>
+ virtual const Atom* target() const {<br>
+ return _target;<br>
+ }<br>
+<br>
+ virtual Addend addend() const {<br>
+ return _addend;<br>
+ }<br>
+<br>
+ virtual void setTarget(const Atom* newAtom) {<br>
+ _target = newAtom;<br>
+ }<br>
+<br>
+ const Atom* _target;<br>
+ const char* _targetName;<br>
+ uint64_t _offsetInAtom;<br>
+ Addend _addend;<br>
+ Kind _kind;<br>
+};<br>
+<br>
+<br>
+<br>
+class YAMLDefinedAtom;<br>
+<br>
class YAMLFile : public File {<br>
public:<br>
YAMLFile()<br>
@@ -255,29 +297,24 @@<br>
virtual bool justInTimeforEachAtom(llvm::StringRef name,<br>
File::AtomHandler &) const;<br>
<br>
- std::vector<DefinedAtom*> _definedAtoms;<br>
- std::vector<UndefinedAtom*> _undefinedAtoms;<br>
- std::vector<Reference> _references;<br>
- unsigned int _lastRefIndex;<br>
-};<br>
+ void bindTargetReferences();<br>
+ void addDefinedAtom(YAMLDefinedAtom* atom, const char* refName);<br>
+ void addUndefinedAtom(UndefinedAtom* atom);<br>
+ Atom* findAtom(const char* name);<br>
+<br>
+ struct NameAtomPair {<br>
+ NameAtomPair(const char* n, Atom* a) : name(n), atom(a) {}<br>
+ const char* name;<br>
+ Atom* atom;<br>
+ };<br>
<br>
-bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {<br>
- handler.doFile(*this);<br>
- for (std::vector<DefinedAtom *>::const_iterator it = _definedAtoms.begin();<br>
- it != _definedAtoms.end(); ++it) {<br>
- handler.doDefinedAtom(**it);<br>
- }<br>
- for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();<br>
- it != _undefinedAtoms.end(); ++it) {<br>
- handler.doUndefinedAtom(**it);<br>
- }<br>
- return true;<br>
-}<br>
+ std::vector<YAMLDefinedAtom*> _definedAtoms;<br>
+ std::vector<UndefinedAtom*> _undefinedAtoms;<br>
+ std::vector<YAMLReference> _references;<br>
+ std::vector<NameAtomPair> _nameToAtomMapping;<br>
+ unsigned int _lastRefIndex;<br>
+};<br>
<br>
-bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,<br>
- File::AtomHandler &handler) const {<br>
- return false;<br>
-}<br>
<br>
<br>
class YAMLDefinedAtom : public DefinedAtom {<br>
@@ -291,7 +328,6 @@<br>
, DefinedAtom::Merge merge<br>
, DefinedAtom::DeadStripKind deadStrip<br>
, DefinedAtom::ContentPermissions perms<br>
- , bool internalName<br>
, bool isThumb<br>
, bool isAlias<br>
, DefinedAtom::Alignment alignment<br>
@@ -313,7 +349,6 @@<br>
, _merge(merge)<br>
, _deadStrip(deadStrip)<br>
, _permissions(perms)<br>
- , _internalName(internalName)<br>
, _isThumb(isThumb)<br>
, _isAlias(isAlias)<br>
, _refStartIndex(file._lastRefIndex)<br>
@@ -326,13 +361,12 @@<br>
}<br>
<br>
virtual llvm::StringRef name() const {<br>
- return _name;<br>
+ if ( _name == NULL )<br>
+ return llvm::StringRef();<br>
+ else<br>
+ return _name;<br>
}<br>
<br>
- virtual bool internalName() const {<br>
- return _internalName;<br>
- }<br>
-<br>
virtual uint64_t size() const {<br>
return (_content ? _content->size() : _size);<br>
}<br>
@@ -393,16 +427,18 @@<br>
}<br>
<br>
<br>
- virtual Reference::iterator referencesBegin() const {<br>
- if (_file._references.size() < _refStartIndex)<br>
- return (Reference::iterator)&_file._references[_refStartIndex];<br>
- return 0;<br>
+ virtual void forEachReference(ReferenceHandler& handler) const {<br>
+ for (uint32_t i=_refStartIndex; i < _refEndIndex; ++i) {<br>
+ handler.doReference(_file._references[i]);<br>
+ }<br>
}<br>
-<br>
- virtual Reference::iterator referencesEnd() const {<br>
- if (_file._references.size() < _refEndIndex)<br>
- return (Reference::iterator)&_file._references[_refEndIndex];<br>
- return 0;<br>
+<br>
+ void bindTargetReferences() {<br>
+ for (unsigned int i=_refStartIndex; i < _refEndIndex; ++i) {<br>
+ const char* targetName = _file._references[i]._targetName;<br>
+ Atom* targetAtom = _file.findAtom(targetName);<br>
+ _file._references[i]._target = targetAtom;<br>
+ }<br>
}<br>
<br>
private:<br>
@@ -420,7 +456,6 @@<br>
DefinedAtom::Merge _merge;<br>
DefinedAtom::DeadStripKind _deadStrip;<br>
DefinedAtom::ContentPermissions _permissions;<br>
- bool _internalName;<br>
bool _isThumb;<br>
bool _isAlias;<br>
unsigned int _refStartIndex;<br>
@@ -453,22 +488,71 @@<br>
};<br>
<br>
<br>
+bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {<br>
+ handler.doFile(*this);<br>
+ for (std::vector<YAMLDefinedAtom *>::const_iterator it = _definedAtoms.begin();<br>
+ it != _definedAtoms.end(); ++it) {<br>
+ handler.doDefinedAtom(**it);<br>
+ }<br>
+ for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();<br>
+ it != _undefinedAtoms.end(); ++it) {<br>
+ handler.doUndefinedAtom(**it);<br>
+ }<br>
+ return true;<br>
+}<br>
+<br>
+bool YAMLFile::justInTimeforEachAtom(llvm::StringRef name,<br>
+ File::AtomHandler &handler) const {<br>
+ return false;<br>
+}<br>
+<br>
+void YAMLFile::bindTargetReferences() {<br>
+ for (std::vector<YAMLDefinedAtom *>::const_iterator<br>
+ it = _definedAtoms.begin(); it != _definedAtoms.end(); ++it) {<br>
+ YAMLDefinedAtom* atom = *it;<br>
+ atom->bindTargetReferences();<br>
+ }<br>
+}<br>
+<br>
+Atom* YAMLFile::findAtom(const char* name) {<br>
+ for (std::vector<NameAtomPair>::const_iterator it = _nameToAtomMapping.begin();<br>
+ it != _nameToAtomMapping.end(); ++it) {<br>
+ if ( strcmp(name, it->name) == 0 )<br>
+ return it->atom;<br>
+ }<br>
+ llvm::report_fatal_error("reference to atom that does not exist");<br>
+}<br>
+<br>
+void YAMLFile::addDefinedAtom(YAMLDefinedAtom* atom, const char* refName) {<br>
+ _definedAtoms.push_back(atom);<br>
+ assert(refName != NULL);<br>
+ _nameToAtomMapping.push_back(NameAtomPair(refName, atom));<br>
+}<br>
+<br>
+void YAMLFile::addUndefinedAtom(UndefinedAtom* atom) {<br>
+ _undefinedAtoms.push_back(atom);<br>
+ _nameToAtomMapping.push_back(NameAtomPair(atom->name().data(), atom));<br>
+}<br>
+<br>
<br>
class YAMLAtomState {<br>
public:<br>
YAMLAtomState();<br>
<br>
void setName(const char *n);<br>
+ void setRefName(const char *n);<br>
void setAlign2(const char *n);<br>
<br>
void setFixupKind(const char *n);<br>
void setFixupOffset(const char *n);<br>
void setFixupTarget(const char *n);<br>
+ void setFixupAddend(const char *n);<br>
void addFixup(YAMLFile *f);<br>
<br>
void makeAtom(YAMLFile&);<br>
<br>
const char * _name;<br>
+ const char * _refName;<br>
const char * _sectionName;<br>
unsigned long long _size;<br>
uint32_t _ordinal;<br>
@@ -482,16 +566,16 @@<br>
DefinedAtom::Merge _merge;<br>
DefinedAtom::DeadStripKind _deadStrip;<br>
DefinedAtom::ContentPermissions _permissions;<br>
- bool _internalName;<br>
bool _isThumb;<br>
bool _isAlias;<br>
bool _weakImport;<br>
- Reference _ref;<br>
+ YAMLReference _ref;<br>
};<br>
<br>
<br>
YAMLAtomState::YAMLAtomState()<br>
: _name(NULL)<br>
+ , _refName(NULL)<br>
, _sectionName(NULL)<br>
, _size(0)<br>
, _ordinal(0)<br>
@@ -505,38 +589,31 @@<br>
, _merge(KeyValues::mergeDefault)<br>
, _deadStrip(KeyValues::deadStripKindDefault)<br>
, _permissions(KeyValues::permissionsDefault)<br>
- , _internalName(KeyValues::internalNameDefault)<br>
, _isThumb(KeyValues::isThumbDefault)<br>
, _isAlias(KeyValues::isAliasDefault)<br>
, _weakImport(false)<br>
{<br>
- _ref.target = NULL;<br>
- _ref.addend = 0;<br>
- _ref.offsetInAtom = 0;<br>
- _ref.kind = 0;<br>
- _ref.flags = 0;<br>
-}<br>
+ }<br>
<br>
<br>
void YAMLAtomState::makeAtom(YAMLFile& f) {<br>
if ( _definition == Atom::definitionRegular ) {<br>
- DefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,<br>
+ YAMLDefinedAtom *a = new YAMLDefinedAtom(_ordinal, f, _scope, _type,<br>
_sectionChoice, _interpose, _merge, _deadStrip,<br>
- _permissions, _internalName, _isThumb, _isAlias,<br>
+ _permissions, _isThumb, _isAlias,<br>
_alignment, _name, _sectionName, _size, _content);<br>
-<br>
- f._definedAtoms.push_back(a);<br>
+ f.addDefinedAtom(a, _refName ? _refName : _name);<br>
++_ordinal;<br>
}<br>
else if ( _definition == Atom::definitionUndefined ) {<br>
UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);<br>
-<br>
- f._undefinedAtoms.push_back(a);<br>
+ f.addUndefinedAtom(a);<br>
++_ordinal;<br>
}<br>
<br>
// reset state for next atom<br>
_name = NULL;<br>
+ _refName = NULL;<br>
_sectionName = NULL;<br>
_size = 0;<br>
_ordinal = 0;<br>
@@ -554,17 +631,20 @@<br>
_isThumb = KeyValues::isThumbDefault;<br>
_isAlias = KeyValues::isAliasDefault;<br>
_weakImport = KeyValues::weakImportDefault;<br>
- _ref.target = NULL;<br>
- _ref.addend = 0;<br>
- _ref.offsetInAtom = 0;<br>
- _ref.kind = 0;<br>
- _ref.flags = 0;<br>
+ _ref._target = NULL;<br>
+ _ref._targetName = NULL;<br>
+ _ref._addend = 0;<br>
+ _ref._offsetInAtom = 0;<br>
+ _ref._kind = 0;<br>
}<br>
<br>
void YAMLAtomState::setName(const char *n) {<br>
_name = n;<br>
}<br>
<br>
+void YAMLAtomState::setRefName(const char *n) {<br>
+ _refName = n;<br>
+}<br>
<br>
void YAMLAtomState::setAlign2(const char *s) {<br>
llvm::StringRef str(s);<br>
@@ -576,33 +656,54 @@<br>
<br>
void YAMLAtomState::setFixupKind(const char *s) {<br>
if (strcmp(s, "pcrel32") == 0)<br>
- _ref.kind = 1;<br>
+ _ref._kind = 1;<br>
else if (strcmp(s, "call32") == 0)<br>
- _ref.kind = 2;<br>
- else<br>
- llvm::report_fatal_error("bad fixup kind value");<br>
+ _ref._kind = 2;<br>
+ else {<br>
+ int k;<br>
+ llvm::StringRef(s).getAsInteger(10, k);<br>
+ _ref._kind = k;<br>
+ }<br>
}<br>
<br>
void YAMLAtomState::setFixupOffset(const char *s) {<br>
if ((s[0] == '0') && (s[1] == 'x'))<br>
- llvm::StringRef(s).getAsInteger(16, _ref.offsetInAtom);<br>
+ llvm::StringRef(s).getAsInteger(16, _ref._offsetInAtom);<br>
else<br>
- llvm::StringRef(s).getAsInteger(10, _ref.offsetInAtom);<br>
+ llvm::StringRef(s).getAsInteger(10, _ref._offsetInAtom);<br>
}<br>
<br>
void YAMLAtomState::setFixupTarget(const char *s) {<br>
+ _ref._targetName = s;<br>
}<br>
<br>
+void YAMLAtomState::setFixupAddend(const char *s) {<br>
+ if ((s[0] == '0') && (s[1] == 'x'))<br>
+ llvm::StringRef(s).getAsInteger(16, _ref._addend);<br>
+ else<br>
+ llvm::StringRef(s).getAsInteger(10, _ref._addend);<br>
+}<br>
+<br>
+<br>
void YAMLAtomState::addFixup(YAMLFile *f) {<br>
f->_references.push_back(_ref);<br>
// clear for next ref<br>
- _ref.target = NULL;<br>
- _ref.addend = 0;<br>
- _ref.offsetInAtom = 0;<br>
- _ref.kind = 0;<br>
- _ref.flags = 0;<br>
+ _ref._target = NULL;<br>
+ _ref._targetName = NULL;<br>
+ _ref._addend = 0;<br>
+ _ref._offsetInAtom = 0;<br>
+ _ref._kind = 0;<br>
}<br>
<br>
+<br>
+} // anonymous namespace<br>
+<br>
+<br>
+<br>
+<br>
+<br>
+/// parseObjectText - Parse the specified YAML formatted MemoryBuffer<br>
+/// into lld::File object(s) and append each to the specified vector<File*>.<br>
llvm::error_code parseObjectText( llvm::MemoryBuffer *mb<br>
, std::vector<File *> &result) {<br>
std::vector<const YAML::Entry *> entries;<br>
@@ -628,6 +729,7 @@<br>
atomState.makeAtom(*file);<br>
haveAtom = false;<br>
}<br>
+ file->bindTargetReferences();<br>
result.push_back(file);<br>
}<br>
file = new YAMLFile();<br>
@@ -663,10 +765,10 @@<br>
atomState.setName(entry->value);<br>
haveAtom = true;<br>
}<br>
- else if (strcmp(entry->key, KeyValues::internalNameKeyword) == 0) {<br>
- atomState._internalName = KeyValues::internalName(entry->value);<br>
+ else if (strcmp(entry->key, KeyValues::refNameKeyword) == 0) {<br>
+ atomState.setRefName(entry->value);<br>
haveAtom = true;<br>
- }<br>
+ }<br>
else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) {<br>
atomState._definition = KeyValues::definition(entry->value);<br>
haveAtom = true;<br>
@@ -725,8 +827,9 @@<br>
atomState.setAlign2(entry->value);<br>
haveAtom = true;<br>
}<br>
- else if (strcmp(entry->key, "fixups") == 0) {<br>
+ else if (strcmp(entry->key, KeyValues::fixupsKeyword) == 0) {<br>
inFixups = true;<br>
+<br>
}<br>
else {<br>
return make_error_code(yaml_reader_error::unknown_keyword);<br>
@@ -739,16 +842,22 @@<br>
haveFixup = false;<br>
}<br>
}<br>
- if (strcmp(entry->key, "kind") == 0) {<br>
+ if (strcmp(entry->key, KeyValues::fixupsKindKeyword) == 0) {<br>
atomState.setFixupKind(entry->value);<br>
haveFixup = true;<br>
- } else if (strcmp(entry->key, "offset") == 0) {<br>
+ }<br>
+ else if (strcmp(entry->key, KeyValues::fixupsOffsetKeyword) == 0) {<br>
atomState.setFixupOffset(entry->value);<br>
haveFixup = true;<br>
- } else if (strcmp(entry->key, "target") == 0) {<br>
+ }<br>
+ else if (strcmp(entry->key, KeyValues::fixupsTargetKeyword) == 0) {<br>
atomState.setFixupTarget(entry->value);<br>
haveFixup = true;<br>
}<br>
+ else if (strcmp(entry->key, KeyValues::fixupsAddendKeyword) == 0) {<br>
+ atomState.setFixupAddend(entry->value);<br>
+ haveFixup = true;<br>
+ }<br>
}<br>
}<br>
lastDepth = entry->depth;<br>
@@ -757,10 +866,12 @@<br>
atomState.makeAtom(*file);<br>
}<br>
<br>
+ file->bindTargetReferences();<br>
result.push_back(file);<br>
return make_error_code(yaml_reader_error::success);<br>
}<br>
<br>
+<br>
//<br>
// Fill in vector<File*> from path to input text file.<br>
//<br>
<br>
Modified: lld/trunk/lib/Core/YamlWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/YamlWriter.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/Core/YamlWriter.cpp (original)<br>
+++ lld/trunk/lib/Core/YamlWriter.cpp Tue Feb 14 18:38:09 2012<br>
@@ -15,6 +15,8 @@<br>
#include "lld/Core/Reference.h"<br>
<br>
#include "llvm/ADT/OwningPtr.h"<br>
+#include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/StringExtras.h"<br>
#include "llvm/ADT/ArrayRef.h"<br>
#include "llvm/ADT/StringExtras.h"<br>
#include "llvm/Support/DataTypes.h"<br>
@@ -26,50 +28,154 @@<br>
namespace lld {<br>
namespace yaml {<br>
<br>
-class Handler : public File::AtomHandler {<br>
+namespace {<br>
+///<br>
+/// In most cases, atoms names are unambiguous, so references can just<br>
+/// use the atom name as the target (e.g. target: foo). But in a few<br>
+/// cases that does not work, so ref-names are added. These are labels<br>
+/// used only in yaml. The labels do not exist in the Atom model.<br>
+///<br>
+/// One need for ref-names are when atoms have no user supplied name<br>
+/// (e.g. c-string literal). Another case is when two object files with<br>
+/// identically named static functions are merged (ld -r) into one object file.<br>
+/// In that case referencing the function by name is ambiguous, so a unique<br>
+/// ref-name is added.<br>
+///<br>
+class RefNameBuilder : public File::AtomHandler,<br>
+ public DefinedAtom::ReferenceHandler {<br>
public:<br>
- Handler(llvm::raw_ostream &out) : _out(out), _firstAtom(true) { }<br>
+ RefNameBuilder() { }<br>
+<br>
+ virtual void doReference(const Reference& ref) {<br>
+ // create refname for any unnamed reference target<br>
+ if ( ref.target()->name().empty() ) {<br>
+ char* buffer;<br>
+ asprintf(&buffer, "L%03d", _unnamedCounter++);<br>
+ _refNames[ref.target()] = buffer;<br>
+ }<br>
+ }<br>
+<br>
+ virtual void doFile(const File &) { }<br>
+<br>
+ virtual void doDefinedAtom(const DefinedAtom& atom) {<br>
+ // Build map of atoms names to detect duplicates<br>
+ if ( ! <a href="http://atom.name" target="_blank">atom.name</a>().empty() )<br>
+ buildDuplicateNameMap(atom);<br>
+<br>
+ // Find references to unnamed atoms and create ref-names for them.<br>
+ _unnamedCounter = 0;<br>
+ atom.forEachReference(*this);<br>
+ }<br>
+<br>
+ virtual void doUndefinedAtom(const UndefinedAtom& atom) {<br>
+ buildDuplicateNameMap(atom);<br>
+ }<br>
+<br>
+ void buildDuplicateNameMap(const Atom& atom) {<br>
+ assert(!<a href="http://atom.name" target="_blank">atom.name</a>().empty());<br>
+ NameToAtom::iterator pos = _nameMap.find(<a href="http://atom.name" target="_blank">atom.name</a>());<br>
+ if ( pos != _nameMap.end() ) {<br>
+ // Found name collision, give each a unique ref-name.<br>
+ char* buffer;<br>
+ asprintf(&buffer, "%s.%03d", <a href="http://atom.name" target="_blank">atom.name</a>().data(), ++_collisionCount);<br>
+ _refNames[&atom] = buffer;<br>
+ const Atom* prevAtom = pos->second;<br>
+ AtomToRefName::iterator pos2 = _refNames.find(prevAtom);<br>
+ if ( pos2 == _refNames.end() ) {<br>
+ // only create ref-name for previous if none already created<br>
+ asprintf(&buffer, "%s.%03d", prevAtom->name().data(), ++_collisionCount);<br>
+ _refNames[prevAtom] = buffer;<br>
+ }<br>
+ }<br>
+ else {<br>
+ // First time we've seen this name, just add it to map.<br>
+ _nameMap[<a href="http://atom.name" target="_blank">atom.name</a>()] = &atom;<br>
+ }<br>
+ }<br>
+<br>
+ bool hasRefName(const Atom* atom) {<br>
+ return _refNames.count(atom);<br>
+ }<br>
+<br>
+ const char* refName(const Atom* atom) {<br>
+ return _refNames.find(atom)->second;<br>
+ }<br>
+<br>
+private:<br>
+ struct MyMappingInfo {<br>
+ static llvm::StringRef getEmptyKey() { return llvm::StringRef(); }<br>
+ static llvm::StringRef getTombstoneKey() { return llvm::StringRef(" ", 0); }<br>
+ static unsigned getHashValue(llvm::StringRef const val) {<br>
+ return llvm::HashString(val); }<br>
+ static bool isEqual(llvm::StringRef const lhs,<br>
+ llvm::StringRef const rhs) { return lhs.equals(rhs); }<br>
+ };<br>
+ typedef llvm::DenseMap<llvm::StringRef, const Atom*, MyMappingInfo> NameToAtom;<br>
+ typedef llvm::DenseMap<const Atom*, const char*> AtomToRefName;<br>
+<br>
+ unsigned int _collisionCount;<br>
+ unsigned int _unnamedCounter;<br>
+ NameToAtom _nameMap;<br>
+ AtomToRefName _refNames;<br>
+};<br>
+<br>
+<br>
+///<br>
+/// Helper class for writeObjectText() to write out atoms in yaml format.<br>
+///<br>
+class AtomWriter : public File::AtomHandler,<br>
+ public DefinedAtom::ReferenceHandler {<br>
+public:<br>
+ AtomWriter(RefNameBuilder& rnb, llvm::raw_ostream &out)<br>
+ : _out(out), _rnb(rnb), _firstAtom(true) { }<br>
<br>
virtual void doFile(const class File &) { _firstAtom = true; }<br>
<br>
virtual void doDefinedAtom(const class DefinedAtom &atom) {<br>
- // add blank line between atoms for readability<br>
- if ( !_firstAtom )<br>
- _out << "\n";<br>
- _firstAtom = false;<br>
-<br>
+ // add blank line between atoms for readability<br>
+ if ( !_firstAtom )<br>
+ _out << "\n";<br>
+ _firstAtom = false;<br>
+<br>
+ bool hasDash = false;<br>
+ if ( !<a href="http://atom.name" target="_blank">atom.name</a>().empty() ) {<br>
_out << " - "<br>
<< KeyValues::nameKeyword<br>
<< ":"<br>
<< spacePadding(KeyValues::nameKeyword)<br>
<< <a href="http://atom.name" target="_blank">atom.name</a>()<br>
<< "\n";<br>
-<br>
- if ( atom.internalName() != KeyValues::internalNameDefault ) {<br>
- _out << " "<br>
- << KeyValues::internalNameKeyword<br>
+ hasDash = true;<br>
+ }<br>
+<br>
+ if ( _rnb.hasRefName(&atom) ) {<br>
+ _out << (hasDash ? " " : " - ")<br>
+ << KeyValues::refNameKeyword<br>
<< ":"<br>
- << spacePadding(KeyValues::internalNameKeyword)<br>
- << KeyValues::internalName(atom.internalName())<br>
+ << spacePadding(KeyValues::refNameKeyword)<br>
+ << _rnb.refName(&atom)<br>
<< "\n";<br>
+ hasDash = true;<br>
}<br>
<br>
if ( atom.definition() != KeyValues::definitionDefault ) {<br>
- _out << " "<br>
+ _out << (hasDash ? " " : " - ")<br>
<< KeyValues::definitionKeyword<br>
<< ":"<br>
<< spacePadding(KeyValues::definitionKeyword)<br>
<< KeyValues::definition(atom.definition())<br>
<< "\n";<br>
+ hasDash = true;<br>
}<br>
<br>
if ( atom.scope() != KeyValues::scopeDefault ) {<br>
- _out << " "<br>
+ _out << (hasDash ? " " : " - ")<br>
<< KeyValues::scopeKeyword<br>
<< ":"<br>
<< spacePadding(KeyValues::scopeKeyword)<br>
<< KeyValues::scope(atom.scope())<br>
<< "\n";<br>
+ hasDash = true;<br>
}<br>
<br>
if ( atom.interposable() != KeyValues::interposableDefault ) {<br>
@@ -161,17 +267,51 @@<br>
_out << " ]\n";<br>
}<br>
<br>
- if (atom.referencesBegin() != atom.referencesEnd()) {<br>
+ _wroteFirstFixup = false;<br>
+ atom.forEachReference(*this);<br>
+ }<br>
+<br>
+ virtual void doReference(const Reference& ref) {<br>
+ if ( !_wroteFirstFixup ) {<br>
_out << " fixups:\n";<br>
- for (Reference::iterator it = atom.referencesBegin(),<br>
- end = atom.referencesEnd(); it != end; ++it) {<br>
- _out << " - kind: " << it->kind << "\n";<br>
- _out << " offset: " << it->offsetInAtom << "\n";<br>
- }<br>
+ _wroteFirstFixup = true;<br>
+ }<br>
+ _out << " - "<br>
+ << KeyValues::fixupsOffsetKeyword<br>
+ << ":"<br>
+ << spacePadding(KeyValues::fixupsOffsetKeyword)<br>
+ << ref.offsetInAtom()<br>
+ << "\n";<br>
+ _out << " "<br>
+ << KeyValues::fixupsKindKeyword<br>
+ << ":"<br>
+ << spacePadding(KeyValues::fixupsKindKeyword)<br>
+ << ref.kind()<br>
+ << "\n";<br>
+ const Atom* target = ref.target();<br>
+ if ( target != NULL ) {<br>
+ llvm::StringRef refName = target->name();<br>
+ if ( _rnb.hasRefName(target) )<br>
+ refName = _rnb.refName(target);<br>
+ assert(!refName.empty());<br>
+ _out << " "<br>
+ << KeyValues::fixupsTargetKeyword<br>
+ << ":"<br>
+ << spacePadding(KeyValues::fixupsTargetKeyword)<br>
+ << refName<br>
+ << "\n";<br>
+ }<br>
+ if ( ref.addend() != 0 ) {<br>
+ _out << " "<br>
+ << KeyValues::fixupsAddendKeyword<br>
+ << ":"<br>
+ << spacePadding(KeyValues::fixupsAddendKeyword)<br>
+ << ref.addend()<br>
+ << "\n";<br>
}<br>
-<br>
}<br>
<br>
+<br>
virtual void doUndefinedAtom(const class UndefinedAtom &atom) {<br>
// add blank line between atoms for readability<br>
if ( !_firstAtom )<br>
@@ -219,11 +359,26 @@<br>
}<br>
<br>
llvm::raw_ostream& _out;<br>
+ RefNameBuilder _rnb;<br>
bool _firstAtom;<br>
+ bool _wroteFirstFixup;<br>
};<br>
<br>
+} // anonymous namespace<br>
+<br>
+<br>
+<br>
+///<br>
+/// writeObjectText - writes the lld::File object as in YAML<br>
+/// format to the specified stream.<br>
+///<br>
void writeObjectText(const File &file, llvm::raw_ostream &out) {<br>
- Handler h(out);<br>
+ // Figure what ref-name labels are needed<br>
+ RefNameBuilder rnb;<br>
+ file.forEachAtom(rnb);<br>
+<br>
+ // Write out all atoms<br>
+ AtomWriter h(rnb, out);<br>
out << "---\n";<br>
out << "atoms:\n";<br>
file.forEachAtom(h);<br>
<br>
Modified: lld/trunk/test/cstring-coalesce.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/cstring-coalesce.objtxt?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/cstring-coalesce.objtxt?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/test/cstring-coalesce.objtxt (original)<br>
+++ lld/trunk/test/cstring-coalesce.objtxt Tue Feb 14 18:38:09 2012<br>
@@ -6,28 +6,24 @@<br>
<br>
---<br>
atoms:<br>
- - name: L0<br>
- internal-name: true<br>
+ - ref-name: L0<br>
scope: hidden<br>
type: c-string<br>
content: [ 68, 65, 6c, 6c, 6f, 00 ]<br>
<br>
- - name: L1<br>
- internal-name: true<br>
+ - ref-name: L1<br>
scope: hidden<br>
type: c-string<br>
content: [ 74, 68, 65, 72, 65, 00 ]<br>
---<br>
atoms:<br>
- - name: L2<br>
- internal-name: true<br>
+ - ref-name: L2<br>
scope: hidden<br>
type: c-string<br>
content: [ 68, 65, 6c, 6c, 6f, 00 ]<br>
---<br>
atoms:<br>
- - name: L2<br>
- internal-name: true<br>
+ - ref-name: L2<br>
scope: hidden<br>
type: c-string<br>
content: [ 74, 68, 65, 72, 65, 00 ]<br>
<br>
Added: lld/trunk/test/fixups-addend.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-addend.objtxt?rev=150539&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-addend.objtxt?rev=150539&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/fixups-addend.objtxt (added)<br>
+++ lld/trunk/test/fixups-addend.objtxt Tue Feb 14 18:38:09 2012<br>
@@ -0,0 +1,50 @@<br>
+# RUN: lld-core %s | FileCheck %s<br>
+<br>
+#<br>
+# Test addends in fixups<br>
+#<br>
+<br>
+---<br>
+atoms:<br>
+ - name: foo<br>
+ type: code<br>
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,<br>
+ 48, 8D, 3D, 00, 00, 00, 00 ]<br>
+ fixups:<br>
+ - offset: 3<br>
+ kind: 3<br>
+ target: bar<br>
+ addend: 100<br>
+ - offset: 10<br>
+ kind: 3<br>
+ target: bar<br>
+ addend: -50<br>
+<br>
+ - name: func<br>
+ type: code<br>
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,<br>
+ 48, 8D, 3D, 00, 00, 00, 00 ]<br>
+ fixups:<br>
+ - offset: 3<br>
+ kind: 3<br>
+ target: bar<br>
+ addend: 8000000000<br>
+ - offset: 10<br>
+ kind: 3<br>
+ target: bar<br>
+ addend: -50<br>
+<br>
+ - name: bar<br>
+ definition: undefined<br>
+<br>
+<br>
+...<br>
+<br>
+# CHECK: name: foo<br>
+# CHECK: fixups:<br>
+# CHECK: addend: 100<br>
+# CHECK: addend: -50<br>
+# CHECK: name: func<br>
+# CHECK: fixups:<br>
+# CHECK: addend: 8000000000<br>
+# CHECK: addend: -50<br>
<br>
Added: lld/trunk/test/fixups-dup-named.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-dup-named.objtxt?rev=150539&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-dup-named.objtxt?rev=150539&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/fixups-dup-named.objtxt (added)<br>
+++ lld/trunk/test/fixups-dup-named.objtxt Tue Feb 14 18:38:09 2012<br>
@@ -0,0 +1,31 @@<br>
+# RUN: lld-core %s | FileCheck %s<br>
+<br>
+#<br>
+# Test fixups referencing multiple atoms that have the same name<br>
+#<br>
+<br>
+---<br>
+atoms:<br>
+ - name: foo<br>
+ type: code<br>
+ content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]<br>
+ fixups:<br>
+ - offset: 1<br>
+ kind: 3<br>
+ target: bar_1<br>
+ - offset: 6<br>
+ kind: 3<br>
+ target: bar_2<br>
+<br>
+ - name: bar<br>
+ ref-name: bar_1<br>
+ scope: static<br>
+<br>
+ - name: bar<br>
+ ref-name: bar_2<br>
+ scope: static<br>
+<br>
+<br>
+...<br>
+<br>
+# CHECK: ...<br>
<br>
Added: lld/trunk/test/fixups-named.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-named.objtxt?rev=150539&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-named.objtxt?rev=150539&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/fixups-named.objtxt (added)<br>
+++ lld/trunk/test/fixups-named.objtxt Tue Feb 14 18:38:09 2012<br>
@@ -0,0 +1,35 @@<br>
+# RUN: lld-core %s | FileCheck %s<br>
+<br>
+#<br>
+# Test fixups to simple named atoms<br>
+#<br>
+<br>
+---<br>
+atoms:<br>
+ - name: foo<br>
+ type: code<br>
+ content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00, 00 ]<br>
+ fixups:<br>
+ - offset: 1<br>
+ kind: 3<br>
+ target: bar<br>
+ - offset: 6<br>
+ kind: 3<br>
+ target: baz<br>
+<br>
+ - name: baz<br>
+ scope: static<br>
+ type: code<br>
+<br>
+ - name: bar<br>
+ definition: undefined<br>
+<br>
+<br>
+...<br>
+<br>
+# CHECK: name: foo<br>
+# CHECK: fixups:<br>
+# CHECK: target: bar<br>
+# CHECK: target: baz<br>
+# CHECK: ...<br>
+<br>
<br>
Added: lld/trunk/test/fixups-unnamed.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-unnamed.objtxt?rev=150539&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/fixups-unnamed.objtxt?rev=150539&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/fixups-unnamed.objtxt (added)<br>
+++ lld/trunk/test/fixups-unnamed.objtxt Tue Feb 14 18:38:09 2012<br>
@@ -0,0 +1,40 @@<br>
+# RUN: lld-core %s | FileCheck %s<br>
+<br>
+#<br>
+# Test fixups to unnamed atoms<br>
+#<br>
+<br>
+---<br>
+atoms:<br>
+ - name: foo<br>
+ type: code<br>
+ content: [ 48, 8D, 3D, 00, 00, 00, 00,<br>
+ 48, 8D, 3D, 00, 00, 00, 00 ]<br>
+ fixups:<br>
+ - offset: 3<br>
+ kind: 3<br>
+ target: LC1<br>
+ - offset: 10<br>
+ kind: 3<br>
+ target: LC2<br>
+<br>
+<br>
+ - ref-name: LC1<br>
+ scope: hidden<br>
+ type: c-string<br>
+ content: [ 68, 65, 6c, 6c, 6f, 00 ]<br>
+<br>
+ - ref-name: LC2<br>
+ scope: hidden<br>
+ type: c-string<br>
+ content: [ 74, 68, 65, 72, 65, 00 ]<br>
+<br>
+<br>
+...<br>
+<br>
+# CHECK: name: foo<br>
+# CHECK: fixups:<br>
+# CHECK: offset: 3<br>
+# CHECK: offset: 10<br>
+# CHECK: ref-name:<br>
+# CHECK: ref-name:<br>
<br>
Removed: lld/trunk/test/internal-name-attributes.objtxt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/internal-name-attributes.objtxt?rev=150538&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/internal-name-attributes.objtxt?rev=150538&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/internal-name-attributes.objtxt (original)<br>
+++ lld/trunk/test/internal-name-attributes.objtxt (removed)<br>
@@ -1,27 +0,0 @@<br>
-# RUN: lld-core %s | FileCheck %s<br>
-<br>
-#<br>
-# Test that internal-name attributes are preserved<br>
-#<br>
-<br>
----<br>
-atoms:<br>
- - name: foo<br>
- internal-name: false<br>
- - name: L0<br>
- internal-name: true<br>
- - name: L1<br>
- internal-name: true<br>
- - name: bar<br>
-...<br>
-<br>
-<br>
-# CHECK: name: foo<br>
-# CHECK-NOT: internal-name: false<br>
-# CHECK: name: L0<br>
-# CHECK: internal-name: true<br>
-# CHECK: name: L1<br>
-# CHECK: internal-name: true<br>
-# CHECK: name: bar<br>
-# CHECK-NOT: internal-name: false<br>
-# CHECK: ...<br>
<br>
Modified: lld/trunk/tools/lld-core/lld-core.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=150539&r1=150538&r2=150539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld-core/lld-core.cpp?rev=150539&r1=150538&r2=150539&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/tools/lld-core/lld-core.cpp (original)<br>
+++ lld/trunk/tools/lld-core/lld-core.cpp Tue Feb 14 18:38:09 2012<br>
@@ -234,8 +234,9 @@<br>
<br>
// read native file<br>
llvm::OwningPtr<lld::File> natFile;<br>
- parseNativeObjectFileOrSTDIN(tempPath, natFile);<br>
-<br>
+ if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) )<br>
+ return 1;<br>
+<br>
// write new atom graph out as YAML doc<br>
yaml::writeObjectText(*natFile, out);<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>