summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2012-02-07 02:59:54 +0000
committerNick Kledzik <kledzik@apple.com>2012-02-07 02:59:54 +0000
commit23384e84afd9e7a53cf2c802829f505cef2754c2 (patch)
tree363052290c18a83f3bb54871e9533d7f21aaeb14 /lld/lib
parente55c556a247a9c0decb4e256d9e897dfc9cf841d (diff)
downloadbcm5719-llvm-23384e84afd9e7a53cf2c802829f505cef2754c2.tar.gz
bcm5719-llvm-23384e84afd9e7a53cf2c802829f505cef2754c2.zip
Add support for UndefinedAtom in yaml and native format. Add test cases with undefined atoms
llvm-svn: 149962
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/NativeFileFormat.h15
-rw-r--r--lld/lib/Core/NativeReader.cpp115
-rw-r--r--lld/lib/Core/NativeWriter.cpp105
-rw-r--r--lld/lib/Core/Resolver.cpp2
-rw-r--r--lld/lib/Core/YamlKeyValues.cpp183
-rw-r--r--lld/lib/Core/YamlKeyValues.h5
-rw-r--r--lld/lib/Core/YamlReader.cpp43
-rw-r--r--lld/lib/Core/YamlWriter.cpp37
8 files changed, 362 insertions, 143 deletions
diff --git a/lld/lib/Core/NativeFileFormat.h b/lld/lib/Core/NativeFileFormat.h
index 4e4bfb4e1f9..9fb6d5fe62c 100644
--- a/lld/lib/Core/NativeFileFormat.h
+++ b/lld/lib/Core/NativeFileFormat.h
@@ -88,9 +88,10 @@ struct NativeFileHeader {
enum NativeChunkSignatures {
NCS_DefinedAtomsV1 = 1,
NCS_AttributesArrayV1 = 2,
- NCS_Content = 3,
+ NCS_UndefinedAtomsV1 = 3,
NCS_Strings = 4,
- NCS_ReferencesArray = 5,
+ NCS_Content = 5,
+ NCS_ReferencesArray = 6,
};
//
@@ -152,6 +153,16 @@ struct NativeAtomAttributesV1 {
+//
+// The NCS_UndefinedAtomsV1 chunk contains an array of these structs
+//
+struct NativeUndefinedAtomIvarsV1 {
+ uint32_t nameOffset;
+ uint32_t flags;
+};
+
+
+
diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/Core/NativeReader.cpp
index 845d6bf45ac..033cf9890f6 100644
--- a/lld/lib/Core/NativeReader.cpp
+++ b/lld/lib/Core/NativeReader.cpp
@@ -65,7 +65,8 @@ public:
}
virtual DefinedAtom::ContentType contentType() const {
- return (DefinedAtom::ContentType)(attributes().contentType);
+ const NativeAtomAttributesV1& attr = attributes();
+ return (DefinedAtom::ContentType)(attr.contentType);
}
virtual DefinedAtom::Alignment alignment() const {
@@ -113,6 +114,29 @@ private:
+//
+// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
+// struct in the NCS_UndefinedAtomsV1 chunk.
+//
+class NativeUndefinedAtomV1 : public UndefinedAtom {
+public:
+ NativeUndefinedAtomV1(const NativeFile& f,
+ const NativeUndefinedAtomIvarsV1* ivarData)
+ : _file(&f), _ivarData(ivarData) { }
+
+ virtual const File& file() const;
+ virtual llvm::StringRef name() const;
+
+ virtual bool weakImport() const {
+ return (_ivarData->flags & 0x1);
+ }
+
+private:
+ const NativeFile* _file;
+ const NativeUndefinedAtomIvarsV1* _ivarData;
+};
+
+
//
// lld::File object for native llvm object file
@@ -122,8 +146,9 @@ public:
/// Instantiates a File object from a native object file. Ownership
/// of the MemoryBuffer is transfered to the resulting File object.
- static llvm::error_code make(llvm::MemoryBuffer* mb, llvm::StringRef path,
- File*& result) {
+ static llvm::error_code make(llvm::OwningPtr<llvm::MemoryBuffer>& mb,
+ llvm::StringRef path,
+ llvm::OwningPtr<File>& result) {
const uint8_t* const base =
reinterpret_cast<const uint8_t*>(mb->getBufferStart());
const NativeFileHeader* const header =
@@ -159,6 +184,9 @@ public:
case NCS_AttributesArrayV1:
ec = file->processAttributesV1(base, chunk);
break;
+ case NCS_UndefinedAtomsV1:
+ ec = file->processUndefinedAtomsV1(base, chunk);
+ break;
case NCS_Content:
ec = file->processContent(base, chunk);
break;
@@ -175,7 +203,7 @@ public:
// TO DO: validate enough chunks were used
- result = file;
+ result.reset(file);
}
@@ -183,13 +211,14 @@ public:
}
virtual ~NativeFile() {
- // The NativeFile owns the MemoryBuffer and must not delete it.
- delete _buffer;
+ // _buffer is automatically deleted because of OwningPtr<>
+
// All other ivar pointers are pointers into the MemoryBuffer, except
// the _definedAtoms array which was allocated to contain an array
// of Atom objects. The atoms have empty destructors, so it is ok
// to just delete the memory.
delete _definedAtoms.arrayStart;
+ delete _undefinedAtoms.arrayStart;
}
// visits each atom in the file
@@ -199,6 +228,11 @@ public:
const DefinedAtom* atom = reinterpret_cast<const DefinedAtom*>(p);
handler.doDefinedAtom(*atom);
}
+ for(const uint8_t* p=_undefinedAtoms.arrayStart; p != _undefinedAtoms.arrayEnd;
+ p += _undefinedAtoms.elementSize) {
+ const UndefinedAtom* atom = reinterpret_cast<const UndefinedAtom*>(p);
+ handler.doUndefinedAtom(*atom);
+ }
return (_definedAtoms.arrayStart != _definedAtoms.arrayEnd);
}
@@ -210,6 +244,7 @@ public:
private:
friend class NativeDefinedAtomV1;
+ friend class NativeUndefinedAtomV1;
// instantiate array of DefinedAtoms from v1 ivar data in file
llvm::error_code processDefinedAtomsV1(const uint8_t* base,
@@ -247,6 +282,34 @@ private:
return make_error_code(native_reader_error::success);
}
+ llvm::error_code processUndefinedAtomsV1(const uint8_t* base,
+ const NativeChunk* chunk) {
+ const size_t atomSize = sizeof(NativeUndefinedAtomV1);
+ size_t atomsArraySize = chunk->elementCount * atomSize;
+ uint8_t* atomsStart = reinterpret_cast<uint8_t*>
+ (operator new(atomsArraySize, std::nothrow));
+ if (atomsStart == NULL )
+ return make_error_code(native_reader_error::memory_error);
+ const size_t ivarElementSize = chunk->fileSize
+ / chunk->elementCount;
+ if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
+ return make_error_code(native_reader_error::file_malformed);
+ uint8_t* atomsEnd = atomsStart + atomsArraySize;
+ const NativeUndefinedAtomIvarsV1* ivarData =
+ reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
+ (base + chunk->fileOffset);
+ for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
+ NativeUndefinedAtomV1* atomAllocSpace =
+ reinterpret_cast<NativeUndefinedAtomV1*>(s);
+ new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
+ ++ivarData;
+ }
+ this->_undefinedAtoms.arrayStart = atomsStart;
+ this->_undefinedAtoms.arrayEnd = atomsEnd;
+ this->_undefinedAtoms.elementSize = atomSize;
+ return make_error_code(native_reader_error::success);
+ }
+
// set up pointers to string pool in file
llvm::error_code processStrings(const uint8_t* base,
const NativeChunk* chunk) {
@@ -281,12 +344,18 @@ private:
// private constructor, only called by make()
- NativeFile(llvm::MemoryBuffer* mb, llvm::StringRef path) :
- lld::File(path), _buffer(mb), _header(NULL),
- _strings(NULL), _stringsMaxOffset(0),
- _contentStart(NULL), _contentEnd(NULL)
+ NativeFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb, llvm::StringRef path) :
+ lld::File(path),
+ _buffer(mb.take()), // NativeFile now takes ownership of buffer
+ _header(NULL),
+ _strings(NULL),
+ _stringsMaxOffset(0),
+ _contentStart(NULL),
+ _contentEnd(NULL)
{
- _header = reinterpret_cast<const NativeFileHeader*>(mb->getBufferStart());
+ _header = reinterpret_cast<const NativeFileHeader*>(_buffer->getBufferStart());
+ _definedAtoms.arrayStart = NULL;
+ _undefinedAtoms.arrayStart = NULL;
}
struct AtomArray {
@@ -297,9 +366,10 @@ private:
uint32_t elementSize;
};
- llvm::MemoryBuffer* _buffer;
+ llvm::OwningPtr<llvm::MemoryBuffer> _buffer;
const NativeFileHeader* _header;
AtomArray _definedAtoms;
+ AtomArray _undefinedAtoms;
const uint8_t* _attributes;
uint32_t _attributesMaxOffset;
const char* _strings;
@@ -342,11 +412,24 @@ inline llvm::StringRef NativeDefinedAtomV1::customSectionName() const {
+
+inline const class File& NativeUndefinedAtomV1::file() const {
+ return *_file;
+}
+
+inline llvm::StringRef NativeUndefinedAtomV1::name() const {
+ return _file->string(_ivarData->nameOffset);
+}
+
+
+
+
//
// Instantiate an lld::File from the given native object file buffer
//
-llvm::error_code parseNativeObjectFile(llvm::MemoryBuffer* mb,
- llvm::StringRef path, File*& result) {
+llvm::error_code parseNativeObjectFile(llvm::OwningPtr<llvm::MemoryBuffer>& mb,
+ llvm::StringRef path,
+ llvm::OwningPtr<File>& result) {
return NativeFile::make(mb, path, result);
}
@@ -356,13 +439,13 @@ llvm::error_code parseNativeObjectFile(llvm::MemoryBuffer* mb,
// Instantiate an lld::File from the given native object file path
//
llvm::error_code parseNativeObjectFileOrSTDIN(llvm::StringRef path,
- File*& result) {
+ llvm::OwningPtr<File>& result) {
llvm::OwningPtr<llvm::MemoryBuffer> mb;
llvm::error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
if ( ec )
return ec;
- return parseNativeObjectFile(mb.take(), path, result);
+ return parseNativeObjectFile(mb, path, result);
}
diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/Core/NativeWriter.cpp
index e9533be636c..09fdd9cdd17 100644
--- a/lld/lib/Core/NativeWriter.cpp
+++ b/lld/lib/Core/NativeWriter.cpp
@@ -44,10 +44,13 @@ public:
if (!_attributes.empty())
out.write((char*)&_attributes[0],
_attributes.size()*sizeof(NativeAtomAttributesV1));
- if (!_contentPool.empty())
- out.write((char*)&_contentPool[0], _contentPool.size());
+ if ( !_undefinedAtomIvars.empty() )
+ out.write((char*)&_undefinedAtomIvars[0],
+ _undefinedAtomIvars.size()*sizeof(NativeUndefinedAtomIvarsV1));
if (!_stringPool.empty())
out.write(&_stringPool[0], _stringPool.size());
+ if (!_contentPool.empty())
+ out.write((char*)&_contentPool[0], _contentPool.size());
}
private:
@@ -64,15 +67,22 @@ private:
// visitor routine called by forEachAtom()
virtual void doUndefinedAtom(const class UndefinedAtom& atom) {
+ NativeUndefinedAtomIvarsV1 ivar;
+ ivar.nameOffset = getNameOffset(atom);
+ ivar.flags = (atom.weakImport() ? 1 : 0);
+ _undefinedAtomIvars.push_back(ivar);
}
// visitor routine called by forEachAtom()
virtual void doFile(const class File &) {
}
-
+
// fill out native file header and chunk directory
void makeHeader() {
- _headerBufferSize = sizeof(NativeFileHeader) + 4*sizeof(NativeChunk);
+ const bool hasUndefines = !_undefinedAtomIvars.empty();
+ const int chunkCount = hasUndefines ? 5 : 4;
+ _headerBufferSize = sizeof(NativeFileHeader)
+ + chunkCount*sizeof(NativeChunk);
_headerBuffer = reinterpret_cast<NativeFileHeader*>
(operator new(_headerBufferSize, std::nothrow));
NativeChunk *chunks =
@@ -82,39 +92,59 @@ private:
_headerBuffer->endian = NFH_LittleEndian;
_headerBuffer->architecture = 0;
_headerBuffer->fileSize = 0;
- _headerBuffer->chunkCount = 4;
+ _headerBuffer->chunkCount = chunkCount;
+
// create chunk for atom ivar array
- NativeChunk& ch0 = chunks[0];
- ch0.signature = NCS_DefinedAtomsV1;
- ch0.fileOffset = _headerBufferSize;
- ch0.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
- ch0.elementCount = _definedAtomIvars.size();
- // create chunk for attributes
- NativeChunk& ch1 = chunks[1];
- ch1.signature = NCS_AttributesArrayV1;
- ch1.fileOffset = ch0.fileOffset + ch0.fileSize;
- ch1.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
- ch1.elementCount = _attributes.size();
- // create chunk for content
- NativeChunk& ch2 = chunks[2];
- ch2.signature = NCS_Content;
- ch2.fileOffset = ch1.fileOffset + ch1.fileSize;
- ch2.fileSize = _contentPool.size();
- ch2.elementCount = _contentPool.size();
+ int nextIndex = 0;
+ NativeChunk& chd = chunks[nextIndex++];
+ chd.signature = NCS_DefinedAtomsV1;
+ chd.fileOffset = _headerBufferSize;
+ chd.fileSize = _definedAtomIvars.size()*sizeof(NativeDefinedAtomIvarsV1);
+ chd.elementCount = _definedAtomIvars.size();
+ uint32_t nextFileOffset = chd.fileOffset + chd.fileSize;
+
+ // create chunk for attributes
+ NativeChunk& cha = chunks[nextIndex++];
+ cha.signature = NCS_AttributesArrayV1;
+ cha.fileOffset = nextFileOffset;
+ cha.fileSize = _attributes.size()*sizeof(NativeAtomAttributesV1);
+ cha.elementCount = _attributes.size();
+ nextFileOffset = cha.fileOffset + cha.fileSize;
+
+ // create chunk for undefined atom array
+ if ( hasUndefines ) {
+ NativeChunk& chu = chunks[nextIndex++];
+ chu.signature = NCS_UndefinedAtomsV1;
+ chu.fileOffset = nextFileOffset;
+ chu.fileSize = _undefinedAtomIvars.size() *
+ sizeof(NativeUndefinedAtomIvarsV1);
+ chu.elementCount = _undefinedAtomIvars.size();
+ nextFileOffset = chu.fileOffset + chu.fileSize;
+ }
+
// create chunk for symbol strings
- NativeChunk& ch3 = chunks[3];
- ch3.signature = NCS_Strings;
- ch3.fileOffset = ch2.fileOffset + ch2.fileSize;
- ch3.fileSize = _stringPool.size();
- ch3.elementCount = _stringPool.size();
+ NativeChunk& chs = chunks[nextIndex++];
+ chs.signature = NCS_Strings;
+ chs.fileOffset = nextFileOffset;
+ chs.fileSize = _stringPool.size();
+ chs.elementCount = _stringPool.size();
+ nextFileOffset = chs.fileOffset + chs.fileSize;
- _headerBuffer->fileSize = ch3.fileOffset + ch3.fileSize;
+ // create chunk for content
+ NativeChunk& chc = chunks[nextIndex++];
+ chc.signature = NCS_Content;
+ chc.fileOffset = nextFileOffset;
+ chc.fileSize = _contentPool.size();
+ chc.elementCount = _contentPool.size();
+ nextFileOffset = chc.fileOffset + chc.fileSize;
+
+ _headerBuffer->fileSize = nextFileOffset;
}
// append atom name to string pool and return offset
- uint32_t getNameOffset(const class DefinedAtom& atom) {
+ uint32_t getNameOffset(const Atom& atom) {
return this->getNameOffset(atom.name());
}
@@ -190,14 +220,15 @@ private:
typedef std::vector<std::pair<llvm::StringRef, uint32_t> > NameToOffsetVector;
- const lld::File& _file;
- NativeFileHeader* _headerBuffer;
- size_t _headerBufferSize;
- std::vector<char> _stringPool;
- std::vector<uint8_t> _contentPool;
- std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
- std::vector<NativeAtomAttributesV1> _attributes;
- NameToOffsetVector _sectionNames;
+ const lld::File& _file;
+ NativeFileHeader* _headerBuffer;
+ size_t _headerBufferSize;
+ std::vector<char> _stringPool;
+ std::vector<uint8_t> _contentPool;
+ std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
+ std::vector<NativeAtomAttributesV1> _attributes;
+ std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
+ NameToOffsetVector _sectionNames;
};
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index 51f6a481a65..cebf3f7d10c 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -33,7 +33,7 @@ public:
// don't remove if live
if ( _liveAtoms.count(atom) )
return false;
- // don't remove if marked never-dead-strip
+ // don't remove if marked never-dead-strip
if ( const DefinedAtom* defAtom = atom->definedAtom() ) {
if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
return false;
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp
index 4158e6d4e51..9401aae949a 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/Core/YamlKeyValues.cpp
@@ -31,7 +31,8 @@ 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 char* const KeyValues::permissionsKeyword = "permissions";
+const char* const KeyValues::weakImportKeyword = "weak-import";
const DefinedAtom::Definition KeyValues::definitionDefault = Atom::definitionRegular;
@@ -45,27 +46,28 @@ const DefinedAtom::ContentPermissions KeyValues::permissionsDefault = DefinedAto
const bool KeyValues::internalNameDefault = false;
const bool KeyValues::isThumbDefault = false;
const bool KeyValues::isAliasDefault = false;
+const bool KeyValues::weakImportDefault = false;
struct DefinitionMapping {
- const char* string;
- Atom::Definition value;
+ const char* string;
+ Atom::Definition value;
};
static const DefinitionMapping defMappings[] = {
- { "regular", Atom::definitionRegular },
- { "absolute", Atom::definitionAbsolute },
- { "undefined", Atom::definitionUndefined },
- { "shared-library", Atom::definitionSharedLibrary },
+ { "regular", Atom::definitionRegular },
+ { "absolute", Atom::definitionAbsolute },
+ { "undefined", Atom::definitionUndefined },
+ { "shared-library", Atom::definitionSharedLibrary },
{ NULL, Atom::definitionRegular }
};
Atom::Definition KeyValues::definition(const char* s)
{
- for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) {
+ for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -73,7 +75,7 @@ Atom::Definition KeyValues::definition(const char* s)
}
const char* KeyValues::definition(Atom::Definition s) {
- for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) {
+ for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) {
if ( p->value == s )
return p->string;
}
@@ -85,20 +87,20 @@ const char* KeyValues::definition(Atom::Definition s) {
struct ScopeMapping {
- const char* string;
- DefinedAtom::Scope value;
+ const char* string;
+ DefinedAtom::Scope value;
};
static const ScopeMapping scopeMappings[] = {
- { "global", DefinedAtom::scopeGlobal },
- { "hidden", DefinedAtom::scopeLinkageUnit },
- { "static", DefinedAtom::scopeTranslationUnit },
+ { "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) {
+ for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -106,7 +108,7 @@ DefinedAtom::Scope KeyValues::scope(const char* s)
}
const char* KeyValues::scope(DefinedAtom::Scope s) {
- for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
+ for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) {
if ( p->value == s )
return p->string;
}
@@ -121,41 +123,41 @@ const char* KeyValues::scope(DefinedAtom::Scope s) {
struct ContentTypeMapping {
- const char* string;
- DefinedAtom::ContentType value;
+ const char* string;
+ DefinedAtom::ContentType value;
};
static const ContentTypeMapping typeMappings[] = {
- { "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 },
+ { "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 }
};
DefinedAtom::ContentType KeyValues::contentType(const char* s)
{
- for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
+ for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -163,7 +165,7 @@ DefinedAtom::ContentType KeyValues::contentType(const char* s)
}
const char* KeyValues::contentType(DefinedAtom::ContentType s) {
- for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
+ for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) {
if ( p->value == s )
return p->string;
}
@@ -177,20 +179,20 @@ const char* KeyValues::contentType(DefinedAtom::ContentType s) {
struct DeadStripMapping {
- const char* string;
- DefinedAtom::DeadStripKind value;
+ const char* string;
+ DefinedAtom::DeadStripKind value;
};
static const DeadStripMapping deadStripMappings[] = {
- { "normal", DefinedAtom::deadStripNormal },
- { "never", DefinedAtom::deadStripNever },
- { "always", DefinedAtom::deadStripAlways },
+ { "normal", DefinedAtom::deadStripNormal },
+ { "never", DefinedAtom::deadStripNever },
+ { "always", DefinedAtom::deadStripAlways },
{ NULL, DefinedAtom::deadStripNormal }
};
DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s)
{
- for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
+ for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -198,7 +200,7 @@ DefinedAtom::DeadStripKind KeyValues::deadStripKind(const char* s)
}
const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
- for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
+ for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) {
if ( p->value == dsk )
return p->string;
}
@@ -210,20 +212,20 @@ const char* KeyValues::deadStripKind(DefinedAtom::DeadStripKind dsk) {
struct InterposableMapping {
- const char* string;
- DefinedAtom::Interposable value;
+ const char* string;
+ DefinedAtom::Interposable value;
};
static const InterposableMapping interMappings[] = {
- { "no", DefinedAtom::interposeNo },
- { "yes", DefinedAtom::interposeYes },
- { "yesAndWeak", DefinedAtom::interposeYesAndRuntimeWeak },
+ { "no", DefinedAtom::interposeNo },
+ { "yes", DefinedAtom::interposeYes },
+ { "yesAndWeak", DefinedAtom::interposeYesAndRuntimeWeak },
{ NULL, DefinedAtom::interposeNo }
};
DefinedAtom::Interposable KeyValues::interposable(const char* s)
{
- for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
+ for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -231,7 +233,7 @@ DefinedAtom::Interposable KeyValues::interposable(const char* s)
}
const char* KeyValues::interposable(DefinedAtom::Interposable in) {
- for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
+ for (const InterposableMapping* p = interMappings; p->string != NULL; ++p) {
if ( p->value == in )
return p->string;
}
@@ -244,21 +246,21 @@ const char* KeyValues::interposable(DefinedAtom::Interposable in) {
struct MergeMapping {
- const char* string;
- DefinedAtom::Merge value;
+ const char* string;
+ DefinedAtom::Merge value;
};
static const MergeMapping mergeMappings[] = {
- { "no", DefinedAtom::mergeNo },
- { "asTentative", DefinedAtom::mergeAsTentative },
- { "asWeak", DefinedAtom::mergeAsWeak },
- { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed },
+ { "no", DefinedAtom::mergeNo },
+ { "asTentative", DefinedAtom::mergeAsTentative },
+ { "asWeak", DefinedAtom::mergeAsWeak },
+ { "asAddressedWeak",DefinedAtom::mergeAsWeakAndAddressUsed },
{ NULL, DefinedAtom::mergeNo }
};
DefinedAtom::Merge KeyValues::merge(const char* s)
{
- for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
+ for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -266,7 +268,7 @@ DefinedAtom::Merge KeyValues::merge(const char* s)
}
const char* KeyValues::merge(DefinedAtom::Merge in) {
- for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
+ for (const MergeMapping* p = mergeMappings; p->string != NULL; ++p) {
if ( p->value == in )
return p->string;
}
@@ -279,20 +281,20 @@ const char* KeyValues::merge(DefinedAtom::Merge in) {
struct SectionChoiceMapping {
- const char* string;
- DefinedAtom::SectionChoice value;
+ const char* string;
+ DefinedAtom::SectionChoice value;
};
static const SectionChoiceMapping sectMappings[] = {
- { "content", DefinedAtom::sectionBasedOnContent },
- { "custom", DefinedAtom::sectionCustomPreferred },
- { "custom-required", DefinedAtom::sectionCustomRequired },
+ { "content", DefinedAtom::sectionBasedOnContent },
+ { "custom", DefinedAtom::sectionCustomPreferred },
+ { "custom-required", DefinedAtom::sectionCustomRequired },
{ NULL, DefinedAtom::sectionBasedOnContent }
};
DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s)
{
- for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
+ for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -300,7 +302,7 @@ DefinedAtom::SectionChoice KeyValues::sectionChoice(const char* s)
}
const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
- for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
+ for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) {
if ( p->value == s )
return p->string;
}
@@ -314,22 +316,22 @@ const char* KeyValues::sectionChoice(DefinedAtom::SectionChoice s) {
struct PermissionsMapping {
- const char* string;
- DefinedAtom::ContentPermissions value;
+ 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 },
+ { "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) {
+ for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) {
if ( strcmp(p->string, s) == 0 )
return p->value;
}
@@ -337,7 +339,7 @@ DefinedAtom::ContentPermissions KeyValues::permissions(const char* s)
}
const char* KeyValues::permissions(DefinedAtom::ContentPermissions s) {
- for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) {
+ for (const PermissionsMapping* p = permMappings; p->string != NULL; ++p) {
if ( p->value == s )
return p->string;
}
@@ -398,6 +400,23 @@ const char* KeyValues::isAlias(bool b) {
+bool KeyValues::weakImport(const char* s)
+{
+ if ( strcmp(s, "true") == 0 )
+ return true;
+ else if ( strcmp(s, "false") == 0 )
+ return false;
+ llvm::report_fatal_error("bad weak-import value");
+}
+
+const char* KeyValues::weakImport(bool b) {
+ return b ? "true" : "false";
+}
+
+
+
+
+
} // namespace yaml
diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h
index b38a26cfaf3..2a15ed25639 100644
--- a/lld/lib/Core/YamlKeyValues.h
+++ b/lld/lib/Core/YamlKeyValues.h
@@ -79,6 +79,11 @@ public:
static bool isAlias(const char*);
static const char* isAlias(bool);
+ static const char* const weakImportKeyword;
+ static const bool weakImportDefault;
+ static bool weakImport(const char*);
+ static const char* weakImport(bool);
+
};
} // namespace yaml
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp
index 39c06432f39..37c6382fc52 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/Core/YamlReader.cpp
@@ -267,6 +267,10 @@ bool YAMLFile::forEachAtom(File::AtomHandler &handler) const {
it != _definedAtoms.end(); ++it) {
handler.doDefinedAtom(**it);
}
+ for (std::vector<UndefinedAtom *>::const_iterator it = _undefinedAtoms.begin();
+ it != _undefinedAtoms.end(); ++it) {
+ handler.doUndefinedAtom(**it);
+ }
return true;
}
@@ -424,6 +428,32 @@ private:
};
+class YAMLUndefinedAtom : public UndefinedAtom {
+public:
+ YAMLUndefinedAtom(YAMLFile& f, int32_t ord, const char* nm, bool wi)
+ : _file(f), _name(nm), _ordinal(ord), _weakImport(wi) { }
+
+ virtual const class File& file() const {
+ return _file;
+ }
+
+ virtual llvm::StringRef name() const {
+ return _name;
+ }
+
+ virtual bool weakImport() const {
+ return _weakImport;
+ }
+
+private:
+ YAMLFile& _file;
+ const char * _name;
+ uint32_t _ordinal;
+ bool _weakImport;
+};
+
+
+
class YAMLAtomState {
public:
YAMLAtomState();
@@ -455,6 +485,7 @@ public:
bool _internalName;
bool _isThumb;
bool _isAlias;
+ bool _weakImport;
Reference _ref;
};
@@ -477,6 +508,7 @@ YAMLAtomState::YAMLAtomState()
, _internalName(KeyValues::internalNameDefault)
, _isThumb(KeyValues::isThumbDefault)
, _isAlias(KeyValues::isAliasDefault)
+ , _weakImport(false)
{
_ref.target = NULL;
_ref.addend = 0;
@@ -496,6 +528,12 @@ void YAMLAtomState::makeAtom(YAMLFile& f) {
f._definedAtoms.push_back(a);
++_ordinal;
}
+ else if ( _definition == Atom::definitionUndefined ) {
+ UndefinedAtom *a = new YAMLUndefinedAtom(f, _ordinal, _name, _weakImport);
+
+ f._undefinedAtoms.push_back(a);
+ ++_ordinal;
+ }
// reset state for next atom
_name = NULL;
@@ -515,6 +553,7 @@ void YAMLAtomState::makeAtom(YAMLFile& f) {
_permissions = KeyValues::permissionsDefault;
_isThumb = KeyValues::isThumbDefault;
_isAlias = KeyValues::isAliasDefault;
+ _weakImport = KeyValues::weakImportDefault;
_ref.target = NULL;
_ref.addend = 0;
_ref.offsetInAtom = 0;
@@ -664,6 +703,10 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb
atomState._isAlias = KeyValues::isAlias(entry->value);
haveAtom = true;
}
+ else if (strcmp(entry->key, KeyValues::weakImportKeyword) == 0) {
+ atomState._weakImport = KeyValues::weakImport(entry->value);
+ haveAtom = true;
+ }
else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) {
atomState._sectionName = entry->value;
haveAtom = true;
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp
index e5f0b1c44c3..db46b5a12d7 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/Core/YamlWriter.cpp
@@ -81,7 +81,7 @@ public:
<< "\n";
}
- if ( atom.merge() != KeyValues::mergeDefault ) {
+ if ( atom.merge() != KeyValues::mergeDefault ) {
_out << " "
<< KeyValues::mergeKeyword
<< ":"
@@ -124,7 +124,7 @@ public:
<< "\n";
}
- if ( atom.isThumb() != KeyValues::isThumbDefault ) {
+ if ( atom.isThumb() != KeyValues::isThumbDefault ) {
_out << " "
<< KeyValues::isThumbKeyword
<< ":"
@@ -142,7 +142,8 @@ public:
<< "\n";
}
- if ( atom.contentType() != DefinedAtom::typeZeroFill ) {
+ if ( (atom.contentType() != DefinedAtom::typeZeroFill)
+ && (atom.size() != 0) ) {
_out << " "
<< KeyValues::contentKeyword
<< ":"
@@ -171,9 +172,35 @@ public:
}
- virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
+ virtual void doUndefinedAtom(const class UndefinedAtom &atom) {
+ // add blank line between atoms for readability
+ if ( !_firstAtom )
+ _out << "\n";
+ _firstAtom = false;
+
+ _out << " - "
+ << KeyValues::nameKeyword
+ << ":"
+ << spacePadding(KeyValues::nameKeyword)
+ << atom.name()
+ << "\n";
- }
+ _out << " "
+ << KeyValues::definitionKeyword
+ << ":"
+ << spacePadding(KeyValues::definitionKeyword)
+ << KeyValues::definition(atom.definition())
+ << "\n";
+
+ if ( atom.weakImport() != KeyValues::weakImportDefault ) {
+ _out << " "
+ << KeyValues::weakImportKeyword
+ << ":"
+ << spacePadding(KeyValues::weakImportKeyword)
+ << KeyValues::weakImport(atom.weakImport())
+ << "\n";
+ }
+ }
private:
OpenPOWER on IntegriCloud