From: Nick Kledzik Date: Wed, 4 Jan 2012 23:58:17 +0000 (+0000) Subject: Support more Atom attributes. Add more test cases to lld-core X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7735a7d1a07607a2c6176225b6dcaf338dd6b7f7;p=platform%2Fupstream%2Fllvm.git Support more Atom attributes. Add more test cases to lld-core llvm-svn: 147571 --- diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h index 2ca38ad..b413cdd 100644 --- a/lld/include/lld/Core/Atom.h +++ b/lld/include/lld/Core/Atom.h @@ -336,7 +336,8 @@ public: , ContentType ct , SectionChoice sc , bool internalName - , bool md + , bool mergeDupes + , bool autoHide , DeadStripKind ds , bool IsThumb , bool IsAlias @@ -344,16 +345,18 @@ public: : _address(ord) , _alignmentModulus(a.modulus) , _alignmentPowerOf2(a.powerOf2) + , _contentType(ct) , _definition(d) + , _scope(s) + , _sectionChoice(sc) , _internalName(internalName) , _deadStrip(ds) , _mode(modeOrdinal) - , _mergeDuplicates(md) + , _mergeDuplicates(mergeDupes) , _thumb(IsThumb) + , _autoHide(autoHide) , _alias(IsAlias) - , _contentType(ct) - , _scope(s) - , _sectionChoice(sc) {} + {} protected: diff --git a/lld/include/lld/Core/Reference.h b/lld/include/lld/Core/Reference.h index 23bf233..36588d1 100644 --- a/lld/include/lld/Core/Reference.h +++ b/lld/include/lld/Core/Reference.h @@ -10,7 +10,8 @@ #ifndef LLD_CORE_REFERENCES_H_ #define LLD_CORE_REFERENCES_H_ -#include "llvm/Support/DataTypes.h" +#include + namespace lld { diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h index 4792275..8924d76 100644 --- a/lld/include/lld/Core/UndefinedAtom.h +++ b/lld/include/lld/Core/UndefinedAtom.h @@ -28,6 +28,7 @@ public: , Atom::sectionBasedOnContent , false , false + , false , deadStripNormal , false , false diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt index 66de63d..aa08637 100644 --- a/lld/lib/Core/CMakeLists.txt +++ b/lld/lib/Core/CMakeLists.txt @@ -3,6 +3,7 @@ add_lld_library(lldCore File.cpp Resolver.cpp SymbolTable.cpp + YamlKeyValues.cpp YamlReader.cpp YamlWriter.cpp ) diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index 223f15e..b88ff0a 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -84,41 +84,49 @@ void SymbolTable::addByName(const Atom & newAtom) { llvm::StringRef name = newAtom.name(); const Atom *existing = this->findByName(name); if (existing == NULL) { - // name is not in symbol table yet, add it associate with this atom + // Name is not in symbol table yet, add it associate with this atom. _nameTable[name] = &newAtom; - } else { - // name is already in symbol table and associated with another atom + } + else { + // Name is already in symbol table and associated with another atom. + bool useNew = true; switch (collide(existing->definition(), newAtom.definition())) { case NCR_First: - // using first, just add new to _replacedAtoms - _replacedAtoms[&newAtom] = existing; + useNew = false; break; case NCR_Second: - // using second, update tables - _nameTable[name] = &newAtom; - _replacedAtoms[existing] = &newAtom; + useNew = true; break; case NCR_Dup: if ( existing->mergeDuplicates() && newAtom.mergeDuplicates() ) { - // using existing atom, add new atom to _replacedAtoms - _replacedAtoms[&newAtom] = existing; - } - else { - const Atom& use = _platform.handleMultipleDefinitions(*existing, newAtom); - if ( &use == existing ) { - // using existing atom, add new atom to _replacedAtoms - _replacedAtoms[&newAtom] = existing; + // Both mergeable. Use auto-hide bit as tie breaker + if ( existing->autoHide() != newAtom.autoHide() ) { + // They have different autoHide values, keep non-autohide one + useNew = existing->autoHide(); } else { - // using new atom, update tables - _nameTable[name] = &newAtom; - _replacedAtoms[existing] = &newAtom; + // They have same autoHide, so just keep using existing + useNew = false; } } + else { + const Atom& use = _platform.handleMultipleDefinitions(*existing, newAtom); + useNew = ( &use != existing ); + } break; default: llvm::report_fatal_error("SymbolTable::addByName(): unhandled switch clause"); } + if ( useNew ) { + // Update name table to use new atom. + _nameTable[name] = &newAtom; + // Add existing atom to replacement table. + _replacedAtoms[existing] = &newAtom; + } + else { + // New atom is not being used. Add it to replacement table. + _replacedAtoms[&newAtom] = existing; + } } } diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/Core/YamlKeyValues.cpp new file mode 100644 index 0000000..47729d6 --- /dev/null +++ b/lld/lib/Core/YamlKeyValues.cpp @@ -0,0 +1,330 @@ +//===- Core/YamlKeyValues.cpp - Reads YAML --------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "YamlKeyValues.h" + +#include "llvm/Support/ErrorHandling.h" + +namespace lld { +namespace yaml { + + +const char* const KeyValues::nameKeyword = "name"; +const char* const KeyValues::scopeKeyword = "scope"; +const char* const KeyValues::definitionKeyword = "definition"; +const char* const KeyValues::contentTypeKeyword = "type"; +const char* const KeyValues::deadStripKindKeyword = "dead-strip"; +const char* const KeyValues::sectionChoiceKeyword = "section-choice"; +const char* const KeyValues::internalNameKeyword = "internal-name"; +const char* const KeyValues::mergeDuplicatesKeyword = "merge-duplicates"; +const char* const KeyValues::autoHideKeyword = "auto-hide"; +const char* const KeyValues::isThumbKeyword = "is-thumb"; +const char* const KeyValues::isAliasKeyword = "is-alias"; +const char* const KeyValues::sectionNameKeyword = "section-name"; +const char* const KeyValues::contentKeyword = "content"; +const char* const KeyValues::sizeKeyword = "size"; + + +const Atom::Scope KeyValues::scopeDefault = Atom::scopeTranslationUnit; +const Atom::Definition KeyValues::definitionDefault = Atom::definitionRegular; +const Atom::ContentType KeyValues::contentTypeDefault = Atom::typeData; +const Atom::DeadStripKind KeyValues::deadStripKindDefault = Atom::deadStripNormal; +const Atom::SectionChoice KeyValues::sectionChoiceDefault = Atom::sectionBasedOnContent; +const bool KeyValues::internalNameDefault = false; +const bool KeyValues::mergeDuplicatesDefault = false; +const bool KeyValues::autoHideDefault = false; +const bool KeyValues::isThumbDefault = false; +const bool KeyValues::isAliasDefault = false; + + +struct ScopeMapping { + const char* string; + Atom::Scope value; +}; + +static const ScopeMapping scopeMappings[] = { + { "global", Atom::scopeGlobal }, + { "hidden", Atom::scopeLinkageUnit }, + { "static", Atom::scopeTranslationUnit }, + { NULL, Atom::scopeGlobal } +}; + +Atom::Scope KeyValues::scope(const char* s) +{ + for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad scope value"); +} + +const char* KeyValues::scope(Atom::Scope s) { + for (const ScopeMapping* p = scopeMappings; p->string != NULL; ++p) { + if ( p->value == s ) + return p->string; + } + llvm::report_fatal_error("bad scope value"); +} + + + + + +struct DefinitionMapping { + const char* string; + Atom::Definition value; +}; + +static const DefinitionMapping defMappings[] = { + { "regular", Atom::definitionRegular }, + { "weak", Atom::definitionWeak }, + { "tentative", Atom::definitionTentative }, + { "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) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad definition value"); +} + +const char* KeyValues::definition(Atom::Definition s) { + for (const DefinitionMapping* p = defMappings; p->string != NULL; ++p) { + if ( p->value == s ) + return p->string; + } + llvm::report_fatal_error("bad definition value"); +} + + + + + +struct ContentTypeMapping { + const char* string; + Atom::ContentType value; +}; + +static const ContentTypeMapping typeMappings[] = { + { "unknown", Atom::typeUnknown }, + { "code", Atom::typeCode }, + { "resolver", Atom::typeResolver }, + { "constant", Atom::typeConstant }, + { "c-string", Atom::typeCString }, + { "utf16-string", Atom::typeUTF16String }, + { "CFI", Atom::typeCFI }, + { "LSDA", Atom::typeLSDA }, + { "literal-4", Atom::typeLiteral4 }, + { "literal-8", Atom::typeLiteral8 }, + { "literal-16", Atom::typeLiteral16 }, + { "data", Atom::typeData }, + { "zero-fill", Atom::typeZeroFill }, + { "cf-string", Atom::typeCFString }, + { "initializer-ptr",Atom::typeInitializerPtr }, + { "terminator-ptr", Atom::typeTerminatorPtr }, + { "c-string-ptr", Atom::typeCStringPtr }, + { "objc1-class", Atom::typeObjC1Class }, + { "objc1-class-ptr",Atom::typeObjCClassPtr }, + { "objc2-cat-ptr", Atom::typeObjC2CategoryList }, + { "tlv-thunk", Atom::typeThunkTLV }, + { "tlv-data", Atom::typeTLVInitialData }, + { "tlv-zero-fill", Atom::typeTLVInitialZeroFill }, + { "tlv-init-ptr", Atom::typeTLVInitializerPtr }, + { NULL, Atom::typeUnknown } +}; + +Atom::ContentType KeyValues::contentType(const char* s) +{ + for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad content type value"); +} + +const char* KeyValues::contentType(Atom::ContentType s) { + for (const ContentTypeMapping* p = typeMappings; p->string != NULL; ++p) { + if ( p->value == s ) + return p->string; + } + llvm::report_fatal_error("bad content type value"); +} + + + + + + + +struct DeadStripMapping { + const char* string; + Atom::DeadStripKind value; +}; + +static const DeadStripMapping deadStripMappings[] = { + { "normal", Atom::deadStripNormal }, + { "never", Atom::deadStripNever }, + { "always", Atom::deadStripAlways }, + { NULL, Atom::deadStripNormal } +}; + +Atom::DeadStripKind KeyValues::deadStripKind(const char* s) +{ + for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad dead strip value"); +} + +const char* KeyValues::deadStripKind(Atom::DeadStripKind dsk) { + for (const DeadStripMapping* p = deadStripMappings; p->string != NULL; ++p) { + if ( p->value == dsk ) + return p->string; + } + llvm::report_fatal_error("bad dead strip value"); +} + + + + + + +struct SectionChoiceMapping { + const char* string; + Atom::SectionChoice value; +}; + +static const SectionChoiceMapping sectMappings[] = { + { "content", Atom::sectionBasedOnContent }, + { "custom", Atom::sectionCustomPreferred }, + { "custom-required", Atom::sectionCustomRequired }, + { NULL, Atom::sectionBasedOnContent } +}; + +Atom::SectionChoice KeyValues::sectionChoice(const char* s) +{ + for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { + if ( strcmp(p->string, s) == 0 ) + return p->value; + } + llvm::report_fatal_error("bad dead strip value"); +} + +const char* KeyValues::sectionChoice(Atom::SectionChoice s) { + for (const SectionChoiceMapping* p = sectMappings; p->string != NULL; ++p) { + if ( p->value == s ) + return p->string; + } + llvm::report_fatal_error("bad dead strip value"); +} + + + + + + + +bool KeyValues::internalName(const char* s) +{ + if ( strcmp(s, "true") == 0 ) + return true; + else if ( strcmp(s, "false") == 0 ) + return false; + llvm::report_fatal_error("bad internal-name value"); +} + +const char* KeyValues::internalName(bool b) { + return b ? "true" : "false"; +} + + + + + + +bool KeyValues::mergeDuplicates(const char* s) +{ + if ( strcmp(s, "true") == 0 ) + return true; + else if ( strcmp(s, "false") == 0 ) + return false; + llvm::report_fatal_error("bad merge-duplicates value"); +} + +const char* KeyValues::mergeDuplicates(bool b) { + return b ? "true" : "false"; +} + + + + + + +bool KeyValues::autoHide(const char* s) +{ + if ( strcmp(s, "true") == 0 ) + return true; + else if ( strcmp(s, "false") == 0 ) + return false; + llvm::report_fatal_error("bad auto-hide value"); +} + +const char* KeyValues::autoHide(bool b) { + return b ? "true" : "false"; +} + + + + + +bool KeyValues::isThumb(const char* s) +{ + if ( strcmp(s, "true") == 0 ) + return true; + else if ( strcmp(s, "false") == 0 ) + return false; + llvm::report_fatal_error("bad is-thumb value"); +} + +const char* KeyValues::isThumb(bool b) { + return b ? "true" : "false"; +} + + + + +bool KeyValues::isAlias(const char* s) +{ + if ( strcmp(s, "true") == 0 ) + return true; + else if ( strcmp(s, "false") == 0 ) + return false; + llvm::report_fatal_error("bad is-alias value"); +} + +const char* KeyValues::isAlias(bool b) { + return b ? "true" : "false"; +} + + + + + + +} // namespace yaml +} // namespace lld diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/Core/YamlKeyValues.h new file mode 100644 index 0000000..c8890bd --- /dev/null +++ b/lld/lib/Core/YamlKeyValues.h @@ -0,0 +1,83 @@ +//===- Core/YamlKeyValues.h - Reads YAML ----------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_CORE_YAML_KEY_VALUES_H_ +#define LLD_CORE_YAML_KEY_VALUES_H_ + +#include "lld/Core/Atom.h" + + +namespace lld { +namespace yaml { + +class KeyValues { +public: + static const char* const nameKeyword; + static const char* const sectionNameKeyword; + static const char* const contentKeyword; + static const char* const sizeKeyword; + + + static const char* const scopeKeyword; + static const Atom::Scope scopeDefault; + static Atom::Scope scope(const char*); + static const char* scope(Atom::Scope); + + static const char* const definitionKeyword; + static const Atom::Definition definitionDefault; + static Atom::Definition definition(const char*); + static const char* definition(Atom::Definition); + + static const char* const contentTypeKeyword; + static const Atom::ContentType contentTypeDefault; + static Atom::ContentType contentType(const char*); + static const char* contentType(Atom::ContentType); + + static const char* const deadStripKindKeyword; + static const Atom::DeadStripKind deadStripKindDefault; + static Atom::DeadStripKind deadStripKind(const char*); + static const char* deadStripKind(Atom::DeadStripKind); + + static const char* const sectionChoiceKeyword; + static const Atom::SectionChoice sectionChoiceDefault; + static Atom::SectionChoice sectionChoice(const char*); + static const char* sectionChoice(Atom::SectionChoice); + + static const char* const internalNameKeyword; + static const bool internalNameDefault; + static bool internalName(const char*); + static const char* internalName(bool); + + static const char* const mergeDuplicatesKeyword; + static const bool mergeDuplicatesDefault; + static bool mergeDuplicates(const char*); + static const char* mergeDuplicates(bool); + + static const char* const autoHideKeyword; + static const bool autoHideDefault; + static bool autoHide(const char*); + static const char* autoHide(bool); + + static const char* const isThumbKeyword; + static const bool isThumbDefault; + static bool isThumb(const char*); + static const char* isThumb(bool); + + static const char* const isAliasKeyword; + static const bool isAliasDefault; + static bool isAlias(const char*); + static const char* isAlias(bool); + +}; + +} // namespace yaml +} // namespace lld + +#endif // LLD_CORE_YAML_KEY_VALUES_H_ + diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/Core/YamlReader.cpp index c35664e..7930d64e 100644 --- a/lld/lib/Core/YamlReader.cpp +++ b/lld/lib/Core/YamlReader.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "YamlKeyValues.h" + #include "lld/Core/YamlReader.h" #include "lld/Core/Atom.h" #include "lld/Core/File.h" @@ -21,10 +23,46 @@ #include -namespace { const llvm::error_code success; } + namespace lld { namespace yaml { + +enum yaml_reader_errors { + success = 0, + unknown_keyword, + illegal_value +}; + +class reader_error_category : public llvm::_do_message { +public: + virtual const char* name() const { + return "lld.yaml.reader"; + } + virtual std::string message(int ev) const; +}; + +const reader_error_category reader_error_category_singleton; + +std::string reader_error_category::message(int ev) const { + switch (ev) { + case success: + return "Success"; + case unknown_keyword: + return "Unknown keyword found in yaml file"; + case illegal_value: + return "Bad value found in yaml file"; + default: + llvm_unreachable("An enumerator of yaml_reader_errors does not have a " + "message defined."); + } +} + +inline llvm::error_code make_error_code(yaml_reader_errors e) { + return llvm::error_code(static_cast(e), reader_error_category_singleton); +} + + class YAML { public: struct Entry { @@ -137,6 +175,7 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector &entries) { state = inTriplePeriod; } else if (c == '\n') { // ignore empty lines + depth = 0; } else if (c == '\t') { llvm::report_fatal_error("TAB character found in yaml file"); } else { @@ -176,6 +215,8 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector &entries) { state = inValueSequence; } else if (c == ' ') { // eat space + } else if (c == '\t') { + llvm::report_fatal_error("TAB character found in yaml file"); } else { return; } @@ -247,16 +288,20 @@ public: , SectionChoice sc , bool intn , bool md + , bool ah , DeadStripKind dsk , bool tb , bool al , Alignment a , YAMLFile& f - , const char *n) - : Atom(ord, d, s, ct, sc, intn, md, dsk, tb, al, a) + , const char *n + , const char* sn + , uint64_t sz) + : Atom(ord, d, s, ct, sc, intn, md, ah, dsk, tb, al, a) , _file(f) , _name(n) - , _size(0) + , _sectionName(sn) + , _size(sz) , _refStartIndex(f._lastRefIndex) , _refEndIndex(f._references.size()) { f._lastRefIndex = _refEndIndex; @@ -273,6 +318,10 @@ public: virtual llvm::StringRef name() const { return _name; } + + virtual llvm::StringRef customSectionName() const { + return _sectionName; + } virtual uint64_t objectAddress() const { return 0; @@ -286,11 +335,12 @@ public: virtual Reference::iterator referencesBegin() const; virtual Reference::iterator referencesEnd() const; private: - YAMLFile& _file; - const char *_name; - unsigned long _size; - unsigned int _refStartIndex; - unsigned int _refEndIndex; + YAMLFile& _file; + const char * _name; + const char * _sectionName; + unsigned long _size; + unsigned int _refStartIndex; + unsigned int _refEndIndex; }; Reference::iterator YAMLAtom::referencesBegin() const { @@ -310,11 +360,7 @@ public: YAMLAtomState(); void setName(const char *n); - void setScope(const char *n); - void setType(const char *n); void setAlign2(const char *n); - void setDefinition(const char *n); - void setMergeDuplicates(const char *n); void setFixupKind(const char *n); void setFixupOffset(const char *n); @@ -323,8 +369,8 @@ public: void makeAtom(YAMLFile&); -private: uint64_t _ordinal; + long long _size; const char *_name; Atom::Alignment _align; Atom::ContentType _type; @@ -333,23 +379,29 @@ private: Atom::SectionChoice _sectionChoice; bool _internalName; bool _mergeDuplicates; - Atom::DeadStripKind _dontDeadStrip; + Atom::DeadStripKind _deadStrip; bool _thumb; bool _alias; + bool _autoHide; + const char *_sectionName; Reference _ref; }; YAMLAtomState::YAMLAtomState() : _ordinal(0) + , _size(0) , _name(NULL) , _align(0, 0) - , _type(Atom::typeData) - , _scope(Atom::scopeGlobal) - , _internalName(false) - , _mergeDuplicates(false) - , _dontDeadStrip(Atom::deadStripNormal) - , _thumb(false) - , _alias(false) { + , _type(KeyValues::contentTypeDefault) + , _scope(KeyValues::scopeDefault) + , _def(KeyValues::definitionDefault) + , _internalName(KeyValues::internalNameDefault) + , _mergeDuplicates(KeyValues::mergeDuplicatesDefault) + , _deadStrip(KeyValues::deadStripKindDefault) + , _thumb(KeyValues::isThumbDefault) + , _alias(KeyValues::isAliasDefault) + , _autoHide(KeyValues::autoHideDefault) + , _sectionName(NULL) { _ref.target = NULL; _ref.addend = 0; _ref.offsetInAtom = 0; @@ -359,8 +411,9 @@ YAMLAtomState::YAMLAtomState() void YAMLAtomState::makeAtom(YAMLFile& f) { Atom *a = new YAMLAtom(_ordinal, _def, _scope, _type, _sectionChoice, - _internalName, _mergeDuplicates, _dontDeadStrip, - _thumb, _alias, _align, f, _name); + _internalName, _mergeDuplicates, _autoHide, + _deadStrip, _thumb, _alias, _align, f, + _name, _sectionName, _size); f._atoms.push_back(a); ++_ordinal; @@ -369,15 +422,17 @@ void YAMLAtomState::makeAtom(YAMLFile& f) { _name = NULL; _align.powerOf2 = 0; _align.modulus = 0; - _type = Atom::typeData; - _scope = Atom::scopeGlobal; - _def = Atom::definitionRegular; - _sectionChoice = Atom::sectionBasedOnContent; - _internalName = false; - _mergeDuplicates = false; - _dontDeadStrip = Atom::deadStripNormal; - _thumb = false; - _alias = false; + _type = KeyValues::contentTypeDefault; + _scope = KeyValues::scopeDefault; + _def = KeyValues::definitionDefault; + _sectionChoice = KeyValues::sectionChoiceDefault; + _internalName = KeyValues::internalNameDefault; + _mergeDuplicates = KeyValues::mergeDuplicatesDefault; + _deadStrip = KeyValues::deadStripKindDefault; + _thumb = KeyValues::isThumbDefault; + _alias = KeyValues::isAliasDefault; + _autoHide = KeyValues::autoHideDefault; + _sectionName = NULL; _ref.target = NULL; _ref.addend = 0; _ref.offsetInAtom = 0; @@ -389,29 +444,6 @@ void YAMLAtomState::setName(const char *n) { _name = n; } -void YAMLAtomState::setScope(const char *s) { - if (strcmp(s, "global") == 0) - _scope = Atom::scopeGlobal; - else if (strcmp(s, "hidden") == 0) - _scope = Atom::scopeLinkageUnit; - else if (strcmp(s, "static") == 0) - _scope = Atom::scopeTranslationUnit; - else - llvm::report_fatal_error("bad scope value"); -} - -void YAMLAtomState::setType(const char *s) { - if (strcmp(s, "code") == 0) - _type = Atom::typeCode; - else if (strcmp(s, "c-string") == 0) - _type = Atom::typeCString; - else if (strcmp(s, "zero-fill") == 0) - _type = Atom::typeZeroFill; - else if (strcmp(s, "data") == 0) - _type = Atom::typeData; - else - llvm::report_fatal_error("bad type value"); -} void YAMLAtomState::setAlign2(const char *s) { llvm::StringRef str(s); @@ -420,27 +452,6 @@ void YAMLAtomState::setAlign2(const char *s) { _align.powerOf2 = static_cast(res); } -void YAMLAtomState::setDefinition(const char *s) { - if (strcmp(s, "regular") == 0) - _def = Atom::definitionRegular; - else if (strcmp(s, "tentative") == 0) - _def = Atom::definitionTentative; - else if (strcmp(s, "weak") == 0) - _def = Atom::definitionWeak; - else if (strcmp(s, "absolute") == 0) - _def = Atom::definitionAbsolute; - else - llvm::report_fatal_error("bad definition value"); -} - -void YAMLAtomState::setMergeDuplicates(const char *s) { - if (strcmp(s, "true") == 0) - _mergeDuplicates = true; - else if (strcmp(s, "false") == 0) - _mergeDuplicates = false; - else - llvm::report_fatal_error("bad merge-duplicates value"); -} void YAMLAtomState::setFixupKind(const char *s) { if (strcmp(s, "pcrel32") == 0) @@ -527,28 +538,76 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb haveAtom = false; } } - if (strcmp(entry->key, "name") == 0) { + if (strcmp(entry->key, KeyValues::nameKeyword) == 0) { atomState.setName(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "scope") == 0) { - atomState.setScope(entry->value); + } + else if (strcmp(entry->key, KeyValues::internalNameKeyword) == 0) { + atomState._internalName = KeyValues::internalName(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "type") == 0) { - atomState.setType(entry->value); + } + else if (strcmp(entry->key, KeyValues::definitionKeyword) == 0) { + atomState._def = KeyValues::definition(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "align2") == 0) { - atomState.setAlign2(entry->value); + } + else if (strcmp(entry->key, KeyValues::scopeKeyword) == 0) { + atomState._scope = KeyValues::scope(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::contentTypeKeyword) == 0) { + atomState._type = KeyValues::contentType(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::deadStripKindKeyword) == 0) { + atomState._deadStrip = KeyValues::deadStripKind(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::sectionChoiceKeyword) == 0) { + atomState._sectionChoice = KeyValues::sectionChoice(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "definition") == 0) { - atomState.setDefinition(entry->value); + } + else if (strcmp(entry->key, KeyValues::mergeDuplicatesKeyword) == 0) { + atomState._mergeDuplicates = KeyValues::mergeDuplicates(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::autoHideKeyword) == 0) { + atomState._autoHide = KeyValues::autoHide(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "merge-duplicates") == 0) { - atomState.setMergeDuplicates(entry->value); + } + else if (strcmp(entry->key, KeyValues::isThumbKeyword) == 0) { + atomState._thumb = KeyValues::isThumb(entry->value); haveAtom = true; - } else if (strcmp(entry->key, "fixups") == 0) { + } + else if (strcmp(entry->key, KeyValues::isAliasKeyword) == 0) { + atomState._alias = KeyValues::isAlias(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::sectionNameKeyword) == 0) { + atomState._sectionName = entry->value; + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::sizeKeyword) == 0) { + llvm::StringRef val = entry->value; + if ( val.getAsInteger(0, atomState._size) ) + return make_error_code(illegal_value); + haveAtom = true; + } + else if (strcmp(entry->key, KeyValues::contentKeyword) == 0) { + // TO DO: switch to content mode + haveAtom = true; + } + else if (strcmp(entry->key, "align2") == 0) { + atomState.setAlign2(entry->value); + haveAtom = true; + } + else if (strcmp(entry->key, "fixups") == 0) { inFixups = true; } - } else if (depthForFixups == entry->depth) { + else { + return make_error_code(unknown_keyword); + } + } + else if (depthForFixups == entry->depth) { if (entry->beginSequence) { if (haveFixup) { atomState.addFixup(file); @@ -574,7 +633,7 @@ llvm::error_code parseObjectText( llvm::MemoryBuffer *mb } result.push_back(file); - return success; + return make_error_code(success); } // diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/Core/YamlWriter.cpp index e571106..8efb94c 100644 --- a/lld/lib/Core/YamlWriter.cpp +++ b/lld/lib/Core/YamlWriter.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "YamlKeyValues.h" + #include "lld/Core/YamlWriter.h" #include "lld/Core/Atom.h" #include "lld/Core/File.h" @@ -24,26 +26,121 @@ namespace yaml { class Handler : public File::AtomHandler { public: - Handler(llvm::raw_ostream &out) : _out(out) { } + Handler(llvm::raw_ostream &out) : _out(out), _firstAtom(true) { } - virtual void doFile(const class File &) { } + virtual void doFile(const class File &) { _firstAtom = true; } + virtual void doAtom(const class Atom &atom) { - _out << " - name: " << atom.name() << "\n"; + // add blank line between atoms for readability + if ( !_firstAtom ) + _out << "\n"; + _firstAtom = false; + + _out << " - " + << KeyValues::nameKeyword + << ":" + << spacePadding(KeyValues::nameKeyword) + << atom.name() + << "\n"; + + if ( atom.internalName() != KeyValues::internalNameDefault ) { + _out << " " + << KeyValues::internalNameKeyword + << ":" + << spacePadding(KeyValues::internalNameKeyword) + << KeyValues::internalName(atom.internalName()) + << "\n"; + } - if ( atom.internalName() ) - _out << " internal-name: true\n"; - - if ( atom.definition() != Atom::definitionRegular ) - _out << " definition: " << definitionString(atom.definition()) <<"\n"; - - if ( atom.scope() != Atom::scopeTranslationUnit ) - _out << " scope: " << scopeString(atom.scope()) << "\n"; - - _out << " type: " << typeString(atom.contentType()) << "\n"; + if ( atom.definition() != KeyValues::definitionDefault ) { + _out << " " + << KeyValues::definitionKeyword + << ":" + << spacePadding(KeyValues::definitionKeyword) + << KeyValues::definition(atom.definition()) + << "\n"; + } - if ( atom.mergeDuplicates() ) - _out << " merge-duplicates: true\n"; - + if ( atom.scope() != KeyValues::scopeDefault ) { + _out << " " + << KeyValues::scopeKeyword + << ":" + << spacePadding(KeyValues::scopeKeyword) + << KeyValues::scope(atom.scope()) + << "\n"; + } + + if ( atom.contentType() != KeyValues::contentTypeDefault ) { + _out << " " + << KeyValues::contentTypeKeyword + << ":" + << spacePadding(KeyValues::contentTypeKeyword) + << KeyValues::contentType(atom.contentType()) + << "\n"; + } + + if ( atom.deadStrip() != KeyValues::deadStripKindDefault ) { + _out << " " + << KeyValues::deadStripKindKeyword + << ":" + << spacePadding(KeyValues::deadStripKindKeyword) + << KeyValues::deadStripKind(atom.deadStrip()) + << "\n"; + } + + if ( atom.sectionChoice() != KeyValues::sectionChoiceDefault ) { + _out << " " + << KeyValues::sectionChoiceKeyword + << ":" + << spacePadding(KeyValues::sectionChoiceKeyword) + << KeyValues::sectionChoice(atom.sectionChoice()) + << "\n"; + assert( ! atom.customSectionName().empty() ); + _out << " " + << KeyValues::sectionNameKeyword + << ":" + << spacePadding(KeyValues::sectionNameKeyword) + << atom.customSectionName() + << "\n"; + } + + if ( atom.mergeDuplicates() != KeyValues::mergeDuplicatesDefault ) { + _out << " " + << KeyValues::mergeDuplicatesKeyword + << ":" + << spacePadding(KeyValues::mergeDuplicatesKeyword) + << KeyValues::mergeDuplicates(atom.mergeDuplicates()) + << "\n"; + } + + if ( atom.autoHide() != KeyValues::autoHideDefault ) { + _out << " " + << KeyValues::autoHideKeyword + << ":" + << spacePadding(KeyValues::autoHideKeyword) + << KeyValues::autoHide(atom.autoHide()) + << "\n"; + } + + if ( atom.isThumb() != KeyValues::isThumbDefault ) { + _out << " " + << KeyValues::isThumbKeyword + << ":" + << spacePadding(KeyValues::isThumbKeyword) + << KeyValues::isThumb(atom.isThumb()) + << "\n"; + } + + if ( atom.isAlias() != KeyValues::isAliasDefault ) { + _out << " " + << KeyValues::isAliasKeyword + << ":" + << spacePadding(KeyValues::isAliasKeyword) + << KeyValues::isAlias(atom.isAlias()) + << "\n"; + } + + if (atom.referencesBegin() != atom.referencesEnd()) { _out << " fixups:\n"; for (Reference::iterator it = atom.referencesBegin(), @@ -56,49 +153,17 @@ public: } private: - const char *scopeString(Atom::Scope scope) { - switch (scope) { - case Atom::scopeTranslationUnit: - return "static"; - case Atom::scopeLinkageUnit: - return "hidden"; - case Atom::scopeGlobal: - return "global"; - } - return "???"; + // return a string of the correct number of spaces to align value + const char* spacePadding(const char* key) { + const char* spaces = " "; + assert(strlen(spaces) > strlen(key)); + return &spaces[strlen(key)]; } - const char *typeString(Atom::ContentType type) { - switch (type) { - case Atom::typeCode: - return "code"; - case Atom::typeCString: - return "c-string"; - case Atom::typeZeroFill: - return "zero-fill"; - case Atom::typeData: - return "data"; - default: - return "???"; - } - } - const char *definitionString(Atom::Definition def) { - switch (def) { - case Atom::definitionRegular: - return "regular"; - case Atom::definitionWeak: - return "weak"; - case Atom::definitionTentative: - return "tentative"; - case Atom::definitionAbsolute: - return "absolute"; - default: - return "???"; - } - } - llvm::raw_ostream &_out; + llvm::raw_ostream& _out; + bool _firstAtom; }; void writeObjectText(File &file, llvm::raw_ostream &out) { diff --git a/lld/test/auto-hide-coalesce.objtxt b/lld/test/auto-hide-coalesce.objtxt new file mode 100644 index 0000000..7ee5638 --- /dev/null +++ b/lld/test/auto-hide-coalesce.objtxt @@ -0,0 +1,76 @@ +# RUN: lld-core %s | FileCheck %s + +# +# Tests auto-hide bit during coalescing +# + +--- +atoms: + - name: _inlineFunc1 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: true + + - name: _inlineFunc2 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: true + + - name: _inlineFunc3 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: false + + - name: _inlineFunc4 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: false +--- +atoms: + - name: _inlineFunc1 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: true + + - name: _inlineFunc2 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: false + + - name: _inlineFunc3 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: true + + - name: _inlineFunc4 + scope: global + definition: regular + type: code + merge-duplicates: true + auto-hide: false +... + + +# CHECK: name: _inlineFunc1 +# CHECK: auto-hide: true +# CHECK: name: _inlineFunc3 +# CHECK-NOT: auto-hide: true +# CHECK: name: _inlineFunc4 +# CHECK-NOT: auto-hide: true +# CHECK: name: _inlineFunc2 +# CHECK-NOT: auto-hide: true +# CHECK: ... diff --git a/lld/test/custom-section.objtxt b/lld/test/custom-section.objtxt new file mode 100644 index 0000000..99a119f --- /dev/null +++ b/lld/test/custom-section.objtxt @@ -0,0 +1,34 @@ +# RUN: lld-core %s | FileCheck %s + +# +# Test that custom sections are preserved +# + +--- +atoms: + - name: _foo1 + scope: global + section-choice: content + + - name: _foo2 + scope: global + section-choice: custom + section-name: __foozle + + - name: _foo3 + scope: global + section-choice: custom-required + section-name: __boozle + +... + + +# CHECK: name: _foo1 +# CHECK-NOT: section-name: +# CHECK: name: _foo2 +# CHECK: section-choice: custom +# CHECK: section-name: __foozle +# CHECK: name: _foo3 +# CHECK: section-choice: custom-required +# CHECK: section-name: __boozle +# CHECK: ... diff --git a/lld/test/dead-strip-attributes.objtxt b/lld/test/dead-strip-attributes.objtxt new file mode 100644 index 0000000..47f46c6 --- /dev/null +++ b/lld/test/dead-strip-attributes.objtxt @@ -0,0 +1,29 @@ +# RUN: lld-core %s | FileCheck %s + +# +# Test that dead strip attributes are preserved +# + +--- +atoms: + - name: _foo1 + dead-strip: normal +--- +atoms: + - name: _foo2 + dead-strip: never +--- +atoms: + - name: _foo3 + dead-strip: always +... + + +# CHECK: name: _foo1 +# CHECK-NOT: dead-strip: never +# CHECK-NOT: dead-strip: always +# CHECK: name: _foo2 +# CHECK: dead-strip: never +# CHECK: name: _foo3 +# CHECK: dead-strip: always +# CHECK: ... diff --git a/lld/test/internal-name-attributes.objtxt b/lld/test/internal-name-attributes.objtxt new file mode 100644 index 0000000..8d37a00 --- /dev/null +++ b/lld/test/internal-name-attributes.objtxt @@ -0,0 +1,27 @@ +# RUN: lld-core %s | FileCheck %s + +# +# Test that internal-name attributes are preserved +# + +--- +atoms: + - name: foo + internal-name: false + - name: L0 + internal-name: true + - name: L1 + internal-name: true + - name: bar +... + + +# CHECK: name: foo +# CHECK-NOT: internal-name: false +# CHECK: name: L0 +# CHECK: internal-name: true +# CHECK: name: L1 +# CHECK: internal-name: true +# CHECK: name: bar +# CHECK-NOT: internal-name: false +# CHECK: ... diff --git a/lld/test/multiple-def-error.objtxt b/lld/test/multiple-def-error.objtxt index 4a52f4d..e57a017 100644 --- a/lld/test/multiple-def-error.objtxt +++ b/lld/test/multiple-def-error.objtxt @@ -8,11 +8,13 @@ atoms: - name: _foo definition: regular + scope: global type: data --- atoms: - name: _foo definition: regular + scope: global type: data ... diff --git a/lld/test/tent-merge.objtxt b/lld/test/tent-merge.objtxt index 799530e..bb8573e 100644 --- a/lld/test/tent-merge.objtxt +++ b/lld/test/tent-merge.objtxt @@ -9,12 +9,14 @@ atoms: - name: _foo definition: tentative + scope: global type: zero-fill size: 4 --- atoms: - name: _foo definition: regular + scope: global type: data content: [ 00, 00, 00, 00 ] ... diff --git a/lld/test/weak-coalesce.objtxt b/lld/test/weak-coalesce.objtxt index 48e9e09..f3640ce 100644 --- a/lld/test/weak-coalesce.objtxt +++ b/lld/test/weak-coalesce.objtxt @@ -8,16 +8,19 @@ atoms: - name: _foo definition: weak + scope: global type: data --- atoms: - name: _foo definition: regular + scope: global type: data --- atoms: - name: _foo definition: weak + scope: global type: data ...