diff --git a/include/lld/ReaderWriter/LinkerScript.h b/include/lld/ReaderWriter/LinkerScript.h index be22bf3..3b914c8 100644 --- a/include/lld/ReaderWriter/LinkerScript.h +++ b/include/lld/ReaderWriter/LinkerScript.h @@ -74,6 +74,9 @@ public: kw_group, kw_hidden, kw_keep, + kw_length, + kw_memory, + kw_origin, kw_provide, kw_provide_hidden, kw_only_if_ro, @@ -149,6 +152,7 @@ public: Entry, Group, InputSectionsCmd, + Memory, OutputArch, OutputFormat, OutputSectionDescription, @@ -279,6 +283,30 @@ private: StringRef _entryName; }; +struct MemoryEntry { + MemoryEntry() {} +}; + +/// Represents all the contents of the MEMORY {} construct. +class Memory: public Command { +public: + //explicit Memory() {} + + static bool classof(const Command *c) { + return c->getKind() == Kind::Memory; + } + + void dump(raw_ostream &os) const override { + os << "MEMORY" << "\n"; + } + + StringRef getMemory() const { return _memory; } + +private: + //std::vector ; + StringRef _memory; +}; + class SearchDir : public Command { public: explicit SearchDir(StringRef searchPath) @@ -861,6 +889,12 @@ private: Group *parseGroup(); bool parseAsNeeded(std::vector &paths); + /// Parse Memory entry description. + const MemoryEntry *parseMemoryEntryDescription(); + /// Parse the MEMORY linker script command. + /// Example: XXXFIXME. + Memory *parseMemory(); + /// Parse the ENTRY linker script command. /// Example: /// diff --git a/lib/ReaderWriter/LinkerScript.cpp b/lib/ReaderWriter/LinkerScript.cpp index 3984408..7f46518 100644 --- a/lib/ReaderWriter/LinkerScript.cpp +++ b/lib/ReaderWriter/LinkerScript.cpp @@ -64,11 +64,14 @@ void Token::dump(raw_ostream &os) const { CASE(kw_exclude_file) CASE(kw_group) CASE(kw_hidden) + CASE(kw_length) + CASE(kw_memory) CASE(kw_keep) CASE(kw_provide) CASE(kw_provide_hidden) CASE(kw_only_if_ro) CASE(kw_only_if_rw) + CASE(kw_origin) CASE(kw_output_arch) CASE(kw_output_format) CASE(kw_overlay) @@ -512,9 +515,16 @@ void Lexer::lex(Token &tok) { .Case("EXCLUDE_FILE", Token::kw_exclude_file) .Case("GROUP", Token::kw_group) .Case("HIDDEN", Token::kw_hidden) + .Case("LENGTH", Token::kw_length) + .Case("len", Token::kw_length) + .Case("l", Token::kw_length) + .Case("MEMORY", Token::kw_memory) .Case("KEEP", Token::kw_keep) .Case("ONLY_IF_RO", Token::kw_only_if_ro) .Case("ONLY_IF_RW", Token::kw_only_if_rw) + .Case("ORIGIN", Token::kw_origin) + .Case("org", Token::kw_origin) + .Case("o", Token::kw_origin) .Case("OUTPUT_ARCH", Token::kw_output_arch) .Case("OUTPUT_FORMAT", Token::kw_output_format) .Case("OVERLAY", Token::kw_overlay) @@ -933,6 +943,12 @@ LinkerScript *Parser::parse() { _script._commands.push_back(entry); break; } + case Token::kw_memory: { + Memory *memory = parseMemory(); + if (!memory) + return nullptr; + break; + } case Token::kw_search_dir: { SearchDir *searchDir = parseSearchDir(); if (!searchDir) @@ -1347,6 +1363,70 @@ Entry *Parser::parseEntry() { return new (_alloc) Entry(entryName); } +static StringRef parseAttributes() { + /*XXX: FIXME */ +} + +const MemoryEntry *Parser::parseMemoryEntryDescription() { + consumeToken(); + StringRef regionName = _tok._range; + StringRef attr; + + // Parse attributes. + // XXX: Are attributes always present? + if (!expectAndConsume(Token::l_paren, "expected (")) + return nullptr; + consumeToken(); + // attr = parseAttributes(); XXX:FIXME + if (!expectAndConsume(Token::r_paren, "expected )")) + return nullptr; + + if (!expectAndConsume(Token::colon, "expected :")) + return nullptr; + + // Parse origin + if (!expectAndConsume(Token::kw_origin, "expected ORIGIN/org/o")) + return nullptr; + if (!expectAndConsume(Token::equal, "expected =")) + return nullptr; + if (!expectAndConsume(Token::number, "expected number")) // XXX: CHECKME + return nullptr; + + if (!expectAndConsume(Token::comma, "expected ,")) + return nullptr; + + // Parse length + if (!expectAndConsume(Token::kw_length, "expect LENGTH/len/l")) + return nullptr; + if (!expectAndConsume(Token::equal, "expect =")) + return nullptr; + if (!expectAndConsume(Token::number, "expect number")) + return nullptr; + // XXX: what should origin/length look like? StringRef maybe? + // Add return. +} + +// Parse MEMORY +Memory *Parser::parseMemory() { + assert(_tok._kind == Token::kw_memory && "Expected MEMORY!"); + consumeToken(); + if (!expectAndConsume(Token::l_brace, "expected {")) + return nullptr; + std::vector memoryEntries; + + // Parse one or more memory entires. + // XXX: There could be zero memory ? + do { + if (_tok._kind != Token::identifier) { + error(_tok, "Expected identifier in MEMORY"); + return nullptr; + } + parseMemoryEntryDescription(); + } while (!isNextToken(Token::r_brace)); + if (!expectAndConsume(Token::r_brace, "expected }")) + return nullptr; +} + // Parse SEARCH_DIR(ident) SearchDir *Parser::parseSearchDir() { assert(_tok._kind == Token::kw_search_dir && "Expected SEARCH_DIR!");