diff options
| author | Nick Kledzik <kledzik@apple.com> | 2012-05-31 22:34:00 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2012-05-31 22:34:00 +0000 |
| commit | abb6981f68a0cf631b6d7d36e67127bb1af50713 (patch) | |
| tree | 63d6fd7aeef209f7528fecf1a151df50f61f7fa9 /lld/tools | |
| parent | 5168a72b2628288c5ba3143745554e2eadbb67b0 (diff) | |
| download | bcm5719-llvm-abb6981f68a0cf631b6d7d36e67127bb1af50713.tar.gz bcm5719-llvm-abb6981f68a0cf631b6d7d36e67127bb1af50713.zip | |
Major refactoring: Remove Platform concept. In its place there are
now Reader and Writer subclasses for each file format. Each Reader and
Writer subclass defines an "options" class which controls how that Reader
or Writer operates.
llvm-svn: 157774
Diffstat (limited to 'lld/tools')
| -rw-r--r-- | lld/tools/lld-core/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | lld/tools/lld-core/TestingHelpers.hpp | 403 | ||||
| -rw-r--r-- | lld/tools/lld-core/lld-core.cpp | 480 |
3 files changed, 495 insertions, 398 deletions
diff --git a/lld/tools/lld-core/CMakeLists.txt b/lld/tools/lld-core/CMakeLists.txt index bd645094d59..4f4a43bbbc6 100644 --- a/lld/tools/lld-core/CMakeLists.txt +++ b/lld/tools/lld-core/CMakeLists.txt @@ -1,9 +1,13 @@ set(LLVM_USED_LIBS lldCore - lldReader lldPasses - lldDarwinPlatform - ) + lldMachO + lldPECOFF + lldELF + lldNative + lldYAML + lldReaderWriter + ) set(LLVM_LINK_COMPONENTS support diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp new file mode 100644 index 00000000000..20f4d570aeb --- /dev/null +++ b/lld/tools/lld-core/TestingHelpers.hpp @@ -0,0 +1,403 @@ +//===- tools/lld/TestingWriter.hpp - Linker Core Test Support -------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_TOOLS_TESTING_HELPERS_H_ +#define LLD_TOOLS_TESTING_HELPERS_H_ + +#include "lld/Core/Atom.h" +#include "lld/Core/LLVM.h" +#include "lld/Core/Pass.h" +#include "lld/Core/Resolver.h" +#include "lld/ReaderWriter/WriterYAML.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/system_error.h" + +#include <vector> + +using namespace lld; + +// +// Simple atom created by the stubs pass. +// +class TestingStubAtom : public DefinedAtom { +public: + TestingStubAtom(const File& f, const Atom& shlib) : + _file(f), _shlib(shlib) { + static uint32_t lastOrdinal = 0; + _ordinal = lastOrdinal++; + } + + virtual const File& file() const { + return _file; + } + + virtual StringRef name() const { + return StringRef(); + } + + virtual uint64_t ordinal() const { + return _ordinal; + } + + virtual uint64_t size() const { + return 0; + } + + virtual Scope scope() const { + return DefinedAtom::scopeLinkageUnit; + } + + virtual Interposable interposable() const { + return DefinedAtom::interposeNo; + } + + virtual Merge merge() const { + return DefinedAtom::mergeNo; + } + + virtual ContentType contentType() const { + return DefinedAtom::typeStub; + } + + virtual Alignment alignment() const { + return Alignment(0,0); + } + + virtual SectionChoice sectionChoice() const { + return DefinedAtom::sectionBasedOnContent; + } + + virtual StringRef customSectionName() const { + return StringRef(); + } + virtual DeadStripKind deadStrip() const { + return DefinedAtom::deadStripNormal; + } + + virtual ContentPermissions permissions() const { + return DefinedAtom::permR_X; + } + + virtual bool isThumb() const { + return false; + } + + virtual bool isAlias() const { + return false; + } + + virtual ArrayRef<uint8_t> rawContent() const { + return ArrayRef<uint8_t>(); + } + + virtual reference_iterator begin() const { + return reference_iterator(*this, nullptr); + } + + virtual reference_iterator end() const { + return reference_iterator(*this, nullptr); + } + + virtual const Reference* derefIterator(const void* iter) const { + return nullptr; + } + + virtual void incrementIterator(const void*& iter) const { + + } + +private: + const File& _file; + const Atom& _shlib; + uint32_t _ordinal; +}; + + + + +// +// Simple atom created by the GOT pass. +// +class TestingGOTAtom : public DefinedAtom { +public: + TestingGOTAtom(const File& f, const Atom& shlib) : + _file(f), _shlib(shlib) { + static uint32_t lastOrdinal = 0; + _ordinal = lastOrdinal++; + } + + virtual const File& file() const { + return _file; + } + + virtual StringRef name() const { + return StringRef(); + } + + virtual uint64_t ordinal() const { + return _ordinal; + } + + virtual uint64_t size() const { + return 0; + } + + virtual Scope scope() const { + return DefinedAtom::scopeLinkageUnit; + } + + virtual Interposable interposable() const { + return DefinedAtom::interposeNo; + } + + virtual Merge merge() const { + return DefinedAtom::mergeNo; + } + + virtual ContentType contentType() const { + return DefinedAtom::typeGOT; + } + + virtual Alignment alignment() const { + return Alignment(3,0); + } + + virtual SectionChoice sectionChoice() const { + return DefinedAtom::sectionBasedOnContent; + } + + virtual StringRef customSectionName() const { + return StringRef(); + } + virtual DeadStripKind deadStrip() const { + return DefinedAtom::deadStripNormal; + } + + virtual ContentPermissions permissions() const { + return DefinedAtom::permRW_; + } + + virtual bool isThumb() const { + return false; + } + + virtual bool isAlias() const { + return false; + } + + virtual ArrayRef<uint8_t> rawContent() const { + return ArrayRef<uint8_t>(); + } + + virtual reference_iterator begin() const { + return reference_iterator(*this, nullptr); + } + + virtual reference_iterator end() const { + return reference_iterator(*this, nullptr); + } + + virtual const Reference* derefIterator(const void* iter) const { + return nullptr; + } + + virtual void incrementIterator(const void*& iter) const { + + } + +private: + const File& _file; + const Atom& _shlib; + uint32_t _ordinal; +}; + + + +class TestingPassFile : public File { +public: + TestingPassFile() : File("Testing pass") { + } + + virtual void addAtom(const Atom &atom) { + if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) { + _definedAtoms._atoms.push_back(defAtom); + } + else { + assert(0 && "atom has unknown definition kind"); + } + } + + virtual const atom_collection<DefinedAtom>& defined() const { + return _definedAtoms; + } + virtual const atom_collection<UndefinedAtom>& undefined() const { + return _undefinedAtoms; + } + virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const { + return _sharedLibraryAtoms; + } + virtual const atom_collection<AbsoluteAtom>& absolute() const { + return _absoluteAtoms; + } + +private: + atom_collection_vector<DefinedAtom> _definedAtoms; + atom_collection_vector<UndefinedAtom> _undefinedAtoms; + atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; + atom_collection_vector<AbsoluteAtom> _absoluteAtoms; +}; + + + +struct TestingKindMapping { + const char* string; + Reference::Kind value; + bool isBranch; + bool isGotLoad; + bool isGotUse; +}; + +// +// Table of fixup kinds in YAML documents used for testing +// +const TestingKindMapping sKinds[] = { + { "call32", 1, true, false, false}, + { "pcrel32", 2, false, false, false }, + { "gotLoad32", 3, false, true, true }, + { "gotUse32", 4, false, false, true }, + { "lea32wasGot", 5, false, false, false }, + { nullptr, 0, false, false, false } + }; + + + +class TestingStubsPass : public StubsPass { +public: + virtual bool noTextRelocs() { + return true; + } + + virtual bool isCallSite(Reference::Kind kind) { + for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) { + if ( kind == p->value ) + return p->isBranch; + } + return false; + } + + virtual const DefinedAtom* getStub(const Atom& target) { + const DefinedAtom *result = new TestingStubAtom(_file, target); + _file.addAtom(*result); + return result; + } + + + virtual void addStubAtoms(File &mergedFile) { + for (const DefinedAtom *stub : _file.defined() ) { + mergedFile.addAtom(*stub); + } + } + +private: + TestingPassFile _file; +}; + + + +class TestingGOTPass : public GOTPass { +public: + virtual bool noTextRelocs() { + return true; + } + + virtual bool isGOTAccess(Reference::Kind kind, bool &canBypassGOT) { + for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) { + if ( kind == p->value ) { + canBypassGOT = p->isGotLoad; + return (p->isGotUse || p->isGotLoad); + } + } + return false; + } + + virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) { + if ( targetIsNowGOT ) + (const_cast<Reference*>(ref))->setKind(2); // pcrel32 + else + (const_cast<Reference*>(ref))->setKind(5); // lea32wasGot + } + + virtual const DefinedAtom* makeGOTEntry(const Atom &target) { + return new TestingGOTAtom(_file, target); + } + +private: + TestingPassFile _file; +}; + + +class TestingWriterOptionsYAML : public lld::WriterOptionsYAML { +public: + TestingWriterOptionsYAML(bool stubs, bool got) + : _doStubs(stubs), _doGOT(got) { + } + + virtual StubsPass *stubPass() const { + if ( _doStubs ) + return const_cast<TestingStubsPass*>(&_stubsPass); + else + return nullptr; + } + + virtual GOTPass *gotPass() const { + if ( _doGOT ) + return const_cast<TestingGOTPass*>(&_gotPass); + else + return nullptr; + } + + virtual StringRef kindToString(Reference::Kind value) const { + for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) { + if ( value == p->value) + return p->string; + } + return StringRef("???"); + } +private: + bool _doStubs; + bool _doGOT; + TestingStubsPass _stubsPass; + TestingGOTPass _gotPass; +}; + + +class TestingReaderOptionsYAML : public lld::ReaderOptionsYAML { + virtual Reference::Kind kindFromString(StringRef kindName) const { + for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) { + if ( kindName.equals(p->string) ) + return p->value; + } + int k; + if (kindName.getAsInteger(0, k)) + k = 0; + return k; + } +}; + + + +#endif // LLD_TOOLS_TESTING_HELPERS_H_ diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp index 229ed868614..37e69cdca47 100644 --- a/lld/tools/lld-core/lld-core.cpp +++ b/lld/tools/lld-core/lld-core.cpp @@ -9,13 +9,17 @@ #include "lld/Core/Atom.h" #include "lld/Core/LLVM.h" -#include "lld/Core/NativeReader.h" -#include "lld/Core/NativeWriter.h" #include "lld/Core/Pass.h" #include "lld/Core/Resolver.h" -#include "lld/Core/YamlReader.h" -#include "lld/Core/YamlWriter.h" -#include "lld/Reader/Reader.h" +#include "lld/ReaderWriter/Reader.h" +#include "lld/ReaderWriter/ReaderNative.h" +#include "lld/ReaderWriter/ReaderYAML.h" +#include "lld/ReaderWriter/Writer.h" +#include "lld/ReaderWriter/WriterELF.h" +#include "lld/ReaderWriter/WriterMachO.h" +#include "lld/ReaderWriter/WriterNative.h" +#include "lld/ReaderWriter/WriterPECOFF.h" +#include "lld/ReaderWriter/WriterYAML.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/CommandLine.h" @@ -29,6 +33,8 @@ #include <vector> +#include "TestingHelpers.hpp" + using namespace lld; static void error(Twine message) { @@ -43,311 +49,6 @@ static bool error(error_code ec) { return false; } -namespace { - - -// -// Simple atom created by the stubs pass. -// -class TestingStubAtom : public DefinedAtom { -public: - TestingStubAtom(const File& f, const Atom& shlib) : - _file(f), _shlib(shlib) { - static uint32_t lastOrdinal = 0; - _ordinal = lastOrdinal++; - } - - virtual const File& file() const { - return _file; - } - - virtual StringRef name() const { - return StringRef(); - } - - virtual uint64_t ordinal() const { - return _ordinal; - } - - virtual uint64_t size() const { - return 0; - } - - virtual Scope scope() const { - return DefinedAtom::scopeLinkageUnit; - } - - virtual Interposable interposable() const { - return DefinedAtom::interposeNo; - } - - virtual Merge merge() const { - return DefinedAtom::mergeNo; - } - - virtual ContentType contentType() const { - return DefinedAtom::typeStub; - } - - virtual Alignment alignment() const { - return Alignment(0,0); - } - - virtual SectionChoice sectionChoice() const { - return DefinedAtom::sectionBasedOnContent; - } - - virtual StringRef customSectionName() const { - return StringRef(); - } - virtual DeadStripKind deadStrip() const { - return DefinedAtom::deadStripNormal; - } - - virtual ContentPermissions permissions() const { - return DefinedAtom::permR_X; - } - - virtual bool isThumb() const { - return false; - } - - virtual bool isAlias() const { - return false; - } - - virtual ArrayRef<uint8_t> rawContent() const { - return ArrayRef<uint8_t>(); - } - - virtual reference_iterator begin() const { - return reference_iterator(*this, nullptr); - } - - virtual reference_iterator end() const { - return reference_iterator(*this, nullptr); - } - - virtual const Reference* derefIterator(const void* iter) const { - return nullptr; - } - - virtual void incrementIterator(const void*& iter) const { - - } - -private: - const File& _file; - const Atom& _shlib; - uint32_t _ordinal; -}; - - - - -// -// Simple atom created by the GOT pass. -// -class TestingGOTAtom : public DefinedAtom { -public: - TestingGOTAtom(const File& f, const Atom& shlib) : - _file(f), _shlib(shlib) { - static uint32_t lastOrdinal = 0; - _ordinal = lastOrdinal++; - } - - virtual const File& file() const { - return _file; - } - - virtual StringRef name() const { - return StringRef(); - } - - virtual uint64_t ordinal() const { - return _ordinal; - } - - virtual uint64_t size() const { - return 0; - } - - virtual Scope scope() const { - return DefinedAtom::scopeLinkageUnit; - } - - virtual Interposable interposable() const { - return DefinedAtom::interposeNo; - } - - virtual Merge merge() const { - return DefinedAtom::mergeNo; - } - - virtual ContentType contentType() const { - return DefinedAtom::typeGOT; - } - - virtual Alignment alignment() const { - return Alignment(3,0); - } - - virtual SectionChoice sectionChoice() const { - return DefinedAtom::sectionBasedOnContent; - } - - virtual StringRef customSectionName() const { - return StringRef(); - } - virtual DeadStripKind deadStrip() const { - return DefinedAtom::deadStripNormal; - } - - virtual ContentPermissions permissions() const { - return DefinedAtom::permRW_; - } - - virtual bool isThumb() const { - return false; - } - - virtual bool isAlias() const { - return false; - } - - virtual ArrayRef<uint8_t> rawContent() const { - return ArrayRef<uint8_t>(); - } - - virtual reference_iterator begin() const { - return reference_iterator(*this, nullptr); - } - - virtual reference_iterator end() const { - return reference_iterator(*this, nullptr); - } - - virtual const Reference* derefIterator(const void* iter) const { - return nullptr; - } - - virtual void incrementIterator(const void*& iter) const { - - } - -private: - const File& _file; - const Atom& _shlib; - uint32_t _ordinal; -}; - -// -// A simple platform for testing. -// -class TestingPlatform : public Platform { -public: - - virtual void addFiles(InputFiles&) { - } - - struct KindMapping { - const char* string; - Reference::Kind value; - bool isBranch; - bool isGotLoad; - bool isGotUse; - }; - - static const KindMapping _s_kindMappings[]; - - virtual Reference::Kind kindFromString(StringRef kindName) { - for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) { - if ( kindName.equals(p->string) ) - return p->value; - } - int k; - if (kindName.getAsInteger(0, k)) - k = 0; - return k; - } - - virtual StringRef kindToString(Reference::Kind value) { - for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) { - if ( value == p->value) - return p->string; - } - return StringRef("???"); - } - - virtual bool noTextRelocs() { - return true; - } - - virtual bool isCallSite(Reference::Kind kind) { - for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) { - if ( kind == p->value ) - return p->isBranch; - } - return false; - } - - virtual bool isGOTAccess(Reference::Kind kind, bool& canBypassGOT) { - for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) { - if ( kind == p->value ) { - canBypassGOT = p->isGotLoad; - return p->isGotUse; - } - } - return false; - } - - virtual void updateReferenceToGOT(const Reference* ref, bool targetIsNowGOT) { - if ( targetIsNowGOT ) - (const_cast<Reference*>(ref))->setKind(kindFromString("pcrel32")); - else - (const_cast<Reference*>(ref))->setKind(kindFromString("lea32wasGot")); - } - - - - virtual const DefinedAtom *getStub(const Atom& shlibAtom, File& file) { - const DefinedAtom *result = new TestingStubAtom(file, shlibAtom); - _stubs.push_back(result); - return result; - } - - virtual const DefinedAtom* makeGOTEntry(const Atom& shlibAtom, File& file) { - return new TestingGOTAtom(file, shlibAtom); - } - - virtual void addStubAtoms(File &file) { - for (const DefinedAtom *stub : _stubs) { - file.addAtom(*stub); - } - } - - virtual void writeExecutable(const lld::File &, raw_ostream &out) { - } -private: - std::vector<const DefinedAtom*> _stubs; -}; - - -// -// Table of fixup kinds in YAML documents used for testing -// -const TestingPlatform::KindMapping TestingPlatform::_s_kindMappings[] = { - { "call32", 1, true, false, false}, - { "pcrel32", 2, false, false, false }, - { "gotLoad32", 3, false, true, true }, - { "gotUse32", 4, false, false, true }, - { "lea32wasGot", 5, false, false, false }, - { nullptr, 0, false, false, false } - }; - - -} // anon namespace - llvm::cl::list<std::string> cmdLineInputFilePaths(llvm::cl::Positional, @@ -383,16 +84,18 @@ cmdLineGlobalsNotDeadStrip("keep-globals", llvm::cl::desc("All global symbols are roots for dead-strip")); -enum PlatformChoice { - platformTesting, platformDarwin +enum WriteChoice { + writeYAML, writeMachO, writePECOFF, writeELF }; -llvm::cl::opt<PlatformChoice> -platformSelected("platform", - llvm::cl::desc("Select platform"), +llvm::cl::opt<WriteChoice> +writeSelected("writer", + llvm::cl::desc("Select writer"), llvm::cl::values( - clEnumValN(platformTesting, "none", "link for testing"), - clEnumValN(platformDarwin, "darwin", "link as darwin would"), + clEnumValN(writeYAML, "YAML", "link assuming YAML format"), + clEnumValN(writeMachO, "mach-o", "link as darwin would"), + clEnumValN(writePECOFF, "PECOFF", "link as windows would"), + clEnumValN(writeELF, "ELF", "link as linux would"), clEnumValEnd)); @@ -410,8 +113,6 @@ public: - - int main(int argc, char *argv[]) { // Print a stack trace if we signal out. llvm::sys::PrintStackTraceOnErrorSignal(); @@ -421,108 +122,97 @@ int main(int argc, char *argv[]) { // parse options llvm::cl::ParseCommandLineOptions(argc, argv); + // if no input file specified, read from stdin if (cmdLineInputFilePaths.empty()) cmdLineInputFilePaths.emplace_back("-"); - // create platform for testing - Platform* platform = nullptr; - switch ( platformSelected ) { - case platformTesting: - platform = new TestingPlatform(); + // if no output path specified, write to stdout + if (cmdLineOutputFilePath.empty()) + cmdLineOutputFilePath.assign("-"); + + // create writer for final output + TestingWriterOptionsYAML writerOptionsYAML(cmdLineDoStubsPass, + cmdLineDoGotPass); + WriterOptionsMachO writerOptionsMachO; + WriterOptionsPECOFF writerOptionsPECOFF; + WriterOptionsELF writerOptionsELF; + Writer* writer = nullptr; + switch ( writeSelected ) { + case writeYAML: + writer = createWriterYAML(writerOptionsYAML); + break; + case writeMachO: + writer = createWriterMachO(writerOptionsMachO); + break; + case writePECOFF: + writer = createWriterPECOFF(writerOptionsPECOFF); break; - case platformDarwin: - platform = createDarwinPlatform(); + case writeELF: + writer = createWriterELF(writerOptionsELF); break; } - // read input YAML doc into object file(s) - std::vector<std::unique_ptr<const File>> files; + // create object to mange input files + InputFiles inputFiles; + + // read input files into in-memory File objects + TestingReaderOptionsYAML readerOptionsYAML; + Reader *reader = createReaderYAML(readerOptionsYAML); for (auto path : cmdLineInputFilePaths) { - OwningPtr<llvm::MemoryBuffer> ofile; - if (error(llvm::MemoryBuffer::getFileOrSTDIN(path, ofile))) + std::vector<std::unique_ptr<File>> files; + if ( error(reader->readFile(path, files)) ) return 1; - std::unique_ptr<llvm::MemoryBuffer> file(ofile.take()); - if (llvm::sys::fs::identify_magic(file->getBuffer()) - == llvm::sys::fs::file_magic::coff_object) { - std::unique_ptr<File> f; - if (error(parseCOFFObjectFile(std::move(file), f))) - return 1; - files.push_back(std::move(f)); - } else { - if (error(yaml::parseObjectText( file.release() - , *platform - , files))) - return 1; - } + inputFiles.appendFiles(files); } + + // given writer a chance to add files + writer->addFiles(inputFiles); // create options for resolving TestingResolverOptions options; - // create object to mange input files - InputFiles inputFiles; - for (const auto &file : files) { - inputFiles.appendFile(*file); - } - - platform->addFiles(inputFiles); - // merge all atom graphs Resolver resolver(options, inputFiles); resolver.resolve(); + File &mergedMasterFile = resolver.resultFile(); // run passes - if ( cmdLineDoGotPass ) { - GOTPass addGot(resolver.resultFile(), *platform); - addGot.perform(); + if ( GOTPass *pass = writer->gotPass() ) { + pass->perform(mergedMasterFile); } - if ( cmdLineDoStubsPass ) { - StubsPass addStubs(resolver.resultFile(), *platform); - addStubs.perform(); + if ( StubsPass *pass = writer->stubPass() ) { + pass->perform(mergedMasterFile); } - -// yaml::writeObjectText(resolver.resultFile(), *platform, llvm::errs()); + // showing yaml at this stage can help when debugging + const bool dumpIntermediateYAML = false; + if ( dumpIntermediateYAML ) + writer->writeFile(mergedMasterFile, "-"); - // make unique temp .o file to put generated object file - int fd; - SmallString<128> tempPath; - llvm::sys::fs::unique_file("temp%%%%%.o", fd, tempPath); - llvm::raw_fd_ostream binaryOut(fd, /*shouldClose=*/true); + // make unique temp file to put generated native object file + llvm::sys::Path tmpNativePath = llvm::sys::Path::GetTemporaryDirectory(); + if (tmpNativePath.createTemporaryFileOnDisk()) { + error("createTemporaryFileOnDisk() failed"); + return 1; + } - // write native file - writeNativeObjectFile(resolver.resultFile(), binaryOut); - binaryOut.close(); // manually close so that file can be read next - -// out << "native file: " << tempPath.str() << "\n"; + // write as native file + WriterOptionsNative optionsNativeWriter; + Writer *natWriter = createWriterNative(optionsNativeWriter); + if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str()))) + return 1; - // read native file - std::unique_ptr<lld::File> natFile; - if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) ) + // read as native file + ReaderOptionsNative optionsNativeReader; + Reader *natReader = createReaderNative(optionsNativeReader); + std::vector<std::unique_ptr<File>> readNativeFiles; + if (error(natReader->readFile(tmpNativePath.c_str(), readNativeFiles))) return 1; - - // write new atom graph - std::string errorInfo; - const char* outPath = (cmdLineOutputFilePath.empty() ? "-" - : cmdLineOutputFilePath.c_str()); - llvm::raw_fd_ostream out(outPath, errorInfo); - if ( platformSelected == platformTesting) { - // write atom graph out as YAML doc - yaml::writeObjectText(resolver.resultFile() /* *natFile */, *platform, out); - } - else { - // write atom graph as an executable - platform->writeExecutable(resolver.resultFile() /* *natFile */, out); - // HACK. I don't see any way to set the 'executable' bit on files - // in raw_fd_ostream or in llvm/Support. -#if HAVE_SYS_STAT_H - ::chmod(outPath, 0777); -#endif - } - - // delete temp .o file - bool existed; - llvm::sys::fs::remove(tempPath.str(), existed); + // write new atom graph + const File *parsedNativeFile = readNativeFiles[0].get(); + if (error(writer->writeFile(*parsedNativeFile, cmdLineOutputFilePath))) + return 1; + return 0; } |

