diff options
| -rw-r--r-- | lld/include/lld/Driver/WinLinkModuleDef.h | 21 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 3 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkModuleDef.cpp | 25 | ||||
| -rw-r--r-- | lld/unittests/DriverTests/WinLinkModuleDefTest.cpp | 20 |
4 files changed, 68 insertions, 1 deletions
diff --git a/lld/include/lld/Driver/WinLinkModuleDef.h b/lld/include/lld/Driver/WinLinkModuleDef.h index 5dc362f3254..030305717e2 100644 --- a/lld/include/lld/Driver/WinLinkModuleDef.h +++ b/lld/include/lld/Driver/WinLinkModuleDef.h @@ -35,6 +35,7 @@ enum class Kind { kw_heapsize, kw_name, kw_noname, + kw_version, }; class Token { @@ -62,7 +63,7 @@ private: class Directive { public: - enum class Kind { exports, heapsize, name }; + enum class Kind { exports, heapsize, name, version }; Kind getKind() const { return _kind; } virtual ~Directive() {} @@ -125,6 +126,23 @@ private: const uint64_t _baseaddr; }; +class Version : public Directive { +public: + explicit Version(int major, int minor) + : Directive(Kind::version), _major(major), _minor(minor) {} + + static bool classof(const Directive *dir) { + return dir->getKind() == Kind::version; + } + + int getMajorVersion() const { return _major; } + int getMinorVersion() const { return _minor; } + +private: + const int _major; + const int _minor; +}; + class Parser { public: explicit Parser(Lexer &lex, llvm::BumpPtrAllocator &alloc) @@ -143,6 +161,7 @@ private: bool parseExport(PECOFFLinkingContext::ExportDesc &result); bool parseHeapsize(uint64_t &reserve, uint64_t &commit); bool parseName(std::string &outfile, uint64_t &baseaddr); + bool parseVersion(int &major, int &minor); Lexer &_lex; llvm::BumpPtrAllocator &_alloc; diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index a65e9f039e4..39643379d78 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -948,6 +948,9 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx, ctx.setOutputPath(ctx.allocate(name->getOutputPath())); if (name->getBaseAddress() && ctx.getBaseAddress()) ctx.setBaseAddress(name->getBaseAddress()); + } else if (auto *ver = dyn_cast<moduledef::Version>(dir.getValue())) { + ctx.setImageVersion(PECOFFLinkingContext::Version( + ver->getMajorVersion(), ver->getMinorVersion())); } 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 dd71b8508a1..bc18609b821 100644 --- a/lld/lib/Driver/WinLinkModuleDef.cpp +++ b/lld/lib/Driver/WinLinkModuleDef.cpp @@ -54,6 +54,7 @@ Token Lexer::lex() { .Case("HEAPSIZE", Kind::kw_heapsize) .Case("NAME", Kind::kw_name) .Case("NONAME", Kind::kw_noname) + .Case("VERSION", Kind::kw_version) .Default(Kind::identifier); _buffer = (end == _buffer.npos) ? "" : _buffer.drop_front(end); return Token(kind, word); @@ -129,6 +130,13 @@ llvm::Optional<Directive *> Parser::parse() { return llvm::None; return new (_alloc) Name(outputPath, baseaddr); } + // VERSION + if (_tok._kind == Kind::kw_version) { + int major, minor; + if (!parseVersion(major, minor)) + return llvm::None; + return new (_alloc) Version(major, minor); + } error(_tok, Twine("Unknown directive: ") + _tok._range); return llvm::None; } @@ -199,5 +207,22 @@ bool Parser::parseName(std::string &outputPath, uint64_t &baseaddr) { return true; } +// VERSION major[.minor] +bool Parser::parseVersion(int &major, int &minor) { + consumeToken(); + if (_tok._kind != Kind::identifier) + return false; + StringRef v1, v2; + llvm::tie(v1, v2) = _tok._range.split('.'); + if (v1.getAsInteger(10, major)) + return false; + if (v2.empty()) { + minor = 0; + } else if (v2.getAsInteger(10, minor)) { + return false; + } + return true; +} + } // moddef } // namespace lld diff --git a/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp b/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp index a7a0cea7c47..a38827a4a32 100644 --- a/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp +++ b/lld/unittests/DriverTests/WinLinkModuleDefTest.cpp @@ -107,3 +107,23 @@ TEST_F(ParserTest, Name2) { EXPECT_EQ("foo.exe", name->getOutputPath()); EXPECT_EQ(4096U, name->getBaseAddress()); } + +TEST_F(ParserTest, Version1) { + llvm::BumpPtrAllocator alloc; + llvm::Optional<moduledef::Directive *> dir = parse("VERSION 12", alloc); + EXPECT_TRUE(dir.hasValue()); + auto *ver = dyn_cast<moduledef::Version>(dir.getValue()); + EXPECT_TRUE(ver != nullptr); + EXPECT_EQ(12, ver->getMajorVersion()); + EXPECT_EQ(0, ver->getMinorVersion()); +} + +TEST_F(ParserTest, Version2) { + llvm::BumpPtrAllocator alloc; + llvm::Optional<moduledef::Directive *> dir = parse("VERSION 12.34", alloc); + EXPECT_TRUE(dir.hasValue()); + auto *ver = dyn_cast<moduledef::Version>(dir.getValue()); + EXPECT_TRUE(ver != nullptr); + EXPECT_EQ(12, ver->getMajorVersion()); + EXPECT_EQ(34, ver->getMinorVersion()); +} |

