diff options
| -rw-r--r-- | lld/include/lld/Driver/WinLinkModuleDef.h | 24 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 5 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkModuleDef.cpp | 42 | ||||
| -rw-r--r-- | lld/unittests/DriverTests/WinLinkModuleDefTest.cpp | 20 |
4 files changed, 90 insertions, 1 deletions
diff --git a/lld/include/lld/Driver/WinLinkModuleDef.h b/lld/include/lld/Driver/WinLinkModuleDef.h index f0a38f77cfe..5dc362f3254 100644 --- a/lld/include/lld/Driver/WinLinkModuleDef.h +++ b/lld/include/lld/Driver/WinLinkModuleDef.h @@ -29,9 +29,11 @@ enum class Kind { identifier, comma, equal, + kw_base, kw_data, kw_exports, kw_heapsize, + kw_name, kw_noname, }; @@ -60,7 +62,7 @@ private: class Directive { public: - enum class Kind { exports, heapsize }; + enum class Kind { exports, heapsize, name }; Kind getKind() const { return _kind; } virtual ~Directive() {} @@ -106,6 +108,23 @@ private: const uint64_t _commit; }; +class Name : public Directive { +public: + explicit Name(StringRef outputPath, uint64_t baseaddr) + : Directive(Kind::name), _outputPath(outputPath), _baseaddr(baseaddr) {} + + static bool classof(const Directive *dir) { + return dir->getKind() == Kind::name; + } + + StringRef getOutputPath() const { return _outputPath; } + uint64_t getBaseAddress() const { return _baseaddr; } + +private: + const std::string _outputPath; + const uint64_t _baseaddr; +}; + class Parser { public: explicit Parser(Lexer &lex, llvm::BumpPtrAllocator &alloc) @@ -116,11 +135,14 @@ public: private: void consumeToken(); bool consumeTokenAsInt(uint64_t &result); + bool expectAndConsume(Kind kind, Twine msg); + void ungetToken(); void error(const Token &tok, Twine msg); bool parseExport(PECOFFLinkingContext::ExportDesc &result); bool parseHeapsize(uint64_t &reserve, uint64_t &commit); + bool parseName(std::string &outfile, uint64_t &baseaddr); Lexer &_lex; llvm::BumpPtrAllocator &_alloc; diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 5224124a6d4..fe57d34db25 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -935,6 +935,11 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx, } else if (auto *hs = dyn_cast<moduledef::Heapsize>(dir.getValue())) { ctx.setHeapReserve(hs->getReserve()); ctx.setHeapCommit(hs->getCommit()); + } else if (auto *name = dyn_cast<moduledef::Name>(dir.getValue())) { + if (!name->getOutputPath().empty() && ctx.outputPath().empty()) + ctx.setOutputPath(ctx.allocate(name->getOutputPath())); + if (name->getBaseAddress() && ctx.getBaseAddress()) + ctx.setBaseAddress(name->getBaseAddress()); } else { llvm::dbgs() << static_cast<int>(dir.getValue()->getKind()) << "\n"; llvm_unreachable("Unknown module-definition directive.\n"); diff --git a/lld/lib/Driver/WinLinkModuleDef.cpp b/lld/lib/Driver/WinLinkModuleDef.cpp index 7ca70efb4b4..dd71b8508a1 100644 --- a/lld/lib/Driver/WinLinkModuleDef.cpp +++ b/lld/lib/Driver/WinLinkModuleDef.cpp @@ -48,9 +48,11 @@ Token Lexer::lex() { "0123456789_.*~+!@#$%^&*()/"); StringRef word = _buffer.substr(0, end); Kind kind = llvm::StringSwitch<Kind>(word) + .Case("BASE", Kind::kw_base) .Case("DATA", Kind::kw_data) .Case("EXPORTS", Kind::kw_exports) .Case("HEAPSIZE", Kind::kw_heapsize) + .Case("NAME", Kind::kw_name) .Case("NONAME", Kind::kw_noname) .Default(Kind::identifier); _buffer = (end == _buffer.npos) ? "" : _buffer.drop_front(end); @@ -82,6 +84,15 @@ bool Parser::consumeTokenAsInt(uint64_t &result) { return true; } +bool Parser::expectAndConsume(Kind kind, Twine msg) { + consumeToken(); + if (_tok._kind != kind) { + error(_tok, msg); + return false; + } + return true; +} + void Parser::ungetToken() { _tokBuf.push_back(_tok); } void Parser::error(const Token &tok, Twine msg) { @@ -92,6 +103,7 @@ void Parser::error(const Token &tok, Twine msg) { llvm::Optional<Directive *> Parser::parse() { consumeToken(); + // EXPORTS if (_tok._kind == Kind::kw_exports) { std::vector<PECOFFLinkingContext::ExportDesc> exports; for (;;) { @@ -102,12 +114,21 @@ llvm::Optional<Directive *> Parser::parse() { } return new (_alloc) Exports(exports); } + // HEAPSIZE if (_tok._kind == Kind::kw_heapsize) { uint64_t reserve, commit; if (!parseHeapsize(reserve, commit)) return llvm::None; return new (_alloc) Heapsize(reserve, commit); } + // NAME + if (_tok._kind == Kind::kw_name) { + std::string outputPath; + uint64_t baseaddr; + if (!parseName(outputPath, baseaddr)) + return llvm::None; + return new (_alloc) Name(outputPath, baseaddr); + } error(_tok, Twine("Unknown directive: ") + _tok._range); return llvm::None; } @@ -141,6 +162,7 @@ bool Parser::parseExport(PECOFFLinkingContext::ExportDesc &result) { } } +// HEAPSIZE reserve [, commit] bool Parser::parseHeapsize(uint64_t &reserve, uint64_t &commit) { if (!consumeTokenAsInt(reserve)) return false; @@ -157,5 +179,25 @@ bool Parser::parseHeapsize(uint64_t &reserve, uint64_t &commit) { return true; } +// NAME [outputPath] [BASE=address] +bool Parser::parseName(std::string &outputPath, uint64_t &baseaddr) { + consumeToken(); + if (_tok._kind == Kind::identifier) { + outputPath = _tok._range; + consumeToken(); + } else { + outputPath = ""; + } + if (_tok._kind == Kind::kw_base) { + if (!expectAndConsume(Kind::equal, "'=' expected")) + return false; + if (!consumeTokenAsInt(baseaddr)) + return false; + } else { + baseaddr = 0; + } + return true; +} + } // moddef } // namespace lld diff --git a/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp b/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp index b4f1b5263c4..a7a0cea7c47 100644 --- a/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp +++ b/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp @@ -87,3 +87,23 @@ TEST_F(ParserTest, Heapsize2) { EXPECT_EQ(65536U, heapsize->getReserve()); EXPECT_EQ(8192U, heapsize->getCommit()); } + +TEST_F(ParserTest, Name1) { + llvm::BumpPtrAllocator alloc; + llvm::Optional<moduledef::Directive *> dir = parse("NAME foo.exe", alloc); + EXPECT_TRUE(dir.hasValue()); + auto *name = dyn_cast<moduledef::Name>(dir.getValue()); + EXPECT_TRUE(name != nullptr); + EXPECT_EQ("foo.exe", name->getOutputPath()); + EXPECT_EQ(0U, name->getBaseAddress()); +} + +TEST_F(ParserTest, Name2) { + llvm::BumpPtrAllocator alloc; + llvm::Optional<moduledef::Directive *> dir = parse("NAME foo.exe BASE=4096", alloc); + EXPECT_TRUE(dir.hasValue()); + auto *name = dyn_cast<moduledef::Name>(dir.getValue()); + EXPECT_TRUE(name != nullptr); + EXPECT_EQ("foo.exe", name->getOutputPath()); + EXPECT_EQ(4096U, name->getBaseAddress()); +} |

