diff options
Diffstat (limited to 'lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp')
-rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 228 |
1 files changed, 111 insertions, 117 deletions
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 8bf5291e7c0..e5356e758dc 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -10,6 +10,7 @@ #include "lld/ReaderWriter/Reader.h" #include "lld/ReaderWriter/Simple.h" #include "lld/ReaderWriter/Writer.h" +#include "lld/ReaderWriter/YamlContext.h" #include "lld/Core/ArchiveLibraryFile.h" #include "lld/Core/DefinedAtom.h" @@ -46,18 +47,6 @@ using namespace lld; /// how the mapping is done to and from YAML. namespace { -/// Most of the traits are context-free and always do the same transformation. -/// But, there are some traits that need some contextual information to properly -/// do their transform. This struct is available via io.getContext() and -/// supplies contextual information. -class ContextInfo { -public: - ContextInfo(const LinkingContext &context) - : _currentFile(nullptr), _context(context) {} - - lld::File *_currentFile; - const LinkingContext &_context; -}; /// Used when writing yaml files. /// In most cases, atoms names are unambiguous, so references can just @@ -260,9 +249,13 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8) // more readable than just true/false. LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull) -// lld::Reference::Kind is a typedef of int32. We need a stronger -// type to make template matching work, so invent RefKind. -LLVM_YAML_STRONG_TYPEDEF(lld::Reference::Kind, RefKind) +// lld::Reference::Kind is a tuple of <namespace, arch, value>. +// For yaml, we just want one string that encapsulates the tuple. +struct RefKind { + Reference::KindNamespace ns; + Reference::KindArch arch; + uint16_t value; +}; } // namespace anon @@ -276,49 +269,26 @@ namespace yaml { // This is a custom formatter for RefKind template <> struct ScalarTraits<RefKind> { - static void output(const RefKind &value, void *ctxt, raw_ostream &out) { + static void output(const RefKind &kind, void *ctxt, raw_ostream &out) { assert(ctxt != nullptr); - ContextInfo *info = reinterpret_cast<ContextInfo *>(ctxt); - switch (value) { - case lld::Reference::kindLayoutAfter: - out << "layout-after"; - break; - case lld::Reference::kindLayoutBefore: - out << "layout-before"; - break; - case lld::Reference::kindInGroup: - out << "in-group"; - break; - default: - if (auto relocStr = info->_context.stringFromRelocKind(value)) - out << *relocStr; - else - out << "<unknown>"; - break; - } + YamlContext *info = reinterpret_cast<YamlContext *>(ctxt); + assert(info->_registry); + StringRef str; + if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value, + str)) + out << str; + else + out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value; } - static StringRef input(StringRef scalar, void *ctxt, RefKind &value) { + static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) { assert(ctxt != nullptr); - ContextInfo *info = reinterpret_cast<ContextInfo *>(ctxt); - auto relocKind = info->_context.relocKindFromString(scalar); - if (!relocKind) { - if (scalar.equals("layout-after")) { - value = lld::Reference::kindLayoutAfter; - return StringRef(); - } - if (scalar.equals("layout-before")) { - value = lld::Reference::kindLayoutBefore; - return StringRef(); - } - if (scalar.equals("in-group")) { - value = lld::Reference::kindInGroup; - return StringRef(); - } - return "Invalid relocation kind"; - } - value = *relocKind; - return StringRef(); + YamlContext *info = reinterpret_cast<YamlContext *>(ctxt); + assert(info->_registry); + if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch, + kind.value)) + return StringRef(); + return StringRef("unknown reference kind"); } }; @@ -595,12 +565,9 @@ template <> struct MappingTraits<const lld::File *> { class NormArchiveFile : public lld::ArchiveLibraryFile { public: NormArchiveFile(IO &io) - : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_context, ""), - _path() {} + : ArchiveLibraryFile(""), _path() {} NormArchiveFile(IO &io, const lld::File *file) - : ArchiveLibraryFile(((ContextInfo *)io.getContext())->_context, - file->path()), - _path(file->path()) { + : ArchiveLibraryFile(file->path()), _path(file->path()) { // If we want to support writing archives, this constructor would // need to populate _members. } @@ -639,15 +606,20 @@ template <> struct MappingTraits<const lld::File *> { return nullptr; } + virtual error_code parseAllMembers( + std::vector<std::unique_ptr<File>> &result) const { + return error_code::success(); + } + StringRef _path; std::vector<ArchMember> _members; }; class NormalizedFile : public lld::File { public: - NormalizedFile(IO &io) : File("", kindObject), _IO(io), _rnb(nullptr) {} + NormalizedFile(IO &io) : File("", kindObject), _io(io), _rnb(nullptr) {} NormalizedFile(IO &io, const lld::File *file) - : File(file->path(), kindObject), _IO(io), + : File(file->path(), kindObject), _io(io), _rnb(new RefNameBuilder(*file)), _path(file->path()) { for (const lld::DefinedAtom *a : file->defined()) _definedAtoms.push_back(a); @@ -674,10 +646,6 @@ template <> struct MappingTraits<const lld::File *> { return _absoluteAtoms; } - virtual const LinkingContext &getLinkingContext() const { - return ((ContextInfo *)_IO.getContext())->_context; - } - // Allocate a new copy of this string and keep track of allocations // in _stringCopies, so they can be freed when File is destroyed. StringRef copyString(StringRef str) { @@ -691,7 +659,7 @@ template <> struct MappingTraits<const lld::File *> { return r; } - IO &_IO; + IO &_io; RefNameBuilder *_rnb; StringRef _path; AtomList<lld::DefinedAtom> _definedAtoms; @@ -706,7 +674,6 @@ template <> struct MappingTraits<const lld::File *> { FileKinds kind = fileKindObjectAtoms; // If reading, peek ahead to see what kind of file this is. io.mapOptional("kind", kind, fileKindObjectAtoms); - // switch (kind) { case fileKindObjectAtoms: mappingAtoms(io, file); @@ -725,9 +692,9 @@ template <> struct MappingTraits<const lld::File *> { static void mappingAtoms(IO &io, const lld::File *&file) { MappingNormalizationHeap<NormalizedFile, const lld::File *> keys(io, file); - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); - info->_currentFile = keys.operator->(); + info->_file = keys.operator->(); io.mapOptional("path", keys->_path); io.mapOptional("defined-atoms", keys->_definedAtoms); @@ -750,19 +717,26 @@ template <> struct MappingTraits<const lld::Reference *> { class NormalizedReference : public lld::Reference { public: NormalizedReference(IO &io) - : _target(nullptr), _targetName(), _offset(0), _addend(0) {} + : lld::Reference(lld::Reference::KindNamespace::all, + lld::Reference::KindArch::all, 0), + _target(nullptr), _targetName(), _offset(0), _addend(0) {} NormalizedReference(IO &io, const lld::Reference *ref) - : _target(nullptr), _targetName(targetName(io, ref)), - _offset(ref->offsetInAtom()), _addend(ref->addend()), - _mappedKind(ref->kind()) {} + : lld::Reference(ref->kindNamespace(), ref->kindArch(), + ref->kindValue()), + _target(nullptr), _targetName(targetName(io, ref)), + _offset(ref->offsetInAtom()), _addend(ref->addend()) { + _mappedKind.ns = ref->kindNamespace(); + _mappedKind.arch = ref->kindArch(); + _mappedKind.value = ref->kindValue(); + } const lld::Reference *denormalize(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); if (!_targetName.empty()) _targetName = f->copyString(_targetName); DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs() @@ -770,7 +744,9 @@ template <> struct MappingTraits<const lld::Reference *> { << _targetName << "' (" << (void *)_targetName.data() << ", " << _targetName.size() << ")\n"); - setKind(_mappedKind); + setKindNamespace(_mappedKind.ns); + setKindArch(_mappedKind.arch); + setKindValue(_mappedKind.value); return this; } void bind(const RefNameResolver &); @@ -830,11 +806,11 @@ template <> struct MappingTraits<const lld::DefinedAtom *> { _content.push_back(x); } const lld::DefinedAtom *denormalize(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); if (!_name.empty()) _name = f->copyString(_name); if (!_refName.empty()) @@ -850,10 +826,10 @@ template <> struct MappingTraits<const lld::DefinedAtom *> { void bind(const RefNameResolver &); // Extract current File object from YAML I/O parsing context const lld::File &fileFromContext(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); - assert(info->_currentFile != nullptr); - return *info->_currentFile; + assert(info->_file != nullptr); + return *info->_file; } virtual const lld::File &file() const { return _file; } @@ -927,10 +903,10 @@ template <> struct MappingTraits<const lld::DefinedAtom *> { if (io.outputting()) { // If writing YAML, check if atom needs a ref-name. typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); assert(f); assert(f->_rnb); if (f->_rnb->hasRefName(atom)) { @@ -980,11 +956,11 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> { _canBeNull(atom->canBeNull()), _fallback(atom->fallback()) {} const lld::UndefinedAtom *denormalize(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); if (!_name.empty()) _name = f->copyString(_name); @@ -997,10 +973,10 @@ template <> struct MappingTraits<const lld::UndefinedAtom *> { // Extract current File object from YAML I/O parsing context const lld::File &fileFromContext(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); - assert(info->_currentFile != nullptr); - return *info->_currentFile; + assert(info->_file != nullptr); + return *info->_file; } virtual const lld::File &file() const { return _file; } @@ -1040,11 +1016,11 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> { _type(atom->type()), _size(atom->size()) {} const lld::SharedLibraryAtom *denormalize(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); if (!_name.empty()) _name = f->copyString(_name); if (!_loadName.empty()) @@ -1059,10 +1035,10 @@ template <> struct MappingTraits<const lld::SharedLibraryAtom *> { // Extract current File object from YAML I/O parsing context const lld::File &fileFromContext(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); - assert(info->_currentFile != nullptr); - return *info->_currentFile; + assert(info->_file != nullptr); + return *info->_file; } virtual const lld::File &file() const { return _file; } @@ -1104,11 +1080,11 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> { : _file(fileFromContext(io)), _name(atom->name()), _scope(atom->scope()), _value(atom->value()) {} const lld::AbsoluteAtom *denormalize(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); if (!_name.empty()) _name = f->copyString(_name); @@ -1120,10 +1096,10 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> { } // Extract current File object from YAML I/O parsing context const lld::File &fileFromContext(IO &io) { - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); - assert(info->_currentFile != nullptr); - return *info->_currentFile; + assert(info->_file != nullptr); + return *info->_file; } virtual const lld::File &file() const { return _file; } @@ -1144,10 +1120,10 @@ template <> struct MappingTraits<const lld::AbsoluteAtom *> { if (io.outputting()) { typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); NormalizedFile *f = - reinterpret_cast<NormalizedFile *>(info->_currentFile); + reinterpret_cast<NormalizedFile *>(info->_file); assert(f); assert(f->_rnb); if (f->_rnb->hasRefName(atom)) { @@ -1226,10 +1202,10 @@ MappingTraits<const lld::Reference *>::NormalizedReference::targetName( IO &io, const lld::Reference *ref) { if (ref->target() == nullptr) return StringRef(); - ContextInfo *info = reinterpret_cast<ContextInfo *>(io.getContext()); + YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext()); assert(info != nullptr); typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile; - NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_currentFile); + NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file); RefNameBuilder *rnb = f->_rnb; if (rnb->hasRefName(ref->target())) return rnb->refName(ref->target()); @@ -1251,8 +1227,10 @@ public: return llvm::make_error_code(llvm::errc::no_such_file_or_directory); // Create yaml Output writer, using yaml options for context. - ContextInfo context(_context); - llvm::yaml::Output yout(out, &context); + YamlContext yamlContext; + yamlContext._linkingContext = &_context; + yamlContext._registry = &_context.registry(); + llvm::yaml::Output yout(out, &yamlContext); // Write yaml output. const lld::File *fileRef = &file; @@ -1265,12 +1243,21 @@ private: const LinkingContext &_context; }; -class ReaderYAML : public Reader { +} // end namespace yaml + +namespace { + +class YAMLReader : public Reader { public: - ReaderYAML(const LinkingContext &context) : Reader(context) {} + YAMLReader(const Registry ®istry) : _registry(registry) { } - error_code parseFile(std::unique_ptr<MemoryBuffer> &mb, - std::vector<std::unique_ptr<File> > &result) const { + virtual bool canParse(file_magic, StringRef ext, const MemoryBuffer&) const { + return (ext.equals(".objtxt") || ext.equals(".yaml")); + } + + virtual error_code + parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &, + std::vector<std::unique_ptr<File>> &result) const { // Note: we do not take ownership of the MemoryBuffer. That is // because yaml may produce multiple File objects, so there is no // *one* File to take ownership. Therefore, the yaml File objects @@ -1278,15 +1265,16 @@ public: // Otherwise the strings will become invalid when this MemoryBuffer // is deallocated. - // Create YAML Input parser. - ContextInfo context(_context); - llvm::yaml::Input yin(mb->getBuffer(), &context); + // Create YAML Input Reader. + YamlContext yamlContext; + yamlContext._registry = &_registry; + llvm::yaml::Input yin(mb->getBuffer(), &yamlContext); // Fill vector with File objects created by parsing yaml. std::vector<const lld::File *> createdFiles; yin >> createdFiles; - // Quit now if there were parsing errors. + // Error out now if there were parsing errors. if (yin.error()) return make_error_code(lld::YamlReaderError::illegal_value); @@ -1297,14 +1285,20 @@ public: } return make_error_code(lld::YamlReaderError::success); } -}; -} // end namespace yaml +private: + const Registry &_registry; +}; + + +} // anonymous namespace + +void Registry::addSupportYamlFiles() { + add(std::unique_ptr<Reader>(new YAMLReader(*this))); +} + std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) { return std::unique_ptr<Writer>(new lld::yaml::Writer(context)); } -std::unique_ptr<Reader> createReaderYAML(const LinkingContext &context) { - return std::unique_ptr<Reader>(new lld::yaml::ReaderYAML(context)); -} } // end namespace lld |