Support more Atom attributes. Add more test cases to lld-core

llvm-svn: 147571
This commit is contained in:
Nick Kledzik 2012-01-04 23:58:17 +00:00
parent e04dadc248
commit 7735a7d1a0
16 changed files with 896 additions and 172 deletions

View File

@ -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:

View File

@ -10,7 +10,8 @@
#ifndef LLD_CORE_REFERENCES_H_
#define LLD_CORE_REFERENCES_H_
#include "llvm/Support/DataTypes.h"
#include <stdint.h>
namespace lld {

View File

@ -28,6 +28,7 @@ public:
, Atom::sectionBasedOnContent
, false
, false
, false
, deadStripNormal
, false
, false

View File

@ -3,6 +3,7 @@ add_lld_library(lldCore
File.cpp
Resolver.cpp
SymbolTable.cpp
YamlKeyValues.cpp
YamlReader.cpp
YamlWriter.cpp
)

View File

@ -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;
// Both mergeable. Use auto-hide bit as tie breaker
if ( existing->autoHide() != newAtom.autoHide() ) {
// They have different autoHide values, keep non-autohide one
useNew = existing->autoHide();
}
else {
// They have same autoHide, so just keep using existing
useNew = false;
}
}
else {
const Atom& use = _platform.handleMultipleDefinitions(*existing, newAtom);
if ( &use == existing ) {
// using existing atom, add new atom to _replacedAtoms
_replacedAtoms[&newAtom] = existing;
}
else {
// using new atom, update tables
_nameTable[name] = &newAtom;
_replacedAtoms[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;
}
}
}

View File

@ -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 <string.h>
#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

View File

@ -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_

View File

@ -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 <vector>
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<int>(e), reader_error_category_singleton);
}
class YAML {
public:
struct Entry {
@ -137,6 +175,7 @@ void YAML::parse(llvm::MemoryBuffer *mb, std::vector<const Entry *> &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<const Entry *> &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<uint16_t>(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) {
}
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, 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, KeyValues::isThumbKeyword) == 0) {
atomState._thumb = KeyValues::isThumb(entry->value);
haveAtom = true;
}
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, "definition") == 0) {
atomState.setDefinition(entry->value);
haveAtom = true;
} else if (strcmp(entry->key, "merge-duplicates") == 0) {
atomState.setMergeDuplicates(entry->value);
haveAtom = true;
} else if (strcmp(entry->key, "fixups") == 0) {
}
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);
}
//

View File

@ -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() )
_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.internalName() != KeyValues::internalNameDefault ) {
_out << " "
<< KeyValues::internalNameKeyword
<< ":"
<< spacePadding(KeyValues::internalNameKeyword)
<< KeyValues::internalName(atom.internalName())
<< "\n";
}
if ( atom.mergeDuplicates() )
_out << " merge-duplicates: true\n";
if ( atom.definition() != KeyValues::definitionDefault ) {
_out << " "
<< KeyValues::definitionKeyword
<< ":"
<< spacePadding(KeyValues::definitionKeyword)
<< KeyValues::definition(atom.definition())
<< "\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) {

View File

@ -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: ...

View File

@ -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: ...

View File

@ -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: ...

View File

@ -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: ...

View File

@ -8,11 +8,13 @@
atoms:
- name: _foo
definition: regular
scope: global
type: data
---
atoms:
- name: _foo
definition: regular
scope: global
type: data
...

View File

@ -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 ]
...

View File

@ -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
...