diff options
-rw-r--r-- | lld/include/lld/ReaderWriter/LinkerScript.h | 26 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/LinkerScript.cpp | 42 | ||||
-rw-r--r-- | lld/test/LinkerScript/linker-script-outputformat.test | 12 | ||||
-rw-r--r-- | lld/test/LinkerScript/linker-script.test (renamed from lld/test/linker-script.test) | 10 |
4 files changed, 79 insertions, 11 deletions
diff --git a/lld/include/lld/ReaderWriter/LinkerScript.h b/lld/include/lld/ReaderWriter/LinkerScript.h index b170dd27a34..ecd9e4793d3 100644 --- a/lld/include/lld/ReaderWriter/LinkerScript.h +++ b/lld/include/lld/ReaderWriter/LinkerScript.h @@ -16,6 +16,7 @@ #define LLD_READER_WRITER_LINKER_SCRIPT_H #include "lld/Core/LLVM.h" +#include "lld/Core/range.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringSwitch.h" @@ -25,6 +26,8 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/system_error.h" +#include <vector> + namespace lld { namespace script { class Token { @@ -33,6 +36,8 @@ public: unknown, eof, identifier, + comma, + quotedString, l_paren, r_paren, kw_entry, @@ -93,21 +98,30 @@ private: class OutputFormat : public Command { public: - explicit OutputFormat(StringRef format) - : Command(Kind::OutputFormat), _format(format) {} + explicit OutputFormat(StringRef format) : Command(Kind::OutputFormat) { + _formats.push_back(format); + } static bool classof(const Command *c) { return c->getKind() == Kind::OutputFormat; } virtual void dump(raw_ostream &os) const { - os << "OUTPUT_FORMAT(" << getFormat() << ")\n"; + os << "OUTPUT_FORMAT("; + for (auto fb = _formats.begin(), fe = _formats.end(); fb != fe; ++fb) { + if (fb != _formats.begin()) + os << ","; + os << *fb; + } + os << ")\n"; } - StringRef getFormat() const { return _format; } + virtual void addOutputFormat(StringRef format) { _formats.push_back(format); } + + range<StringRef *> getFormats() { return _formats; } private: - StringRef _format; + std::vector<StringRef> _formats; }; class OutputArch : public Command { @@ -227,6 +241,8 @@ private: return true; } + bool isNextToken(Token::Kind kind) { return (_tok._kind == kind); } + OutputFormat *parseOutputFormat(); OutputArch *parseOutputArch(); Group *parseGroup(); diff --git a/lld/lib/ReaderWriter/LinkerScript.cpp b/lld/lib/ReaderWriter/LinkerScript.cpp index eba35b9f33e..064f6c9ecfb 100644 --- a/lld/lib/ReaderWriter/LinkerScript.cpp +++ b/lld/lib/ReaderWriter/LinkerScript.cpp @@ -29,6 +29,8 @@ void Token::dump(raw_ostream &os) const { CASE(kw_group) CASE(kw_output_format) CASE(kw_output_arch) + CASE(quotedString) + CASE(comma) CASE(l_paren) CASE(r_paren) CASE(unknown) @@ -67,7 +69,12 @@ bool Lexer::canContinueName(char c) const { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '_': case '.': case '$': case '/': case '\\': case '~': case '=': - case '+': case ',': case '[': case ']': case '*': case '?': case '-': + case '+': + case '[': + case ']': + case '*': + case '?': + case '-': case ':': return true; default: @@ -94,7 +101,23 @@ void Lexer::lex(Token &tok) { tok = Token(_buffer.substr(0, 1), Token::r_paren); _buffer = _buffer.drop_front(); return; + case ',': + tok = Token(_buffer.substr(0, 1), Token::comma); + _buffer = _buffer.drop_front(); + return; default: + // Quoted strings ? + if ((_buffer[0] == '\"') || (_buffer[0] == '\'')) { + char c = _buffer[0]; + _buffer = _buffer.drop_front(); + auto quotedStringEnd = _buffer.find(c); + if (quotedStringEnd == StringRef::npos || quotedStringEnd == 0) + break; + StringRef word = _buffer.substr(0, quotedStringEnd); + tok = Token(word, Token::quotedString); + _buffer = _buffer.drop_front(quotedStringEnd + 1); + return; + } /// keyword or identifer. if (!canStartName(_buffer[0])) break; @@ -215,14 +238,27 @@ OutputFormat *Parser::parseOutputFormat() { if (!expectAndConsume(Token::l_paren, "expected (")) return nullptr; - if (_tok._kind != Token::identifier) { - error(_tok, "Expected identifier in OUTPUT_FORMAT."); + if (_tok._kind != Token::quotedString && _tok._kind != Token::identifier) { + error(_tok, "Expected identifier/string in OUTPUT_FORMAT."); return nullptr; } auto ret = new (_alloc) OutputFormat(_tok._range); consumeToken(); + do { + if (isNextToken(Token::comma)) + consumeToken(); + else + break; + if (_tok._kind != Token::quotedString && _tok._kind != Token::identifier) { + error(_tok, "Expected identifier/string in OUTPUT_FORMAT."); + return nullptr; + } + ret->addOutputFormat(_tok._range); + consumeToken(); + } while (isNextToken(Token::comma)); + if (!expectAndConsume(Token::r_paren, "expected )")) return nullptr; diff --git a/lld/test/LinkerScript/linker-script-outputformat.test b/lld/test/LinkerScript/linker-script-outputformat.test new file mode 100644 index 00000000000..10b6bd33653 --- /dev/null +++ b/lld/test/LinkerScript/linker-script-outputformat.test @@ -0,0 +1,12 @@ +/* RUN: linker-script-test %s | FileCheck %s +*/ + +OUTPUT_FORMAT(elf64-x86-64) + +/* +CHECK: kw_output_format: OUTPUT_FORMAT +CHECK: l_paren: ( +CHECK: identifier: elf64-x86-64 +CHECK: r_paren: ) +CHECK: OUTPUT_FORMAT(elf64-x86-64) +*/ diff --git a/lld/test/linker-script.test b/lld/test/LinkerScript/linker-script.test index d8850f13584..59d2a184c64 100644 --- a/lld/test/linker-script.test +++ b/lld/test/LinkerScript/linker-script.test @@ -2,7 +2,7 @@ */ OUTPUT_ARCH(i386:x86_64) -OUTPUT_FORMAT(elf64-x86-64) +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) ) ENTRY(init) @@ -13,7 +13,11 @@ CHECK: identifier: i386:x86_64 CHECK: r_paren: ) CHECK: kw_output_format: OUTPUT_FORMAT CHECK: l_paren: ( -CHECK: identifier: elf64-x86-64 +CHECK: quotedString: elf64-x86-64 +CHECK: comma: , +CHECK: quotedString: elf64-x86-64 +CHECK: comma: , +CHECK: quotedString: elf64-x86-64 CHECK: r_paren: ) CHECK: kw_group: GROUP CHECK: l_paren: ( @@ -29,7 +33,7 @@ CHECK: l_paren: ( CHECK: identifier: init CHECK: r_paren: ) CHECK: eof: -CHECK: OUTPUT_FORMAT(elf64-x86-64) +CHECK: OUTPUT_FORMAT(elf64-x86-64,elf64-x86-64,elf64-x86-64) CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2)) CHECK: ENTRY(init) */ |