1 // expression.cc -- expressions in linker scripts for gold
3 // Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
6 // This file is part of gold.
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
27 #include "parameters.h"
36 // This file holds the code which handles linker expressions.
38 // When evaluating the value of an expression, we pass in a pointer to
39 // this struct, so that the expression evaluation can find the
40 // information it needs.
42 struct Expression::Expression_eval_info
44 const Symbol_table
* symtab
;
48 // Evaluate an expression.
51 Expression::eval(const Symbol_table
* symtab
, const Layout
* layout
)
53 Expression_eval_info eei
;
56 return this->value(&eei
);
61 class Integer_expression
: public Expression
64 Integer_expression(uint64_t val
)
69 value(const Expression_eval_info
*)
70 { return this->val_
; }
76 extern "C" Expression
*
77 script_exp_integer(uint64_t val
)
79 return new Integer_expression(val
);
82 // An expression whose value is the value of a symbol.
84 class Symbol_expression
: public Expression
87 Symbol_expression(const char* name
, size_t length
)
92 value(const Expression_eval_info
*);
99 Symbol_expression::value(const Expression_eval_info
* eei
)
101 Symbol
* sym
= eei
->symtab
->lookup(this->name_
.c_str());
102 if (sym
== NULL
|| !sym
->is_defined())
104 gold_error(_("undefined symbol '%s' referenced in expression"),
105 this->name_
.c_str());
109 if (parameters
->get_size() == 32)
110 return eei
->symtab
->get_sized_symbol
<32>(sym
)->value();
111 else if (parameters
->get_size() == 64)
112 return eei
->symtab
->get_sized_symbol
<64>(sym
)->value();
117 // An expression whose value is the value of the special symbol ".".
118 // This is only valid within a SECTIONS clause.
120 class Dot_expression
: public Expression
127 value(const Expression_eval_info
*);
131 Dot_expression::value(const Expression_eval_info
*)
133 gold_error("dot symbol unimplemented");
137 // A string. This is either the name of a symbol, or ".".
139 extern "C" Expression
*
140 script_exp_string(const char* name
, size_t length
)
142 if (length
== 1 && name
[0] == '.')
143 return new Dot_expression();
145 return new Symbol_expression(name
, length
);
148 // A unary expression.
150 class Unary_expression
: public Expression
153 Unary_expression(Expression
* arg
)
158 { delete this->arg_
; }
162 arg_value(const Expression_eval_info
* eei
) const
163 { return this->arg_
->value(eei
); }
169 // Handle unary operators. We use a preprocessor macro as a hack to
170 // capture the C operator.
172 #define UNARY_EXPRESSION(NAME, OPERATOR) \
173 class Unary_ ## NAME : public Unary_expression \
176 Unary_ ## NAME(Expression* arg) \
177 : Unary_expression(arg) \
181 value(const Expression_eval_info* eei) \
182 { return OPERATOR this->arg_value(eei); } \
185 extern "C" Expression* \
186 script_exp_unary_ ## NAME(Expression* arg) \
188 return new Unary_ ## NAME(arg); \
191 UNARY_EXPRESSION(minus
, -)
192 UNARY_EXPRESSION(logical_not
, !)
193 UNARY_EXPRESSION(bitwise_not
, ~)
195 // A binary expression.
197 class Binary_expression
: public Expression
200 Binary_expression(Expression
* left
, Expression
* right
)
201 : left_(left
), right_(right
)
212 left_value(const Expression_eval_info
* eei
) const
213 { return this->left_
->value(eei
); }
216 right_value(const Expression_eval_info
* eei
) const
217 { return this->right_
->value(eei
); }
224 // Handle binary operators. We use a preprocessor macro as a hack to
225 // capture the C operator.
227 #define BINARY_EXPRESSION(NAME, OPERATOR) \
228 class Binary_ ## NAME : public Binary_expression \
231 Binary_ ## NAME(Expression* left, Expression* right) \
232 : Binary_expression(left, right) \
236 value(const Expression_eval_info* eei) \
238 return (this->left_value(eei) \
239 OPERATOR this->right_value(eei)); \
243 extern "C" Expression* \
244 script_exp_binary_ ## NAME(Expression* left, Expression* right) \
246 return new Binary_ ## NAME(left, right); \
249 BINARY_EXPRESSION(mult
, *)
250 BINARY_EXPRESSION(div
, /)
251 BINARY_EXPRESSION(mod
, %)
252 BINARY_EXPRESSION(add
, +)
253 BINARY_EXPRESSION(sub
, -)
254 BINARY_EXPRESSION(lshift
, <<)
255 BINARY_EXPRESSION(rshift
, >>)
256 BINARY_EXPRESSION(eq
, ==)
257 BINARY_EXPRESSION(ne
, !=)
258 BINARY_EXPRESSION(le
, <=)
259 BINARY_EXPRESSION(ge
, >=)
260 BINARY_EXPRESSION(lt
, <)
261 BINARY_EXPRESSION(gt
, >)
262 BINARY_EXPRESSION(bitwise_and
, &)
263 BINARY_EXPRESSION(bitwise_xor
, ^)
264 BINARY_EXPRESSION(bitwise_or
, |)
265 BINARY_EXPRESSION(logical_and
, &&)
266 BINARY_EXPRESSION(logical_or
, ||)
268 // A trinary expression.
270 class Trinary_expression
: public Expression
273 Trinary_expression(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
274 : arg1_(arg1
), arg2_(arg2
), arg3_(arg3
)
277 ~Trinary_expression()
286 arg1_value(const Expression_eval_info
* eei
) const
287 { return this->arg1_
->value(eei
); }
290 arg2_value(const Expression_eval_info
* eei
) const
291 { return this->arg2_
->value(eei
); }
294 arg3_value(const Expression_eval_info
* eei
) const
295 { return this->arg3_
->value(eei
); }
303 // The conditional operator.
305 class Trinary_cond
: public Trinary_expression
308 Trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
309 : Trinary_expression(arg1
, arg2
, arg3
)
313 value(const Expression_eval_info
* eei
)
315 return (this->arg1_value(eei
)
316 ? this->arg2_value(eei
)
317 : this->arg3_value(eei
));
321 extern "C" Expression
*
322 script_exp_trinary_cond(Expression
* arg1
, Expression
* arg2
, Expression
* arg3
)
324 return new Trinary_cond(arg1
, arg2
, arg3
);
329 class Max_expression
: public Binary_expression
332 Max_expression(Expression
* left
, Expression
* right
)
333 : Binary_expression(left
, right
)
337 value(const Expression_eval_info
* eei
)
338 { return std::max(this->left_value(eei
), this->right_value(eei
)); }
341 extern "C" Expression
*
342 script_exp_function_max(Expression
* left
, Expression
* right
)
344 return new Max_expression(left
, right
);
349 class Min_expression
: public Binary_expression
352 Min_expression(Expression
* left
, Expression
* right
)
353 : Binary_expression(left
, right
)
357 value(const Expression_eval_info
* eei
)
358 { return std::min(this->left_value(eei
), this->right_value(eei
)); }
361 extern "C" Expression
*
362 script_exp_function_min(Expression
* left
, Expression
* right
)
364 return new Min_expression(left
, right
);
369 class Align_expression
: public Binary_expression
372 Align_expression(Expression
* left
, Expression
* right
)
373 : Binary_expression(left
, right
)
377 value(const Expression_eval_info
* eei
)
379 uint64_t align
= this->right_value(eei
);
380 uint64_t value
= this->left_value(eei
);
383 return ((value
+ align
- 1) / align
) * align
;
387 extern "C" Expression
*
388 script_exp_function_align(Expression
* left
, Expression
* right
)
390 return new Align_expression(left
, right
);
395 class Assert_expression
: public Unary_expression
398 Assert_expression(Expression
* arg
, const char* message
, size_t length
)
399 : Unary_expression(arg
), message_(message
, length
)
403 value(const Expression_eval_info
* eei
)
405 uint64_t value
= this->arg_value(eei
);
407 gold_error("%s", this->message_
.c_str());
412 std::string message_
;
415 extern "C" Expression
*
416 script_exp_function_assert(Expression
* expr
, const char* message
,
419 return new Assert_expression(expr
, message
, length
);
424 extern "C" Expression
*
425 script_exp_function_defined(const char*, size_t)
427 gold_fatal(_("DEFINED not implemented"));
430 extern "C" Expression
*
431 script_exp_function_sizeof_headers()
433 gold_fatal(_("SIZEOF_HEADERS not implemented"));
436 extern "C" Expression
*
437 script_exp_function_alignof(const char*, size_t)
439 gold_fatal(_("ALIGNOF not implemented"));
442 extern "C" Expression
*
443 script_exp_function_sizeof(const char*, size_t)
445 gold_fatal(_("SIZEOF not implemented"));
448 extern "C" Expression
*
449 script_exp_function_addr(const char*, size_t)
451 gold_fatal(_("ADDR not implemented"));
454 extern "C" Expression
*
455 script_exp_function_loadaddr(const char*, size_t)
457 gold_fatal(_("LOADADDR not implemented"));
460 extern "C" Expression
*
461 script_exp_function_origin(const char*, size_t)
463 gold_fatal(_("ORIGIN not implemented"));
466 extern "C" Expression
*
467 script_exp_function_length(const char*, size_t)
469 gold_fatal(_("LENGTH not implemented"));
472 extern "C" Expression
*
473 script_exp_function_constant(const char*, size_t)
475 gold_fatal(_("CONSTANT not implemented"));
478 extern "C" Expression
*
479 script_exp_function_absolute(Expression
*)
481 gold_fatal(_("ABSOLUTE not implemented"));
484 extern "C" Expression
*
485 script_exp_function_data_segment_align(Expression
*, Expression
*)
487 gold_fatal(_("DATA_SEGMENT_ALIGN not implemented"));
490 extern "C" Expression
*
491 script_exp_function_data_segment_relro_end(Expression
*, Expression
*)
493 gold_fatal(_("DATA_SEGMENT_RELRO_END not implemented"));
496 extern "C" Expression
*
497 script_exp_function_data_segment_end(Expression
*)
499 gold_fatal(_("DATA_SEGMENT_END not implemented"));
502 extern "C" Expression
*
503 script_exp_function_segment_start(const char*, size_t, Expression
*)
505 gold_fatal(_("SEGMENT_START not implemented"));
508 } // End namespace gold.