]>
Commit | Line | Data |
---|---|---|
c611e285 SC |
1 | /* This module handles expression trees. |
2 | Copyright (C) 1991 Free Software Foundation, Inc. | |
3 | Written by Steve Chamberlain of Cygnus Support ([email protected]). | |
2fa0b342 DHW |
4 | |
5 | This file is part of GLD, the Gnu Linker. | |
6 | ||
7 | GLD is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
c611e285 | 9 | the Free Software Foundation; either version 2, or (at your option) |
2fa0b342 DHW |
10 | any later version. |
11 | ||
12 | GLD is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GLD; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
21 | /* | |
c611e285 | 22 | This module is in charge of working out the contents of expressions. |
2fa0b342 | 23 | |
c611e285 SC |
24 | It has to keep track of the relative/absness of a symbol etc. This is |
25 | done by keeping all values in a struct (an etree_value_type) which | |
26 | contains a value, a section to which it is relative and a valid bit. | |
27 | ||
28 | */ | |
2fa0b342 DHW |
29 | |
30 | ||
2fa0b342 | 31 | #include "bfd.h" |
c611e285 | 32 | #include "sysdep.h" |
2fa0b342 DHW |
33 | |
34 | #include "ld.h" | |
fcf276c4 | 35 | #include "ldsym.h" |
2fa0b342 DHW |
36 | #include "ldmain.h" |
37 | #include "ldmisc.h" | |
38 | #include "ldexp.h" | |
c611e285 | 39 | #include "ldgram.h" |
2fa0b342 DHW |
40 | #include "ldlang.h" |
41 | ||
2fa0b342 | 42 | static void |
8bf66be8 DM |
43 | exp_print_token (code) |
44 | token_code_type code; | |
2fa0b342 | 45 | { |
8bf66be8 | 46 | static CONST struct { |
2fa0b342 DHW |
47 | token_code_type code; |
48 | char *name; | |
49 | } table[] = | |
c611e285 SC |
50 | { |
51 | INT, "int", | |
52 | NAME,"NAME", | |
53 | PLUSEQ,"+=", | |
54 | MINUSEQ,"-=", | |
55 | MULTEQ,"*=", | |
56 | DIVEQ,"/=", | |
57 | LSHIFTEQ,"<<=", | |
58 | RSHIFTEQ,">>=", | |
59 | ANDEQ,"&=", | |
60 | OREQ,"|=", | |
61 | OROR,"||", | |
62 | ANDAND,"&&", | |
63 | EQ,"==", | |
64 | NE,"!=", | |
65 | LE,"<=", | |
66 | GE,">=", | |
67 | LSHIFT,"<<", | |
68 | RSHIFT,">>=", | |
69 | ALIGN_K,"ALIGN", | |
70 | BLOCK,"BLOCK", | |
71 | SECTIONS,"SECTIONS", | |
72 | SIZEOF_HEADERS,"SIZEOF_HEADERS", | |
73 | NEXT,"NEXT", | |
74 | SIZEOF,"SIZEOF", | |
75 | ADDR,"ADDR", | |
76 | MEMORY,"MEMORY", | |
77 | ||
78 | ||
79 | ||
80 | ||
81 | ||
82 | DEFINED,"DEFINED", | |
83 | TARGET_K,"TARGET", | |
84 | SEARCH_DIR,"SEARCH_DIR", | |
85 | MAP,"MAP", | |
86 | LONG,"LONG", | |
87 | SHORT,"SHORT", | |
88 | BYTE,"BYTE", | |
89 | ENTRY,"ENTRY", | |
90 | 0,(char *)NULL} ; | |
2fa0b342 DHW |
91 | |
92 | ||
93 | ||
94 | unsigned int idx; | |
95 | for (idx = 0; table[idx].name != (char*)NULL; idx++) { | |
96 | if (table[idx].code == code) { | |
2e2bf962 | 97 | fprintf(config.map_file, "%s", table[idx].name); |
2fa0b342 DHW |
98 | return; |
99 | } | |
100 | } | |
101 | /* Not in table, just print it alone */ | |
2e2bf962 | 102 | fprintf(config.map_file, "%c",code); |
2fa0b342 DHW |
103 | } |
104 | ||
105 | static void | |
8bf66be8 DM |
106 | make_abs (ptr) |
107 | etree_value_type *ptr; | |
2fa0b342 | 108 | { |
2fa0b342 DHW |
109 | asection *s = ptr->section->bfd_section; |
110 | ptr->value += s->vma; | |
76971f0d | 111 | ptr->section = abs_output_section; |
2fa0b342 | 112 | } |
c611e285 | 113 | |
8bf66be8 DM |
114 | static etree_value_type |
115 | new_abs (value) | |
116 | bfd_vma value; | |
2fa0b342 DHW |
117 | { |
118 | etree_value_type new; | |
119 | new.valid = true; | |
76971f0d | 120 | new.section = abs_output_section; |
2fa0b342 DHW |
121 | new.value = value; |
122 | return new; | |
123 | } | |
124 | ||
3a399523 | 125 | static void |
8bf66be8 DM |
126 | check (os, name, op) |
127 | lang_output_section_statement_type *os; | |
128 | CONST char *name; | |
129 | CONST char *op; | |
2fa0b342 DHW |
130 | { |
131 | if (os == (lang_output_section_statement_type *)NULL) { | |
fcf276c4 | 132 | einfo("%F%P: %s uses undefined section %s\n", op, name); |
2fa0b342 DHW |
133 | } |
134 | if (os->processed == false) { | |
fcf276c4 | 135 | einfo("%F%P: %s forward reference of section %s\n",op, name); |
2fa0b342 DHW |
136 | } |
137 | } | |
138 | ||
c611e285 | 139 | etree_type * |
8bf66be8 DM |
140 | exp_intop (value) |
141 | bfd_vma value; | |
2fa0b342 | 142 | { |
bfbdc80f | 143 | etree_type *new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->value))); |
2fa0b342 DHW |
144 | new->type.node_code = INT; |
145 | new->value.value = value; | |
146 | new->type.node_class = etree_value; | |
147 | return new; | |
148 | ||
149 | } | |
150 | ||
151 | ||
8bf66be8 DM |
152 | static etree_value_type |
153 | new_rel (value, section) | |
154 | bfd_vma value; | |
155 | lang_output_section_statement_type *section; | |
2fa0b342 DHW |
156 | { |
157 | etree_value_type new; | |
158 | new.valid = true; | |
159 | new.value = value; | |
160 | new.section = section; | |
161 | return new; | |
162 | } | |
163 | ||
8bf66be8 DM |
164 | static etree_value_type |
165 | new_rel_from_section (value, section) | |
166 | bfd_vma value; | |
167 | lang_output_section_statement_type *section; | |
2fa0b342 DHW |
168 | { |
169 | etree_value_type new; | |
170 | new.valid = true; | |
171 | new.value = value; | |
172 | new.section = section; | |
76971f0d | 173 | |
2fa0b342 | 174 | new.value -= section->bfd_section->vma; |
76971f0d | 175 | |
2fa0b342 DHW |
176 | return new; |
177 | } | |
178 | ||
179 | static etree_value_type | |
8bf66be8 DM |
180 | fold_binary (tree, current_section, allocation_done, dot, dotp) |
181 | etree_type *tree; | |
182 | lang_output_section_statement_type *current_section; | |
183 | lang_phase_type allocation_done; | |
184 | bfd_vma dot; | |
185 | bfd_vma *dotp; | |
2fa0b342 DHW |
186 | { |
187 | etree_value_type result; | |
188 | ||
189 | result = exp_fold_tree(tree->binary.lhs, current_section, | |
190 | allocation_done, dot, dotp); | |
191 | if (result.valid) { | |
192 | etree_value_type other; | |
193 | other = exp_fold_tree(tree->binary.rhs, | |
194 | current_section, | |
195 | allocation_done, dot,dotp) ; | |
196 | if (other.valid) { | |
197 | /* If values are from different sections, or this is an */ | |
198 | /* absolute expression, make both source args absolute */ | |
199 | if (result.section != other.section || | |
76971f0d SC |
200 | current_section == abs_output_section) |
201 | { | |
2fa0b342 DHW |
202 | make_abs(&result); |
203 | make_abs(&other); | |
204 | } | |
205 | ||
206 | switch (tree->type.node_code) | |
207 | { | |
208 | case '%': | |
209 | /* Mod, both absolule*/ | |
210 | ||
211 | if (other.value == 0) { | |
fcf276c4 | 212 | einfo("%F%S %% by zero\n"); |
2fa0b342 | 213 | } |
76971f0d | 214 | result.value = (int)result.value % (int)other.value; |
2fa0b342 DHW |
215 | break; |
216 | case '/': | |
217 | if (other.value == 0) { | |
c611e285 | 218 | einfo("%F%S / by zero\n"); |
2fa0b342 | 219 | } |
76971f0d | 220 | result.value = (int)result.value / (int) other.value; |
2fa0b342 DHW |
221 | break; |
222 | #define BOP(x,y) case x : result.value = result.value y other.value;break; | |
223 | BOP('+',+); | |
224 | BOP('*',*); | |
225 | BOP('-',-); | |
226 | BOP(LSHIFT,<<); | |
227 | BOP(RSHIFT,>>); | |
228 | BOP(EQ,==); | |
229 | BOP(NE,!=); | |
230 | BOP('<',<); | |
231 | BOP('>',>); | |
232 | BOP(LE,<=); | |
233 | BOP(GE,>=); | |
234 | BOP('&',&); | |
235 | BOP('^',^); | |
236 | BOP('|',|); | |
237 | BOP(ANDAND,&&); | |
238 | BOP(OROR,||); | |
239 | default: | |
240 | FAIL(); | |
241 | } | |
242 | } | |
070aa819 SC |
243 | else { |
244 | result.valid = false; | |
245 | } | |
2fa0b342 DHW |
246 | } |
247 | return result; | |
248 | } | |
c611e285 | 249 | etree_value_type |
8bf66be8 | 250 | invalid () |
2fa0b342 DHW |
251 | { |
252 | etree_value_type new; | |
253 | new.valid = false; | |
254 | return new; | |
255 | } | |
256 | ||
c611e285 | 257 | etree_value_type |
8bf66be8 DM |
258 | fold_name (tree, current_section, allocation_done, dot) |
259 | etree_type *tree; | |
260 | lang_output_section_statement_type *current_section; | |
261 | lang_phase_type allocation_done; | |
262 | bfd_vma dot; | |
2fa0b342 DHW |
263 | { |
264 | etree_value_type result; | |
265 | switch (tree->type.node_code) | |
ac004870 | 266 | { |
65c552e3 SC |
267 | case SIZEOF_HEADERS: |
268 | if (allocation_done != lang_first_phase_enum) | |
269 | { | |
270 | result = new_abs(bfd_sizeof_headers(output_bfd, | |
271 | config.relocateable_output)); | |
272 | ||
273 | } | |
274 | else { | |
275 | result.valid = false; | |
276 | } | |
277 | break; | |
ac004870 SC |
278 | case DEFINED: |
279 | result.value = | |
280 | ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL; | |
281 | result.section = 0; | |
282 | result.valid = true; | |
283 | break; | |
284 | case NAME: | |
285 | result.valid = false; | |
286 | if (tree->name.name[0] == '.' && tree->name.name[1] == 0) { | |
287 | ||
288 | if (allocation_done != lang_first_phase_enum) { | |
289 | result = new_rel_from_section(dot, current_section); | |
290 | } | |
291 | else { | |
292 | result = invalid(); | |
293 | } | |
2fa0b342 DHW |
294 | } |
295 | else { | |
ac004870 SC |
296 | if (allocation_done == lang_final_phase_enum) { |
297 | ldsym_type *sy = ldsym_get_soft(tree->name.name); | |
2fa0b342 | 298 | |
ac004870 SC |
299 | if (sy) { |
300 | asymbol **sdefp = sy->sdefs_chain; | |
301 | ||
302 | if (sdefp) { | |
303 | asymbol *sdef = *sdefp; | |
76971f0d | 304 | #if 0 |
ac004870 SC |
305 | if (sdef->section == (asection *)NULL) { |
306 | /* This is an absolute symbol */ | |
307 | result = new_abs(sdef->value); | |
308 | } | |
76971f0d SC |
309 | else |
310 | #endif | |
311 | { | |
ac004870 SC |
312 | lang_output_section_statement_type *os = |
313 | lang_output_section_statement_lookup( | |
314 | sdef->section->output_section->name); | |
315 | /* If the symbol is from a file which we are not | |
316 | relocating (-R) then return an absolute for its | |
317 | value */ | |
8bf66be8 DM |
318 | if (bfd_asymbol_bfd(sdef)->usrdata && |
319 | ((lang_input_statement_type*)(bfd_asymbol_bfd(sdef)->usrdata))->just_syms_flag == true) | |
ac004870 | 320 | { |
76971f0d SC |
321 | result = new_abs(sdef->value +sdef->section->vma); |
322 | ||
ac004870 SC |
323 | } |
324 | else { | |
a37cc0c0 | 325 | result = new_rel(sdef->value + sdef->section->output_offset, os); |
ac004870 SC |
326 | } |
327 | } | |
2fa0b342 DHW |
328 | } |
329 | } | |
ac004870 | 330 | if (result.valid == false) { |
fcf276c4 | 331 | einfo("%F%S: undefined symbol `%s' referenced in expression\n", |
2fa0b342 | 332 | tree->name.name); |
ac004870 | 333 | } |
2fa0b342 | 334 | |
ac004870 | 335 | } |
2fa0b342 | 336 | } |
2fa0b342 | 337 | |
ac004870 | 338 | break; |
2fa0b342 | 339 | |
ac004870 | 340 | case ADDR: |
2fa0b342 | 341 | |
ac004870 SC |
342 | if (allocation_done != lang_first_phase_enum) { |
343 | lang_output_section_statement_type *os = | |
344 | lang_output_section_find(tree->name.name); | |
345 | check(os,tree->name.name,"ADDR"); | |
346 | result = new_rel((bfd_vma)0, os); | |
347 | } | |
348 | else { | |
349 | result = invalid(); | |
350 | } | |
351 | break; | |
352 | case SIZEOF: | |
353 | if(allocation_done != lang_first_phase_enum) { | |
354 | lang_output_section_statement_type *os = | |
355 | lang_output_section_find(tree->name.name); | |
356 | check(os,tree->name.name,"SIZEOF"); | |
c611e285 | 357 | result = new_abs((bfd_vma)(os->bfd_section->_raw_size)); |
ac004870 SC |
358 | } |
359 | else { | |
360 | result = invalid(); | |
361 | } | |
362 | break; | |
2fa0b342 | 363 | |
ac004870 SC |
364 | default: |
365 | FAIL(); | |
366 | break; | |
367 | } | |
2fa0b342 DHW |
368 | |
369 | return result; | |
370 | } | |
c611e285 | 371 | etree_value_type |
8bf66be8 DM |
372 | exp_fold_tree (tree, current_section, allocation_done, dot, dotp) |
373 | etree_type *tree; | |
374 | lang_output_section_statement_type *current_section; | |
375 | lang_phase_type allocation_done; | |
376 | bfd_vma dot; | |
377 | bfd_vma *dotp; | |
2fa0b342 DHW |
378 | { |
379 | etree_value_type result; | |
380 | ||
381 | if (tree == (etree_type *)NULL) { | |
8bf66be8 DM |
382 | result.valid = false; |
383 | } | |
2fa0b342 | 384 | else { |
8bf66be8 DM |
385 | switch (tree->type.node_class) |
386 | { | |
387 | case etree_value: | |
388 | result = new_rel(tree->value.value, current_section); | |
389 | break; | |
390 | case etree_unary: | |
391 | result = exp_fold_tree(tree->unary.child, | |
392 | current_section, | |
393 | allocation_done, dot, dotp); | |
394 | if (result.valid == true) | |
c611e285 | 395 | { |
8bf66be8 | 396 | switch(tree->type.node_code) |
d4c02e29 | 397 | { |
8bf66be8 DM |
398 | case ALIGN_K: |
399 | if (allocation_done != lang_first_phase_enum) { | |
400 | result = new_rel_from_section(ALIGN_N(dot, | |
401 | result.value) , | |
402 | current_section); | |
403 | ||
404 | } | |
405 | else { | |
406 | result.valid = false; | |
407 | } | |
408 | break; | |
409 | case ABSOLUTE: | |
410 | if (allocation_done != lang_first_phase_enum) | |
c611e285 | 411 | { |
8bf66be8 DM |
412 | if (current_section |
413 | == (lang_output_section_statement_type*)NULL) | |
414 | { | |
415 | /* Outside a section, so it's all ok */ | |
d4c02e29 | 416 | |
8bf66be8 | 417 | } |
c611e285 | 418 | else { |
8bf66be8 DM |
419 | /* Inside a section, subtract the base of the section, |
420 | so when it's added again (in an assignment), everything comes out fine | |
421 | */ | |
422 | result.section = abs_output_section; | |
423 | result.value -= current_section->bfd_section->vma; | |
424 | result.valid = true; | |
425 | } | |
426 | } | |
427 | else | |
428 | { | |
429 | result.valid = false; | |
430 | } | |
431 | ||
432 | break; | |
433 | case '~': | |
434 | make_abs(&result); | |
435 | result.value = ~result.value; | |
436 | break; | |
437 | case '!': | |
438 | make_abs(&result); | |
439 | result.value = !result.value; | |
440 | break; | |
441 | case '-': | |
442 | make_abs(&result); | |
443 | result.value = -result.value; | |
444 | break; | |
445 | case NEXT: | |
446 | if (allocation_done ==lang_allocating_phase_enum) { | |
c611e285 | 447 | make_abs(&result); |
8bf66be8 | 448 | result.value = ALIGN_N(dot, result.value); |
c611e285 | 449 | } |
8bf66be8 DM |
450 | else { |
451 | /* Return next place aligned to value */ | |
452 | result.valid = false; | |
453 | } | |
454 | break; | |
455 | default: | |
456 | FAIL(); | |
c611e285 | 457 | } |
8bf66be8 | 458 | } |
2fa0b342 | 459 | |
8bf66be8 DM |
460 | break; |
461 | case etree_trinary: | |
2fa0b342 | 462 | |
8bf66be8 DM |
463 | result = exp_fold_tree(tree->trinary.cond, |
464 | current_section, | |
465 | allocation_done, dot, dotp); | |
466 | if (result.valid) { | |
467 | result = exp_fold_tree(result.value ? | |
468 | tree->trinary.lhs:tree->trinary.rhs, | |
c611e285 SC |
469 | current_section, |
470 | allocation_done, dot, dotp); | |
8bf66be8 | 471 | } |
d4c02e29 | 472 | |
8bf66be8 DM |
473 | break; |
474 | case etree_binary: | |
475 | result = fold_binary(tree, current_section, allocation_done, | |
476 | dot, dotp); | |
477 | break; | |
478 | case etree_assign: | |
479 | if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) { | |
480 | /* Assignment to dot can only be done during allocation */ | |
481 | if (allocation_done == lang_allocating_phase_enum) { | |
482 | result = exp_fold_tree(tree->assign.src, | |
483 | current_section, | |
484 | lang_allocating_phase_enum, dot, dotp); | |
485 | if (result.valid == false) { | |
486 | einfo("%F%S invalid assignment to location counter\n"); | |
487 | } | |
488 | else { | |
489 | if (current_section == | |
490 | (lang_output_section_statement_type *)NULL) { | |
491 | einfo("%F%S assignment to location counter invalid outside of SECTION\n"); | |
492 | } | |
493 | else { | |
494 | bfd_vma nextdot =result.value + | |
495 | current_section->bfd_section->vma; | |
496 | if (nextdot < dot) { | |
497 | einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot, nextdot); | |
498 | } | |
499 | else { | |
500 | *dotp = nextdot; | |
2fa0b342 | 501 | } |
8bf66be8 | 502 | } |
2fa0b342 | 503 | } |
8bf66be8 DM |
504 | } |
505 | } | |
506 | else { | |
507 | ldsym_type *sy = ldsym_get(tree->assign.dst); | |
508 | ||
509 | /* If this symbol has just been created then we'll place it into | |
510 | * a section of our choice | |
511 | */ | |
512 | result = exp_fold_tree(tree->assign.src, | |
513 | current_section, allocation_done, | |
514 | dot, dotp); | |
515 | if (result.valid) | |
516 | { | |
517 | asymbol *def; | |
518 | asymbol **def_ptr ; | |
519 | /* Add this definition to script file */ | |
520 | if (sy->sdefs_chain) | |
521 | { | |
522 | def_ptr = sy->sdefs_chain; | |
523 | def = *def_ptr; | |
c611e285 | 524 | |
8bf66be8 DM |
525 | } |
526 | else | |
527 | { | |
528 | def_ptr = (asymbol **)stat_alloc((bfd_size_type)(sizeof(asymbol **))); | |
529 | def = (asymbol *)bfd_make_empty_symbol(script_file->the_bfd); | |
c611e285 SC |
530 | |
531 | ||
8bf66be8 | 532 | def->flags = 0; |
76971f0d | 533 | |
8bf66be8 DM |
534 | sy->sdefs_chain = def_ptr; |
535 | *def_ptr = def; | |
536 | } | |
c611e285 | 537 | |
8bf66be8 | 538 | def->value = result.value; |
76971f0d | 539 | |
8bf66be8 DM |
540 | def->section = result.section->bfd_section; |
541 | def->flags |= BSF_GLOBAL | BSF_EXPORT; | |
d4c02e29 SC |
542 | |
543 | ||
8bf66be8 DM |
544 | def->udata = (PTR)NULL; |
545 | def->name = sy->name; | |
c611e285 | 546 | |
8bf66be8 DM |
547 | if (sy->sdefs_chain == 0) |
548 | enter_global_ref(def_ptr, sy->name); | |
549 | } | |
2fa0b342 | 550 | |
8bf66be8 | 551 | } |
2fa0b342 DHW |
552 | |
553 | ||
8bf66be8 DM |
554 | break; |
555 | case etree_name: | |
556 | result = fold_name(tree, current_section, allocation_done, dot); | |
557 | break; | |
558 | default: | |
fcf276c4 | 559 | einfo("%F%S need more of these %d\n",tree->type.node_class ); |
2fa0b342 | 560 | |
c611e285 | 561 | } |
8bf66be8 | 562 | } |
2fa0b342 DHW |
563 | |
564 | return result; | |
565 | } | |
566 | ||
567 | ||
c611e285 | 568 | etree_value_type |
8bf66be8 DM |
569 | exp_fold_tree_no_dot (tree, current_section, allocation_done) |
570 | etree_type *tree; | |
571 | lang_output_section_statement_type *current_section; | |
572 | lang_phase_type allocation_done; | |
2fa0b342 DHW |
573 | { |
574 | return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma) | |
575 | 0, (bfd_vma *)NULL); | |
576 | } | |
577 | ||
578 | etree_type * | |
8bf66be8 DM |
579 | exp_binop (code, lhs, rhs) |
580 | int code; | |
581 | etree_type *lhs; | |
582 | etree_type *rhs; | |
2fa0b342 DHW |
583 | { |
584 | etree_type value, *new; | |
585 | etree_value_type r; | |
586 | ||
587 | value.type.node_code = code; | |
588 | value.binary.lhs = lhs; | |
589 | value.binary.rhs = rhs; | |
590 | value.type.node_class = etree_binary; | |
76971f0d SC |
591 | r = exp_fold_tree_no_dot(&value, |
592 | abs_output_section, | |
2fa0b342 DHW |
593 | lang_first_phase_enum ); |
594 | if (r.valid) | |
595 | { | |
596 | return exp_intop(r.value); | |
597 | } | |
bfbdc80f | 598 | new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->binary))); |
2fa0b342 DHW |
599 | memcpy((char *)new, (char *)&value, sizeof(new->binary)); |
600 | return new; | |
601 | } | |
602 | ||
603 | etree_type * | |
8bf66be8 DM |
604 | exp_trinop (code, cond, lhs, rhs) |
605 | int code; | |
606 | etree_type *cond; | |
607 | etree_type *lhs; | |
608 | etree_type *rhs; | |
2fa0b342 DHW |
609 | { |
610 | etree_type value, *new; | |
611 | etree_value_type r; | |
612 | value.type.node_code = code; | |
613 | value.trinary.lhs = lhs; | |
614 | value.trinary.cond = cond; | |
615 | value.trinary.rhs = rhs; | |
616 | value.type.node_class = etree_trinary; | |
617 | r= exp_fold_tree_no_dot(&value, (lang_output_section_statement_type | |
618 | *)NULL,lang_first_phase_enum); | |
619 | if (r.valid) { | |
620 | return exp_intop(r.value); | |
621 | } | |
bfbdc80f | 622 | new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->trinary))); |
2fa0b342 DHW |
623 | memcpy((char *)new,(char *) &value, sizeof(new->trinary)); |
624 | return new; | |
625 | } | |
626 | ||
627 | ||
628 | etree_type * | |
8bf66be8 DM |
629 | exp_unop (code, child) |
630 | int code; | |
631 | etree_type *child; | |
2fa0b342 DHW |
632 | { |
633 | etree_type value, *new; | |
634 | ||
635 | etree_value_type r; | |
636 | value.unary.type.node_code = code; | |
637 | value.unary.child = child; | |
638 | value.unary.type.node_class = etree_unary; | |
8bf66be8 | 639 | r = exp_fold_tree_no_dot(&value,abs_output_section, |
c611e285 SC |
640 | lang_first_phase_enum); |
641 | if (r.valid) { | |
2fa0b342 DHW |
642 | return exp_intop(r.value); |
643 | } | |
bfbdc80f | 644 | new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->unary))); |
2fa0b342 DHW |
645 | memcpy((char *)new, (char *)&value, sizeof(new->unary)); |
646 | return new; | |
647 | } | |
648 | ||
649 | ||
650 | etree_type * | |
8bf66be8 DM |
651 | exp_nameop (code, name) |
652 | int code; | |
653 | CONST char *name; | |
2fa0b342 | 654 | { |
2fa0b342 | 655 | etree_type value, *new; |
2fa0b342 DHW |
656 | etree_value_type r; |
657 | value.name.type.node_code = code; | |
658 | value.name.name = name; | |
659 | value.name.type.node_class = etree_name; | |
660 | ||
661 | ||
76971f0d SC |
662 | r = exp_fold_tree_no_dot(&value, |
663 | (lang_output_section_statement_type *)NULL, | |
664 | lang_first_phase_enum); | |
2fa0b342 DHW |
665 | if (r.valid) { |
666 | return exp_intop(r.value); | |
667 | } | |
bfbdc80f | 668 | new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->name))); |
2fa0b342 DHW |
669 | memcpy((char *)new, (char *)&value, sizeof(new->name)); |
670 | return new; | |
671 | ||
672 | } | |
673 | ||
674 | ||
675 | ||
676 | ||
677 | etree_type * | |
8bf66be8 DM |
678 | exp_assop (code, dst, src) |
679 | int code; | |
680 | CONST char *dst; | |
681 | etree_type *src; | |
2fa0b342 DHW |
682 | { |
683 | etree_type value, *new; | |
684 | ||
685 | value.assign.type.node_code = code; | |
686 | ||
687 | ||
688 | value.assign.src = src; | |
689 | value.assign.dst = dst; | |
690 | value.assign.type.node_class = etree_assign; | |
691 | ||
692 | #if 0 | |
693 | if (exp_fold_tree_no_dot(&value, &result)) { | |
694 | return exp_intop(result); | |
695 | } | |
696 | #endif | |
bfbdc80f | 697 | new = (etree_type*)stat_alloc((bfd_size_type)(sizeof(new->assign))); |
2fa0b342 DHW |
698 | memcpy((char *)new, (char *)&value, sizeof(new->assign)); |
699 | return new; | |
700 | } | |
701 | ||
702 | void | |
8bf66be8 DM |
703 | exp_print_tree (tree) |
704 | etree_type *tree; | |
2fa0b342 DHW |
705 | { |
706 | switch (tree->type.node_class) { | |
707 | case etree_value: | |
c611e285 | 708 | print_address(tree->value.value); |
2fa0b342 | 709 | return; |
c611e285 | 710 | |
2fa0b342 DHW |
711 | case etree_assign: |
712 | #if 0 | |
713 | if (tree->assign.dst->sdefs != (asymbol *)NULL){ | |
2e2bf962 | 714 | fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name, |
2fa0b342 DHW |
715 | tree->assign.dst->sdefs->value); |
716 | } | |
717 | else { | |
2e2bf962 | 718 | fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name); |
2fa0b342 DHW |
719 | } |
720 | #endif | |
2e2bf962 SC |
721 | fprintf(config.map_file,"%s ",tree->assign.dst); |
722 | exp_print_token(tree->type.node_code); | |
723 | exp_print_tree(tree->assign.src); | |
2fa0b342 DHW |
724 | break; |
725 | case etree_binary: | |
bfbdc80f | 726 | fprintf(config.map_file,"("); |
2e2bf962 SC |
727 | exp_print_tree(tree->binary.lhs); |
728 | exp_print_token(tree->type.node_code); | |
729 | exp_print_tree(tree->binary.rhs); | |
bfbdc80f | 730 | fprintf(config.map_file,")"); |
2fa0b342 DHW |
731 | break; |
732 | case etree_trinary: | |
2e2bf962 SC |
733 | exp_print_tree(tree->trinary.cond); |
734 | fprintf(config.map_file,"?"); | |
735 | exp_print_tree(tree->trinary.lhs); | |
736 | fprintf(config.map_file,":"); | |
737 | exp_print_tree(tree->trinary.rhs); | |
2fa0b342 DHW |
738 | break; |
739 | case etree_unary: | |
2e2bf962 | 740 | exp_print_token(tree->unary.type.node_code); |
bfbdc80f SC |
741 | if (tree->unary.child) |
742 | { | |
743 | ||
2e2bf962 SC |
744 | fprintf(config.map_file,"("); |
745 | exp_print_tree(tree->unary.child); | |
746 | fprintf(config.map_file,")"); | |
bfbdc80f SC |
747 | } |
748 | ||
2fa0b342 DHW |
749 | break; |
750 | case etree_undef: | |
2e2bf962 | 751 | fprintf(config.map_file,"????????"); |
2fa0b342 DHW |
752 | break; |
753 | case etree_name: | |
754 | if (tree->type.node_code == NAME) { | |
2e2bf962 | 755 | fprintf(config.map_file,"%s", tree->name.name); |
2fa0b342 DHW |
756 | } |
757 | else { | |
2e2bf962 | 758 | exp_print_token(tree->type.node_code); |
bfbdc80f | 759 | if (tree->name.name) |
2e2bf962 | 760 | fprintf(config.map_file,"(%s)", tree->name.name); |
2fa0b342 DHW |
761 | } |
762 | break; | |
763 | default: | |
764 | FAIL(); | |
765 | break; | |
766 | } | |
767 | } | |
768 | ||
769 | ||
770 | ||
771 | ||
772 | bfd_vma | |
8bf66be8 DM |
773 | exp_get_vma (tree, def, name, allocation_done) |
774 | etree_type *tree; | |
775 | bfd_vma def; | |
776 | char *name; | |
777 | lang_phase_type allocation_done; | |
2fa0b342 DHW |
778 | { |
779 | etree_value_type r; | |
780 | ||
781 | if (tree != (etree_type *)NULL) { | |
782 | r = exp_fold_tree_no_dot(tree, | |
bfbdc80f | 783 | abs_output_section, |
2fa0b342 DHW |
784 | allocation_done); |
785 | if (r.valid == false && name) { | |
fcf276c4 | 786 | einfo("%F%S nonconstant expression for %s\n",name); |
2fa0b342 DHW |
787 | } |
788 | return r.value; | |
789 | } | |
790 | else { | |
791 | return def; | |
792 | } | |
793 | } | |
794 | ||
795 | int | |
8bf66be8 DM |
796 | exp_get_value_int (tree,def,name, allocation_done) |
797 | etree_type *tree; | |
798 | int def; | |
799 | char *name; | |
800 | lang_phase_type allocation_done; | |
2fa0b342 DHW |
801 | { |
802 | return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done); | |
803 | } | |
65c552e3 | 804 |