summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/ReaderWriter/LinkerScript.h26
-rw-r--r--lld/lib/ReaderWriter/LinkerScript.cpp42
-rw-r--r--lld/test/LinkerScript/linker-script-outputformat.test12
-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)
*/
OpenPOWER on IntegriCloud