[lld] r232110 - LinkerScript: Add parsing of the EXTERN command
Meador Inge
meadori at codesourcery.com
Thu Mar 12 14:55:51 PDT 2015
Author: meadori
Date: Thu Mar 12 16:55:50 2015
New Revision: 232110
URL: http://llvm.org/viewvc/llvm-project?rev=232110&view=rev
Log:
LinkerScript: Add parsing of the EXTERN command
This patch implements parsing of the GNU ld EXTERN command [1].
Evaluation will be added at a later point in time.
[1] https://sourceware.org/binutils/docs/ld/Miscellaneous-Commands.html#Miscellaneous-Commands
Added:
lld/trunk/test/LinkerScript/extern-bad-symbol.test
lld/trunk/test/LinkerScript/extern-empty.test
lld/trunk/test/LinkerScript/extern-valid.test
Modified:
lld/trunk/include/lld/ReaderWriter/LinkerScript.h
lld/trunk/lib/ReaderWriter/LinkerScript.cpp
Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=232110&r1=232109&r2=232110&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Thu Mar 12 16:55:50 2015
@@ -73,6 +73,7 @@ public:
kw_discard,
kw_entry,
kw_exclude_file,
+ kw_extern,
kw_group,
kw_hidden,
kw_input,
@@ -154,6 +155,7 @@ class Command {
public:
enum class Kind {
Entry,
+ Extern,
Group,
Input,
InputSectionsCmd,
@@ -841,6 +843,28 @@ private:
llvm::ArrayRef<const MemoryBlock *> _blocks;
};
+/// Represents an extern command.
+class Extern : public Command {
+public:
+ Extern(Parser &ctx,
+ const SmallVectorImpl<StringRef> &symbols)
+ : Command(ctx, Kind::Extern) {
+ size_t numSymbols = symbols.size();
+ StringRef *symbolsStart =
+ getAllocator().Allocate<StringRef>(numSymbols);
+ std::copy(std::begin(symbols), std::end(symbols), symbolsStart);
+ _symbols = llvm::makeArrayRef(symbolsStart, numSymbols);
+ }
+
+ static bool classof(const Command *c) {
+ return c->getKind() == Kind::Extern;
+ }
+
+ void dump(raw_ostream &os) const override;
+
+private:
+ llvm::ArrayRef<StringRef> _symbols;
+};
/// Stores the parse tree of a linker script.
class LinkerScript {
@@ -1121,6 +1145,14 @@ private:
///
Memory *parseMemory();
+ /// Parse the EXTERN linker script command.
+ /// Example:
+ ///
+ /// EXTERN(symbol symbol ...)
+ /// ^~~~> parseExtern()
+ ///
+ Extern *parseExtern();
+
private:
// Owns the entire linker script AST nodes
llvm::BumpPtrAllocator _alloc;
Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=232110&r1=232109&r2=232110&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Thu Mar 12 16:55:50 2015
@@ -62,6 +62,7 @@ void Token::dump(raw_ostream &os) const
CASE(kw_discard)
CASE(kw_entry)
CASE(kw_exclude_file)
+ CASE(kw_extern)
CASE(kw_group)
CASE(kw_hidden)
CASE(kw_input)
@@ -467,6 +468,7 @@ void Lexer::lex(Token &tok) {
.Case("AT", Token::kw_at)
.Case("ENTRY", Token::kw_entry)
.Case("EXCLUDE_FILE", Token::kw_exclude_file)
+ .Case("EXTERN", Token::kw_extern)
.Case("GROUP", Token::kw_group)
.Case("HIDDEN", Token::kw_hidden)
.Case("INPUT", Token::kw_input)
@@ -952,6 +954,18 @@ void Memory::dump(raw_ostream &os) const
os << "}\n";
}
+// Extern functions
+void Extern::dump(raw_ostream &os) const {
+ os << "EXTERN(";
+ for (unsigned i = 0, e = _symbols.size(); i != e; ++i) {
+ if (i)
+ os << " ";
+ os << _symbols[i];
+ }
+ os << ")\n";
+}
+
+
// Parser functions
std::error_code Parser::parse() {
// Get the first token.
@@ -1041,6 +1055,13 @@ std::error_code Parser::parse() {
_script._commands.push_back(cmd);
break;
}
+ case Token::kw_extern: {
+ const Command *cmd = parseExtern();
+ if (!cmd)
+ return LinkerScriptReaderError::parse_error;
+ _script._commands.push_back(cmd);
+ break;
+ }
default:
// Unexpected.
error(_tok, "expected linker script command");
@@ -2095,5 +2116,30 @@ Memory *Parser::parseMemory() {
return new (_alloc) Memory(*this, blocks);
}
+Extern *Parser::parseExtern() {
+ assert(_tok._kind == Token::kw_extern && "Expected EXTERN!");
+ consumeToken();
+ if (!expectAndConsume(Token::l_paren, "expected ("))
+ return nullptr;
+
+ // Parse one or more symbols.
+ SmallVector<StringRef, 8> symbols;
+ if (_tok._kind != Token::identifier) {
+ error(_tok, "expected one or more symbols in EXTERN.");
+ return nullptr;
+ }
+ symbols.push_back(_tok._range);
+ consumeToken();
+ while (_tok._kind == Token::identifier) {
+ symbols.push_back(_tok._range);
+ consumeToken();
+ }
+
+ if (!expectAndConsume(Token::r_paren, "expected symbol in EXTERN."))
+ return nullptr;
+
+ return new (_alloc) Extern(*this, symbols);
+}
+
} // end namespace script
} // end namespace lld
Added: lld/trunk/test/LinkerScript/extern-bad-symbol.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/extern-bad-symbol.test?rev=232110&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/extern-bad-symbol.test (added)
+++ lld/trunk/test/LinkerScript/extern-bad-symbol.test Thu Mar 12 16:55:50 2015
@@ -0,0 +1,22 @@
+/*
+ RUN: linker-script-test %s 2> %t | FileCheck %s
+ RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
+*/
+
+
+EXTERN(a b 3)
+/*
+CHECK-ERR: [[@LINE-2]]:12: error: expected symbol in EXTERN.
+CHECK-ERR-NEXT: {{^EXTERN\(a b 3\)}}
+CHECK-ERR-NEXT: {{^ \^}}
+*/
+
+/*
+CHECK: kw_extern: EXTERN
+CHECK: l_paren: (
+CHECK: identifier: a
+CHECK: identifier: b
+CHECK: number: 3
+CHECK: r_paren: )
+CHECK: eof:
+*/
Added: lld/trunk/test/LinkerScript/extern-empty.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/extern-empty.test?rev=232110&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/extern-empty.test (added)
+++ lld/trunk/test/LinkerScript/extern-empty.test Thu Mar 12 16:55:50 2015
@@ -0,0 +1,19 @@
+/*
+ RUN: linker-script-test %s 2> %t | FileCheck %s
+ RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
+*/
+
+
+EXTERN()
+/*
+CHECK-ERR: [[@LINE-2]]:8: error: expected one or more symbols in EXTERN.
+CHECK-ERR-NEXT: {{^EXTERN()}}
+CHECK-ERR-NEXT: {{^ \^}}
+*/
+
+/*
+CHECK: kw_extern: EXTERN
+CHECK: l_paren: (
+CHECK: r_paren: )
+CHECK: eof:
+*/
Added: lld/trunk/test/LinkerScript/extern-valid.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/extern-valid.test?rev=232110&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/extern-valid.test (added)
+++ lld/trunk/test/LinkerScript/extern-valid.test Thu Mar 12 16:55:50 2015
@@ -0,0 +1,29 @@
+/*
+ RUN: linker-script-test %s | FileCheck %s
+*/
+
+EXTERN(a)
+EXTERN(a b)
+EXTERN(_foo _bar _baz)
+
+/*
+CHECK: kw_extern: EXTERN
+CHECK: l_paren: (
+CHECK: identifier: a
+CHECK: r_paren: )
+CHECK: kw_extern: EXTERN
+CHECK: l_paren: (
+CHECK: identifier: a
+CHECK: identifier: b
+CHECK: r_paren: )
+CHECK: kw_extern: EXTERN
+CHECK: l_paren: (
+CHECK: identifier: _foo
+CHECK: identifier: _bar
+CHECK: identifier: _baz
+CHECK: r_paren: )
+CHECK: eof:
+CHECK: EXTERN(a)
+CHECK: EXTERN(a b)
+CHECK: EXTERN(_foo _bar _baz)
+*/
More information about the llvm-commits
mailing list