@@ -66,6 +66,9 @@ void Token::dump(raw_ostream &os) const {
66
66
CASE (kw_hidden)
67
67
CASE (kw_input)
68
68
CASE (kw_keep)
69
+ CASE (kw_length)
70
+ CASE (kw_memory)
71
+ CASE (kw_origin)
69
72
CASE (kw_provide)
70
73
CASE (kw_provide_hidden)
71
74
CASE (kw_only_if_ro)
@@ -468,8 +471,15 @@ void Lexer::lex(Token &tok) {
468
471
.Case (" HIDDEN" , Token::kw_hidden)
469
472
.Case (" INPUT" , Token::kw_input)
470
473
.Case (" KEEP" , Token::kw_keep)
474
+ .Case (" LENGTH" , Token::kw_length)
475
+ .Case (" l" , Token::kw_length)
476
+ .Case (" len" , Token::kw_length)
477
+ .Case (" MEMORY" , Token::kw_memory)
471
478
.Case (" ONLY_IF_RO" , Token::kw_only_if_ro)
472
479
.Case (" ONLY_IF_RW" , Token::kw_only_if_rw)
480
+ .Case (" ORIGIN" , Token::kw_origin)
481
+ .Case (" o" , Token::kw_origin)
482
+ .Case (" org" , Token::kw_origin)
473
483
.Case (" OUTPUT" , Token::kw_output)
474
484
.Case (" OUTPUT_ARCH" , Token::kw_output_arch)
475
485
.Case (" OUTPUT_FORMAT" , Token::kw_output_format)
@@ -916,6 +926,32 @@ void Sections::dump(raw_ostream &os) const {
916
926
os << " }\n " ;
917
927
}
918
928
929
+ // Memory functions
930
+ void MemoryBlock::dump (raw_ostream &os) const {
931
+ os << _name;
932
+
933
+ if (!_attr.empty ())
934
+ os << " (" << _attr << " )" ;
935
+
936
+ os << " : " ;
937
+
938
+ os << " ORIGIN = " ;
939
+ _origin->dump (os);
940
+ os << " , " ;
941
+
942
+ os << " LENGTH = " ;
943
+ _length->dump (os);
944
+ }
945
+
946
+ void Memory::dump (raw_ostream &os) const {
947
+ os << " MEMORY\n {\n " ;
948
+ for (auto &block : _blocks) {
949
+ block->dump (os);
950
+ os << " \n " ;
951
+ }
952
+ os << " }\n " ;
953
+ }
954
+
919
955
// Parser functions
920
956
std::error_code Parser::parse () {
921
957
// Get the first token.
@@ -998,6 +1034,13 @@ std::error_code Parser::parse() {
998
1034
_script._commands .push_back (cmd);
999
1035
break ;
1000
1036
}
1037
+ case Token::kw_memory: {
1038
+ const Command *cmd = parseMemory ();
1039
+ if (!cmd)
1040
+ return LinkerScriptReaderError::parse_error;
1041
+ _script._commands .push_back (cmd);
1042
+ break ;
1043
+ }
1001
1044
default :
1002
1045
// Unexpected.
1003
1046
error (_tok, " expected linker script command" );
@@ -1975,5 +2018,82 @@ Sections *Parser::parseSections() {
1975
2018
return new (_alloc) Sections (*this , sectionsCommands);
1976
2019
}
1977
2020
2021
+ Memory *Parser::parseMemory () {
2022
+ assert (_tok._kind == Token::kw_memory && " Expected MEMORY!" );
2023
+ consumeToken ();
2024
+ if (!expectAndConsume (Token::l_brace, " expected {" ))
2025
+ return nullptr ;
2026
+ SmallVector<const MemoryBlock *, 8 > blocks;
2027
+
2028
+ bool unrecognizedToken = false ;
2029
+ // Parse zero or more memory block descriptors.
2030
+ while (!unrecognizedToken) {
2031
+ if (_tok._kind == Token::identifier) {
2032
+ StringRef name;
2033
+ StringRef attrs;
2034
+ const Expression *origin = nullptr ;
2035
+ const Expression *length = nullptr ;
2036
+
2037
+ name = _tok._range ;
2038
+ consumeToken ();
2039
+
2040
+ // Parse optional memory region attributes.
2041
+ if (_tok._kind == Token::l_paren) {
2042
+ consumeToken ();
2043
+
2044
+ if (_tok._kind != Token::identifier) {
2045
+ error (_tok, " Expected memory attribute string." );
2046
+ return nullptr ;
2047
+ }
2048
+ attrs = _tok._range ;
2049
+ consumeToken ();
2050
+
2051
+ if (!expectAndConsume (Token::r_paren, " expected )" ))
2052
+ return nullptr ;
2053
+ }
2054
+
2055
+ if (!expectAndConsume (Token::colon, " expected :" ))
2056
+ return nullptr ;
2057
+
2058
+ // Parse the ORIGIN (base address of memory block).
2059
+ if (!expectAndConsume (Token::kw_origin, " expected ORIGIN" ))
2060
+ return nullptr ;
2061
+
2062
+ if (!expectAndConsume (Token::equal, " expected =" ))
2063
+ return nullptr ;
2064
+
2065
+ origin = parseExpression ();
2066
+ if (!origin)
2067
+ return nullptr ;
2068
+
2069
+ if (!expectAndConsume (Token::comma, " expected ," ))
2070
+ return nullptr ;
2071
+
2072
+ // Parse the LENGTH (length of memory block).
2073
+ if (!expectAndConsume (Token::kw_length, " expected LENGTH" ))
2074
+ return nullptr ;
2075
+
2076
+ if (!expectAndConsume (Token::equal, " expected =" ))
2077
+ return nullptr ;
2078
+
2079
+ length = parseExpression ();
2080
+ if (!length)
2081
+ return nullptr ;
2082
+
2083
+ MemoryBlock *block =
2084
+ new (_alloc) MemoryBlock (name, attrs, origin, length);
2085
+ blocks.push_back (block);
2086
+ } else {
2087
+ unrecognizedToken = true ;
2088
+ }
2089
+ }
2090
+ if (!expectAndConsume (
2091
+ Token::r_brace,
2092
+ " expected memory block definition." ))
2093
+ return nullptr ;
2094
+
2095
+ return new (_alloc) Memory (*this , blocks);
2096
+ }
2097
+
1978
2098
} // end namespace script
1979
2099
} // end namespace lld
0 commit comments