xref: /openbsd-src/gnu/usr.bin/binutils/ld/ldexp.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* This module handles expression trees.
2b55d4692Sfgsch    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3*007c2a45Smiod    2001, 2002, 2003, 2004
4b305b0f1Sespie    Free Software Foundation, Inc.
5b55d4692Sfgsch    Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
62159047fSniklas 
72159047fSniklas This file is part of GLD, the Gnu Linker.
82159047fSniklas 
92159047fSniklas GLD is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2, or (at your option)
122159047fSniklas any later version.
132159047fSniklas 
142159047fSniklas GLD is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas 
192159047fSniklas You should have received a copy of the GNU General Public License
20b305b0f1Sespie along with GLD; see the file COPYING.  If not, write to the Free
21b305b0f1Sespie Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22b305b0f1Sespie 02111-1307, USA.  */
232159047fSniklas 
24b55d4692Sfgsch /* This module is in charge of working out the contents of expressions.
252159047fSniklas 
26b55d4692Sfgsch    It has to keep track of the relative/absness of a symbol etc. This
27b55d4692Sfgsch    is done by keeping all values in a struct (an etree_value_type)
28b55d4692Sfgsch    which contains a value, a section to which it is relative and a
29b55d4692Sfgsch    valid bit.  */
302159047fSniklas 
312159047fSniklas #include "bfd.h"
322159047fSniklas #include "sysdep.h"
332159047fSniklas #include "bfdlink.h"
342159047fSniklas 
352159047fSniklas #include "ld.h"
362159047fSniklas #include "ldmain.h"
372159047fSniklas #include "ldmisc.h"
382159047fSniklas #include "ldexp.h"
39c074d1c9Sdrahn #include <ldgram.h>
402159047fSniklas #include "ldlang.h"
41c074d1c9Sdrahn #include "libiberty.h"
42c074d1c9Sdrahn #include "safe-ctype.h"
432159047fSniklas 
442159047fSniklas static etree_value_type exp_fold_tree_no_dot
45*007c2a45Smiod   (etree_type *, lang_output_section_statement_type *, lang_phase_type);
46*007c2a45Smiod static bfd_vma align_n
47*007c2a45Smiod   (bfd_vma, bfd_vma);
482159047fSniklas 
49c074d1c9Sdrahn struct exp_data_seg exp_data_seg;
50c074d1c9Sdrahn 
51c074d1c9Sdrahn /* Print the string representation of the given token.  Surround it
52c074d1c9Sdrahn    with spaces if INFIX_P is TRUE.  */
53c074d1c9Sdrahn 
542159047fSniklas static void
exp_print_token(token_code_type code,int infix_p)55*007c2a45Smiod exp_print_token (token_code_type code, int infix_p)
562159047fSniklas {
57c074d1c9Sdrahn   static const struct
58c074d1c9Sdrahn   {
592159047fSniklas     token_code_type code;
602159047fSniklas     char * name;
61c074d1c9Sdrahn   }
62c074d1c9Sdrahn   table[] =
63c074d1c9Sdrahn   {
642159047fSniklas     { INT, "int" },
652159047fSniklas     { NAME, "NAME" },
662159047fSniklas     { PLUSEQ, "+=" },
672159047fSniklas     { MINUSEQ, "-=" },
682159047fSniklas     { MULTEQ, "*=" },
692159047fSniklas     { DIVEQ, "/=" },
702159047fSniklas     { LSHIFTEQ, "<<=" },
712159047fSniklas     { RSHIFTEQ, ">>=" },
722159047fSniklas     { ANDEQ, "&=" },
732159047fSniklas     { OREQ, "|=" },
742159047fSniklas     { OROR, "||" },
752159047fSniklas     { ANDAND, "&&" },
762159047fSniklas     { EQ, "==" },
772159047fSniklas     { NE, "!=" },
782159047fSniklas     { LE, "<=" },
792159047fSniklas     { GE, ">=" },
802159047fSniklas     { LSHIFT, "<<" },
81c074d1c9Sdrahn     { RSHIFT, ">>" },
822159047fSniklas     { ALIGN_K, "ALIGN" },
832159047fSniklas     { BLOCK, "BLOCK" },
842159047fSniklas     { QUAD, "QUAD" },
85b305b0f1Sespie     { SQUAD, "SQUAD" },
862159047fSniklas     { LONG, "LONG" },
872159047fSniklas     { SHORT, "SHORT" },
882159047fSniklas     { BYTE, "BYTE" },
89c074d1c9Sdrahn     { SECTIONS, "SECTIONS" },
90c074d1c9Sdrahn     { SIZEOF_HEADERS, "SIZEOF_HEADERS" },
91c074d1c9Sdrahn     { MEMORY, "MEMORY" },
92c074d1c9Sdrahn     { DEFINED, "DEFINED" },
93c074d1c9Sdrahn     { TARGET_K, "TARGET" },
94c074d1c9Sdrahn     { SEARCH_DIR, "SEARCH_DIR" },
95c074d1c9Sdrahn     { MAP, "MAP" },
962159047fSniklas     { ENTRY, "ENTRY" },
97c074d1c9Sdrahn     { NEXT, "NEXT" },
98c074d1c9Sdrahn     { SIZEOF, "SIZEOF" },
99c074d1c9Sdrahn     { ADDR, "ADDR" },
100c074d1c9Sdrahn     { LOADADDR, "LOADADDR" },
101c074d1c9Sdrahn     { MAX_K, "MAX_K" },
102*007c2a45Smiod     { REL, "relocatable" },
103c074d1c9Sdrahn     { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
104c074d1c9Sdrahn     { DATA_SEGMENT_END, "DATA_SEGMENT_END" }
1052159047fSniklas   };
1062159047fSniklas   unsigned int idx;
1072159047fSniklas 
108c074d1c9Sdrahn   for (idx = 0; idx < ARRAY_SIZE (table); idx++)
109b55d4692Sfgsch     if (table[idx].code == code)
110c074d1c9Sdrahn       break;
111c074d1c9Sdrahn 
112c074d1c9Sdrahn   if (infix_p)
113c074d1c9Sdrahn     fputc (' ', config.map_file);
114c074d1c9Sdrahn 
115c074d1c9Sdrahn   if (idx < ARRAY_SIZE (table))
116c074d1c9Sdrahn     fputs (table[idx].name, config.map_file);
117c074d1c9Sdrahn   else if (code < 127)
118c074d1c9Sdrahn     fputc (code, config.map_file);
119c074d1c9Sdrahn   else
120c074d1c9Sdrahn     fprintf (config.map_file, "<code %d>", code);
121c074d1c9Sdrahn 
122c074d1c9Sdrahn   if (infix_p)
123c074d1c9Sdrahn     fputc (' ', config.map_file);
1242159047fSniklas }
1252159047fSniklas 
1262159047fSniklas static void
make_abs(etree_value_type * ptr)127*007c2a45Smiod make_abs (etree_value_type *ptr)
1282159047fSniklas {
1292159047fSniklas   asection *s = ptr->section->bfd_section;
1302159047fSniklas   ptr->value += s->vma;
1312159047fSniklas   ptr->section = abs_output_section;
1322159047fSniklas }
1332159047fSniklas 
1342159047fSniklas static etree_value_type
new_abs(bfd_vma value)135*007c2a45Smiod new_abs (bfd_vma value)
1362159047fSniklas {
1372159047fSniklas   etree_value_type new;
138c074d1c9Sdrahn   new.valid_p = TRUE;
1392159047fSniklas   new.section = abs_output_section;
1402159047fSniklas   new.value = value;
1412159047fSniklas   return new;
1422159047fSniklas }
1432159047fSniklas 
1442159047fSniklas etree_type *
exp_intop(bfd_vma value)145*007c2a45Smiod exp_intop (bfd_vma value)
1462159047fSniklas {
147*007c2a45Smiod   etree_type *new = stat_alloc (sizeof (new->value));
1482159047fSniklas   new->type.node_code = INT;
1492159047fSniklas   new->value.value = value;
150c074d1c9Sdrahn   new->value.str = NULL;
1512159047fSniklas   new->type.node_class = etree_value;
1522159047fSniklas   return new;
153c074d1c9Sdrahn }
1542159047fSniklas 
155c074d1c9Sdrahn etree_type *
exp_bigintop(bfd_vma value,char * str)156*007c2a45Smiod exp_bigintop (bfd_vma value, char *str)
157c074d1c9Sdrahn {
158*007c2a45Smiod   etree_type *new = stat_alloc (sizeof (new->value));
159c074d1c9Sdrahn   new->type.node_code = INT;
160c074d1c9Sdrahn   new->value.value = value;
161c074d1c9Sdrahn   new->value.str = str;
162c074d1c9Sdrahn   new->type.node_class = etree_value;
163c074d1c9Sdrahn   return new;
1642159047fSniklas }
1652159047fSniklas 
166*007c2a45Smiod /* Build an expression representing an unnamed relocatable value.  */
1672159047fSniklas 
1682159047fSniklas etree_type *
exp_relop(asection * section,bfd_vma value)169*007c2a45Smiod exp_relop (asection *section, bfd_vma value)
1702159047fSniklas {
171*007c2a45Smiod   etree_type *new = stat_alloc (sizeof (new->rel));
1722159047fSniklas   new->type.node_code = REL;
1732159047fSniklas   new->type.node_class = etree_rel;
1742159047fSniklas   new->rel.section = section;
1752159047fSniklas   new->rel.value = value;
1762159047fSniklas   return new;
1772159047fSniklas }
1782159047fSniklas 
1792159047fSniklas static etree_value_type
new_rel(bfd_vma value,char * str,lang_output_section_statement_type * section)180*007c2a45Smiod new_rel (bfd_vma value,
181*007c2a45Smiod 	 char *str,
182*007c2a45Smiod 	 lang_output_section_statement_type *section)
1832159047fSniklas {
1842159047fSniklas   etree_value_type new;
185c074d1c9Sdrahn   new.valid_p = TRUE;
1862159047fSniklas   new.value = value;
187c074d1c9Sdrahn   new.str = str;
1882159047fSniklas   new.section = section;
1892159047fSniklas   return new;
1902159047fSniklas }
1912159047fSniklas 
1922159047fSniklas static etree_value_type
new_rel_from_section(bfd_vma value,lang_output_section_statement_type * section)193*007c2a45Smiod new_rel_from_section (bfd_vma value,
194*007c2a45Smiod 		      lang_output_section_statement_type *section)
1952159047fSniklas {
1962159047fSniklas   etree_value_type new;
197c074d1c9Sdrahn   new.valid_p = TRUE;
1982159047fSniklas   new.value = value;
199c074d1c9Sdrahn   new.str = NULL;
2002159047fSniklas   new.section = section;
2012159047fSniklas 
2022159047fSniklas   new.value -= section->bfd_section->vma;
2032159047fSniklas 
2042159047fSniklas   return new;
2052159047fSniklas }
2062159047fSniklas 
2072159047fSniklas static etree_value_type
fold_unary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)208*007c2a45Smiod fold_unary (etree_type *tree,
209*007c2a45Smiod 	    lang_output_section_statement_type *current_section,
210*007c2a45Smiod 	    lang_phase_type allocation_done,
211*007c2a45Smiod 	    bfd_vma dot,
212*007c2a45Smiod 	    bfd_vma *dotp)
213c074d1c9Sdrahn {
214c074d1c9Sdrahn   etree_value_type result;
215c074d1c9Sdrahn 
216c074d1c9Sdrahn   result = exp_fold_tree (tree->unary.child,
217c074d1c9Sdrahn 			  current_section,
218c074d1c9Sdrahn 			  allocation_done, dot, dotp);
219c074d1c9Sdrahn   if (result.valid_p)
220c074d1c9Sdrahn     {
221c074d1c9Sdrahn       switch (tree->type.node_code)
222c074d1c9Sdrahn 	{
223c074d1c9Sdrahn 	case ALIGN_K:
224c074d1c9Sdrahn 	  if (allocation_done != lang_first_phase_enum)
225c074d1c9Sdrahn 	    result = new_rel_from_section (align_n (dot, result.value),
226c074d1c9Sdrahn 					   current_section);
227c074d1c9Sdrahn 	  else
228c074d1c9Sdrahn 	    result.valid_p = FALSE;
229c074d1c9Sdrahn 	  break;
230c074d1c9Sdrahn 
231c074d1c9Sdrahn 	case ABSOLUTE:
232c074d1c9Sdrahn 	  if (allocation_done != lang_first_phase_enum)
233c074d1c9Sdrahn 	    {
234c074d1c9Sdrahn 	      result.value += result.section->bfd_section->vma;
235c074d1c9Sdrahn 	      result.section = abs_output_section;
236c074d1c9Sdrahn 	    }
237c074d1c9Sdrahn 	  else
238c074d1c9Sdrahn 	    result.valid_p = FALSE;
239c074d1c9Sdrahn 	  break;
240c074d1c9Sdrahn 
241c074d1c9Sdrahn 	case '~':
242c074d1c9Sdrahn 	  make_abs (&result);
243c074d1c9Sdrahn 	  result.value = ~result.value;
244c074d1c9Sdrahn 	  break;
245c074d1c9Sdrahn 
246c074d1c9Sdrahn 	case '!':
247c074d1c9Sdrahn 	  make_abs (&result);
248c074d1c9Sdrahn 	  result.value = !result.value;
249c074d1c9Sdrahn 	  break;
250c074d1c9Sdrahn 
251c074d1c9Sdrahn 	case '-':
252c074d1c9Sdrahn 	  make_abs (&result);
253c074d1c9Sdrahn 	  result.value = -result.value;
254c074d1c9Sdrahn 	  break;
255c074d1c9Sdrahn 
256c074d1c9Sdrahn 	case NEXT:
257c074d1c9Sdrahn 	  /* Return next place aligned to value.  */
258c074d1c9Sdrahn 	  if (allocation_done == lang_allocating_phase_enum)
259c074d1c9Sdrahn 	    {
260c074d1c9Sdrahn 	      make_abs (&result);
261c074d1c9Sdrahn 	      result.value = align_n (dot, result.value);
262c074d1c9Sdrahn 	    }
263c074d1c9Sdrahn 	  else
264c074d1c9Sdrahn 	    result.valid_p = FALSE;
265c074d1c9Sdrahn 	  break;
266c074d1c9Sdrahn 
267c074d1c9Sdrahn 	case DATA_SEGMENT_END:
268c074d1c9Sdrahn 	  if (allocation_done != lang_first_phase_enum
269c074d1c9Sdrahn 	      && current_section == abs_output_section
270c074d1c9Sdrahn 	      && (exp_data_seg.phase == exp_dataseg_align_seen
271c074d1c9Sdrahn 		  || exp_data_seg.phase == exp_dataseg_adjust
272c074d1c9Sdrahn 		  || allocation_done != lang_allocating_phase_enum))
273c074d1c9Sdrahn 	    {
274c074d1c9Sdrahn 	      if (exp_data_seg.phase == exp_dataseg_align_seen)
275c074d1c9Sdrahn 		{
276c074d1c9Sdrahn 		  exp_data_seg.phase = exp_dataseg_end_seen;
277c074d1c9Sdrahn 		  exp_data_seg.end = result.value;
278c074d1c9Sdrahn 		}
279c074d1c9Sdrahn 	    }
280c074d1c9Sdrahn 	  else
281c074d1c9Sdrahn 	    result.valid_p = FALSE;
282c074d1c9Sdrahn 	  break;
283c074d1c9Sdrahn 
284c074d1c9Sdrahn 	default:
285c074d1c9Sdrahn 	  FAIL ();
286c074d1c9Sdrahn 	  break;
287c074d1c9Sdrahn 	}
288c074d1c9Sdrahn     }
289c074d1c9Sdrahn 
290c074d1c9Sdrahn   return result;
291c074d1c9Sdrahn }
292c074d1c9Sdrahn 
293c074d1c9Sdrahn static etree_value_type
fold_binary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)294*007c2a45Smiod fold_binary (etree_type *tree,
295*007c2a45Smiod 	     lang_output_section_statement_type *current_section,
296*007c2a45Smiod 	     lang_phase_type allocation_done,
297*007c2a45Smiod 	     bfd_vma dot,
298*007c2a45Smiod 	     bfd_vma *dotp)
2992159047fSniklas {
3002159047fSniklas   etree_value_type result;
3012159047fSniklas 
3022159047fSniklas   result = exp_fold_tree (tree->binary.lhs, current_section,
3032159047fSniklas 			  allocation_done, dot, dotp);
304b305b0f1Sespie   if (result.valid_p)
3052159047fSniklas     {
3062159047fSniklas       etree_value_type other;
3072159047fSniklas 
3082159047fSniklas       other = exp_fold_tree (tree->binary.rhs,
3092159047fSniklas 			     current_section,
3102159047fSniklas 			     allocation_done, dot, dotp);
311b305b0f1Sespie       if (other.valid_p)
3122159047fSniklas 	{
3132159047fSniklas 	  /* If the values are from different sections, or this is an
3142159047fSniklas 	     absolute expression, make both the source arguments
3152159047fSniklas 	     absolute.  However, adding or subtracting an absolute
3162159047fSniklas 	     value from a relative value is meaningful, and is an
3172159047fSniklas 	     exception.  */
3182159047fSniklas 	  if (current_section != abs_output_section
319191aa565Sniklas 	      && (other.section == abs_output_section
320191aa565Sniklas 		  || (result.section == abs_output_section
321191aa565Sniklas 		      && tree->type.node_code == '+'))
3222159047fSniklas 	      && (tree->type.node_code == '+'
3232159047fSniklas 		  || tree->type.node_code == '-'))
3242159047fSniklas 	    {
325191aa565Sniklas 	      if (other.section != abs_output_section)
3262159047fSniklas 		{
327c074d1c9Sdrahn 		  /* Keep the section of the other term.  */
328c074d1c9Sdrahn 		  if (tree->type.node_code == '+')
329c074d1c9Sdrahn 		    other.value = result.value + other.value;
330c074d1c9Sdrahn 		  else
331c074d1c9Sdrahn 		    other.value = result.value - other.value;
332c074d1c9Sdrahn 		  return other;
3332159047fSniklas 		}
3342159047fSniklas 	    }
3352159047fSniklas 	  else if (result.section != other.section
3362159047fSniklas 		   || current_section == abs_output_section)
3372159047fSniklas 	    {
3382159047fSniklas 	      make_abs (&result);
3392159047fSniklas 	      make_abs (&other);
3402159047fSniklas 	    }
3412159047fSniklas 
3422159047fSniklas 	  switch (tree->type.node_code)
3432159047fSniklas 	    {
3442159047fSniklas 	    case '%':
3452159047fSniklas 	      if (other.value == 0)
346b305b0f1Sespie 		einfo (_("%F%S %% by zero\n"));
3472159047fSniklas 	      result.value = ((bfd_signed_vma) result.value
3482159047fSniklas 			      % (bfd_signed_vma) other.value);
3492159047fSniklas 	      break;
3502159047fSniklas 
3512159047fSniklas 	    case '/':
3522159047fSniklas 	      if (other.value == 0)
353b305b0f1Sespie 		einfo (_("%F%S / by zero\n"));
3542159047fSniklas 	      result.value = ((bfd_signed_vma) result.value
3552159047fSniklas 			      / (bfd_signed_vma) other.value);
3562159047fSniklas 	      break;
3572159047fSniklas 
3582159047fSniklas #define BOP(x,y) case x : result.value = result.value y other.value; break;
3592159047fSniklas 	      BOP ('+', +);
3602159047fSniklas 	      BOP ('*', *);
3612159047fSniklas 	      BOP ('-', -);
3622159047fSniklas 	      BOP (LSHIFT, <<);
3632159047fSniklas 	      BOP (RSHIFT, >>);
3642159047fSniklas 	      BOP (EQ, ==);
3652159047fSniklas 	      BOP (NE, !=);
3662159047fSniklas 	      BOP ('<', <);
3672159047fSniklas 	      BOP ('>', >);
3682159047fSniklas 	      BOP (LE, <=);
3692159047fSniklas 	      BOP (GE, >=);
3702159047fSniklas 	      BOP ('&', &);
3712159047fSniklas 	      BOP ('^', ^);
3722159047fSniklas 	      BOP ('|', |);
3732159047fSniklas 	      BOP (ANDAND, &&);
3742159047fSniklas 	      BOP (OROR, ||);
3752159047fSniklas 
376b305b0f1Sespie 	    case MAX_K:
3770c6d0228Sniklas 	      if (result.value < other.value)
3780c6d0228Sniklas 		result = other;
3790c6d0228Sniklas 	      break;
3800c6d0228Sniklas 
381b305b0f1Sespie 	    case MIN_K:
3820c6d0228Sniklas 	      if (result.value > other.value)
3830c6d0228Sniklas 		result = other;
3840c6d0228Sniklas 	      break;
3850c6d0228Sniklas 
386*007c2a45Smiod 	    case ALIGN_K:
387*007c2a45Smiod 	      result.value = align_n (result.value, other.value);
388*007c2a45Smiod 	      break;
389*007c2a45Smiod 
390c074d1c9Sdrahn 	    case DATA_SEGMENT_ALIGN:
391c074d1c9Sdrahn 	      if (allocation_done != lang_first_phase_enum
392c074d1c9Sdrahn 		  && current_section == abs_output_section
393c074d1c9Sdrahn 		  && (exp_data_seg.phase == exp_dataseg_none
394c074d1c9Sdrahn 		      || exp_data_seg.phase == exp_dataseg_adjust
395c074d1c9Sdrahn 		      || allocation_done != lang_allocating_phase_enum))
396c074d1c9Sdrahn 		{
397c074d1c9Sdrahn 		  bfd_vma maxpage = result.value;
398c074d1c9Sdrahn 
399c074d1c9Sdrahn 		  result.value = align_n (dot, maxpage);
400c074d1c9Sdrahn 		  if (exp_data_seg.phase != exp_dataseg_adjust)
401c074d1c9Sdrahn 		    {
402c074d1c9Sdrahn 		      result.value += dot & (maxpage - 1);
403c074d1c9Sdrahn 		      if (allocation_done == lang_allocating_phase_enum)
404c074d1c9Sdrahn 			{
405c074d1c9Sdrahn 			  exp_data_seg.phase = exp_dataseg_align_seen;
406c074d1c9Sdrahn 			  exp_data_seg.base = result.value;
407c074d1c9Sdrahn 			  exp_data_seg.pagesize = other.value;
408c074d1c9Sdrahn 			}
409c074d1c9Sdrahn 		    }
410c074d1c9Sdrahn 		  else if (other.value < maxpage)
411c074d1c9Sdrahn 		    result.value += (dot + other.value - 1)
412c074d1c9Sdrahn 				    & (maxpage - other.value);
413c074d1c9Sdrahn 		}
414c074d1c9Sdrahn 	      else
415c074d1c9Sdrahn 		result.valid_p = FALSE;
416c074d1c9Sdrahn 	      break;
417c074d1c9Sdrahn 
4182159047fSniklas 	    default:
4192159047fSniklas 	      FAIL ();
4202159047fSniklas 	    }
4212159047fSniklas 	}
4222159047fSniklas       else
4232159047fSniklas 	{
424c074d1c9Sdrahn 	  result.valid_p = FALSE;
4252159047fSniklas 	}
4262159047fSniklas     }
4272159047fSniklas 
4282159047fSniklas   return result;
4292159047fSniklas }
4302159047fSniklas 
431c074d1c9Sdrahn static etree_value_type
fold_trinary(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)432*007c2a45Smiod fold_trinary (etree_type *tree,
433*007c2a45Smiod 	      lang_output_section_statement_type *current_section,
434*007c2a45Smiod 	      lang_phase_type allocation_done,
435*007c2a45Smiod 	      bfd_vma dot,
436*007c2a45Smiod 	      bfd_vma *dotp)
437c074d1c9Sdrahn {
438c074d1c9Sdrahn   etree_value_type result;
439c074d1c9Sdrahn 
440c074d1c9Sdrahn   result = exp_fold_tree (tree->trinary.cond, current_section,
441c074d1c9Sdrahn 			  allocation_done, dot, dotp);
442c074d1c9Sdrahn   if (result.valid_p)
443c074d1c9Sdrahn     result = exp_fold_tree ((result.value
444c074d1c9Sdrahn 			     ? tree->trinary.lhs
445c074d1c9Sdrahn 			     : tree->trinary.rhs),
446c074d1c9Sdrahn 			    current_section,
447c074d1c9Sdrahn 			    allocation_done, dot, dotp);
448c074d1c9Sdrahn 
449c074d1c9Sdrahn   return result;
450c074d1c9Sdrahn }
451c074d1c9Sdrahn 
4522159047fSniklas static etree_value_type
fold_name(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot)453*007c2a45Smiod fold_name (etree_type *tree,
454*007c2a45Smiod 	   lang_output_section_statement_type *current_section,
455*007c2a45Smiod 	   lang_phase_type allocation_done,
456*007c2a45Smiod 	   bfd_vma dot)
4572159047fSniklas {
4582159047fSniklas   etree_value_type result;
459c074d1c9Sdrahn 
460*007c2a45Smiod   result.valid_p = FALSE;
461*007c2a45Smiod 
4622159047fSniklas   switch (tree->type.node_code)
4632159047fSniklas     {
4642159047fSniklas     case SIZEOF_HEADERS:
4652159047fSniklas       if (allocation_done != lang_first_phase_enum)
466*007c2a45Smiod 	result = new_abs (bfd_sizeof_headers (output_bfd,
467*007c2a45Smiod 					      link_info.relocatable));
4682159047fSniklas       break;
4692159047fSniklas     case DEFINED:
4702159047fSniklas       if (allocation_done == lang_first_phase_enum)
471*007c2a45Smiod 	lang_track_definedness (tree->name.name);
4722159047fSniklas       else
4732159047fSniklas 	{
4742159047fSniklas 	  struct bfd_link_hash_entry *h;
475*007c2a45Smiod 	  int def_iteration
476*007c2a45Smiod 	    = lang_symbol_definition_iteration (tree->name.name);
4772159047fSniklas 
478191aa565Sniklas 	  h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
479191aa565Sniklas 					    tree->name.name,
480c074d1c9Sdrahn 					    FALSE, FALSE, TRUE);
481*007c2a45Smiod 	  result.value = (h != NULL
4822159047fSniklas 			  && (h->type == bfd_link_hash_defined
4832159047fSniklas 			      || h->type == bfd_link_hash_defweak
484*007c2a45Smiod 			      || h->type == bfd_link_hash_common)
485*007c2a45Smiod 			  && (def_iteration == lang_statement_iteration
486*007c2a45Smiod 			      || def_iteration == -1));
487*007c2a45Smiod 	  result.section = abs_output_section;
488c074d1c9Sdrahn 	  result.valid_p = TRUE;
4892159047fSniklas 	}
4902159047fSniklas       break;
4912159047fSniklas     case NAME:
4922159047fSniklas       if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
4932159047fSniklas 	{
4942159047fSniklas 	  if (allocation_done != lang_first_phase_enum)
4952159047fSniklas 	    result = new_rel_from_section (dot, current_section);
4962159047fSniklas 	}
4972159047fSniklas       else if (allocation_done != lang_first_phase_enum)
4982159047fSniklas 	{
4992159047fSniklas 	  struct bfd_link_hash_entry *h;
5002159047fSniklas 
501191aa565Sniklas 	  h = bfd_wrapped_link_hash_lookup (output_bfd, &link_info,
502191aa565Sniklas 					    tree->name.name,
503*007c2a45Smiod 					    TRUE, FALSE, TRUE);
504*007c2a45Smiod 	  if (!h)
505*007c2a45Smiod 	    einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n"));
506*007c2a45Smiod 	  else if (h->type == bfd_link_hash_defined
507*007c2a45Smiod 		   || h->type == bfd_link_hash_defweak)
5082159047fSniklas 	    {
5092159047fSniklas 	      if (bfd_is_abs_section (h->u.def.section))
5102159047fSniklas 		result = new_abs (h->u.def.value);
511191aa565Sniklas 	      else if (allocation_done == lang_final_phase_enum
512191aa565Sniklas 		       || allocation_done == lang_allocating_phase_enum)
5132159047fSniklas 		{
514b305b0f1Sespie 		  asection *output_section;
515b305b0f1Sespie 
516b305b0f1Sespie 		  output_section = h->u.def.section->output_section;
517b305b0f1Sespie 		  if (output_section == NULL)
518b305b0f1Sespie 		    einfo (_("%X%S: unresolvable symbol `%s' referenced in expression\n"),
519b305b0f1Sespie 			   tree->name.name);
520b305b0f1Sespie 		  else
521b305b0f1Sespie 		    {
5222159047fSniklas 		      lang_output_section_statement_type *os;
5232159047fSniklas 
5242159047fSniklas 		      os = (lang_output_section_statement_lookup
525b305b0f1Sespie 			    (bfd_get_section_name (output_bfd,
526b305b0f1Sespie 						   output_section)));
5272159047fSniklas 
528b305b0f1Sespie 		      /* FIXME: Is this correct if this section is
529b305b0f1Sespie 			 being linked with -R?  */
5302159047fSniklas 		      result = new_rel ((h->u.def.value
5312159047fSniklas 					 + h->u.def.section->output_offset),
532c074d1c9Sdrahn 					NULL,
5332159047fSniklas 					os);
5342159047fSniklas 		    }
5352159047fSniklas 		}
536b305b0f1Sespie 	    }
5372159047fSniklas 	  else if (allocation_done == lang_final_phase_enum)
538b305b0f1Sespie 	    einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
5392159047fSniklas 		   tree->name.name);
540*007c2a45Smiod 	  else if (h->type == bfd_link_hash_new)
541*007c2a45Smiod 	    {
542*007c2a45Smiod 	      h->type = bfd_link_hash_undefined;
543*007c2a45Smiod 	      h->u.undef.abfd = NULL;
544*007c2a45Smiod 	      bfd_link_add_undef (link_info.hash, h);
545*007c2a45Smiod 	    }
5462159047fSniklas 	}
5472159047fSniklas       break;
5482159047fSniklas 
5492159047fSniklas     case ADDR:
5500c6d0228Sniklas       if (allocation_done != lang_first_phase_enum)
5510c6d0228Sniklas 	{
5520c6d0228Sniklas 	  lang_output_section_statement_type *os;
5532159047fSniklas 
5540c6d0228Sniklas 	  os = lang_output_section_find (tree->name.name);
555*007c2a45Smiod 	  if (os && os->processed > 0)
556c074d1c9Sdrahn 	    result = new_rel (0, NULL, os);
5572159047fSniklas 	}
5582159047fSniklas       break;
5590c6d0228Sniklas 
5600c6d0228Sniklas     case LOADADDR:
5610c6d0228Sniklas       if (allocation_done != lang_first_phase_enum)
5620c6d0228Sniklas 	{
5630c6d0228Sniklas 	  lang_output_section_statement_type *os;
5640c6d0228Sniklas 
5650c6d0228Sniklas 	  os = lang_output_section_find (tree->name.name);
566*007c2a45Smiod 	  if (os && os->processed != 0)
567*007c2a45Smiod 	    {
5680c6d0228Sniklas 	      if (os->load_base == NULL)
569c074d1c9Sdrahn 		result = new_rel (0, NULL, os);
5700c6d0228Sniklas 	      else
5710c6d0228Sniklas 		result = exp_fold_tree_no_dot (os->load_base,
5720c6d0228Sniklas 					       abs_output_section,
5730c6d0228Sniklas 					       allocation_done);
5742159047fSniklas 	    }
575*007c2a45Smiod 	}
5760c6d0228Sniklas       break;
5770c6d0228Sniklas 
5780c6d0228Sniklas     case SIZEOF:
5790c6d0228Sniklas       if (allocation_done != lang_first_phase_enum)
5800c6d0228Sniklas 	{
581b305b0f1Sespie 	  int opb = bfd_octets_per_byte (output_bfd);
5820c6d0228Sniklas 	  lang_output_section_statement_type *os;
5830c6d0228Sniklas 
5840c6d0228Sniklas 	  os = lang_output_section_find (tree->name.name);
585*007c2a45Smiod 	  if (os && os->processed > 0)
586b305b0f1Sespie 	    result = new_abs (os->bfd_section->_raw_size / opb);
5872159047fSniklas 	}
5882159047fSniklas       break;
5892159047fSniklas 
5902159047fSniklas     default:
5912159047fSniklas       FAIL ();
5922159047fSniklas       break;
5932159047fSniklas     }
5942159047fSniklas 
5952159047fSniklas   return result;
5962159047fSniklas }
597b55d4692Sfgsch 
5982159047fSniklas etree_value_type
exp_fold_tree(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done,bfd_vma dot,bfd_vma * dotp)599*007c2a45Smiod exp_fold_tree (etree_type *tree,
600*007c2a45Smiod 	       lang_output_section_statement_type *current_section,
601*007c2a45Smiod 	       lang_phase_type allocation_done,
602*007c2a45Smiod 	       bfd_vma dot,
603*007c2a45Smiod 	       bfd_vma *dotp)
6042159047fSniklas {
6052159047fSniklas   etree_value_type result;
6062159047fSniklas 
6070c6d0228Sniklas   if (tree == NULL)
6080c6d0228Sniklas     {
609c074d1c9Sdrahn       result.valid_p = FALSE;
6100c6d0228Sniklas       return result;
6112159047fSniklas     }
6120c6d0228Sniklas 
6132159047fSniklas   switch (tree->type.node_class)
6142159047fSniklas     {
6152159047fSniklas     case etree_value:
616c074d1c9Sdrahn       result = new_rel (tree->value.value, tree->value.str, current_section);
6172159047fSniklas       break;
6180c6d0228Sniklas 
6192159047fSniklas     case etree_rel:
6202159047fSniklas       if (allocation_done != lang_final_phase_enum)
621c074d1c9Sdrahn 	result.valid_p = FALSE;
6222159047fSniklas       else
6232159047fSniklas 	result = new_rel ((tree->rel.value
6242159047fSniklas 			   + tree->rel.section->output_section->vma
6252159047fSniklas 			   + tree->rel.section->output_offset),
626c074d1c9Sdrahn 			  NULL,
6272159047fSniklas 			  current_section);
6282159047fSniklas       break;
6290c6d0228Sniklas 
630b305b0f1Sespie     case etree_assert:
631b305b0f1Sespie       result = exp_fold_tree (tree->assert_s.child,
632b305b0f1Sespie 			      current_section,
633b305b0f1Sespie 			      allocation_done, dot, dotp);
634b305b0f1Sespie       if (result.valid_p)
635b305b0f1Sespie 	{
636b305b0f1Sespie 	  if (! result.value)
637b305b0f1Sespie 	    einfo ("%F%P: %s\n", tree->assert_s.message);
638b305b0f1Sespie 	  return result;
639b305b0f1Sespie 	}
640b305b0f1Sespie       break;
641b305b0f1Sespie 
6422159047fSniklas     case etree_unary:
643c074d1c9Sdrahn       result = fold_unary (tree, current_section, allocation_done,
644c074d1c9Sdrahn 			   dot, dotp);
6452159047fSniklas       break;
6460c6d0228Sniklas 
6472159047fSniklas     case etree_binary:
6482159047fSniklas       result = fold_binary (tree, current_section, allocation_done,
6492159047fSniklas 			    dot, dotp);
6502159047fSniklas       break;
6510c6d0228Sniklas 
652c074d1c9Sdrahn     case etree_trinary:
653c074d1c9Sdrahn       result = fold_trinary (tree, current_section, allocation_done,
654c074d1c9Sdrahn 			     dot, dotp);
655c074d1c9Sdrahn       break;
656c074d1c9Sdrahn 
6572159047fSniklas     case etree_assign:
6582159047fSniklas     case etree_provide:
659b55d4692Sfgsch     case etree_provided:
6600c6d0228Sniklas       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
6610c6d0228Sniklas 	{
662c074d1c9Sdrahn 	  /* Assignment to dot can only be done during allocation.  */
663b55d4692Sfgsch 	  if (tree->type.node_class != etree_assign)
664b305b0f1Sespie 	    einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
665191aa565Sniklas 	  if (allocation_done == lang_allocating_phase_enum
666191aa565Sniklas 	      || (allocation_done == lang_final_phase_enum
6670c6d0228Sniklas 		  && current_section == abs_output_section))
6680c6d0228Sniklas 	    {
6692159047fSniklas 	      result = exp_fold_tree (tree->assign.src,
6702159047fSniklas 				      current_section,
671c074d1c9Sdrahn 				      allocation_done, dot,
6720c6d0228Sniklas 				      dotp);
673b305b0f1Sespie 	      if (! result.valid_p)
674b305b0f1Sespie 		einfo (_("%F%S invalid assignment to location counter\n"));
6750c6d0228Sniklas 	      else
6760c6d0228Sniklas 		{
6770c6d0228Sniklas 		  if (current_section == NULL)
678b305b0f1Sespie 		    einfo (_("%F%S assignment to location counter invalid outside of SECTION\n"));
6790c6d0228Sniklas 		  else
6800c6d0228Sniklas 		    {
6810c6d0228Sniklas 		      bfd_vma nextdot;
6820c6d0228Sniklas 
6830c6d0228Sniklas 		      nextdot = (result.value
6840c6d0228Sniklas 				 + current_section->bfd_section->vma);
6850c6d0228Sniklas 		      if (nextdot < dot
6860c6d0228Sniklas 			  && current_section != abs_output_section)
687b305b0f1Sespie 			einfo (_("%F%S cannot move location counter backwards (from %V to %V)\n"),
6880c6d0228Sniklas 			       dot, nextdot);
6890c6d0228Sniklas 		      else
6902159047fSniklas 			*dotp = nextdot;
6912159047fSniklas 		    }
6922159047fSniklas 		}
6932159047fSniklas 	    }
6942159047fSniklas 	}
6952159047fSniklas       else
6962159047fSniklas 	{
6972159047fSniklas 	  result = exp_fold_tree (tree->assign.src,
6982159047fSniklas 				  current_section, allocation_done,
6992159047fSniklas 				  dot, dotp);
700b305b0f1Sespie 	  if (result.valid_p)
7012159047fSniklas 	    {
702c074d1c9Sdrahn 	      bfd_boolean create;
7032159047fSniklas 	      struct bfd_link_hash_entry *h;
7042159047fSniklas 
7050c6d0228Sniklas 	      if (tree->type.node_class == etree_assign)
706c074d1c9Sdrahn 		create = TRUE;
7070c6d0228Sniklas 	      else
708c074d1c9Sdrahn 		create = FALSE;
7092159047fSniklas 	      h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
710*007c2a45Smiod 					create, FALSE, TRUE);
711*007c2a45Smiod 	      if (h == NULL)
7122159047fSniklas 		{
713*007c2a45Smiod 		  if (create)
714b305b0f1Sespie 		    einfo (_("%P%F:%s: hash creation failed\n"),
7152159047fSniklas 			   tree->assign.dst);
7162159047fSniklas 		}
7172159047fSniklas 	      else if (tree->type.node_class == etree_provide
718*007c2a45Smiod 		       && h->type != bfd_link_hash_new
7192159047fSniklas 		       && h->type != bfd_link_hash_undefined
7202159047fSniklas 		       && h->type != bfd_link_hash_common)
7212159047fSniklas 		{
7222159047fSniklas 		  /* Do nothing.  The symbol was defined by some
7232159047fSniklas 		     object.  */
7242159047fSniklas 		}
7252159047fSniklas 	      else
7262159047fSniklas 		{
7272159047fSniklas 		  /* FIXME: Should we worry if the symbol is already
7282159047fSniklas 		     defined?  */
729*007c2a45Smiod 		  lang_update_definedness (tree->assign.dst, h);
7302159047fSniklas 		  h->type = bfd_link_hash_defined;
7312159047fSniklas 		  h->u.def.value = result.value;
7322159047fSniklas 		  h->u.def.section = result.section->bfd_section;
733b55d4692Sfgsch 		  if (tree->type.node_class == etree_provide)
734b55d4692Sfgsch 		    tree->type.node_class = etree_provided;
7352159047fSniklas 		}
7362159047fSniklas 	    }
7372159047fSniklas 	}
7382159047fSniklas       break;
7390c6d0228Sniklas 
7402159047fSniklas     case etree_name:
7412159047fSniklas       result = fold_name (tree, current_section, allocation_done, dot);
7422159047fSniklas       break;
7432159047fSniklas 
7440c6d0228Sniklas     default:
7450c6d0228Sniklas       FAIL ();
7460c6d0228Sniklas       break;
7472159047fSniklas     }
7482159047fSniklas 
7492159047fSniklas   return result;
7502159047fSniklas }
7512159047fSniklas 
7522159047fSniklas static etree_value_type
exp_fold_tree_no_dot(etree_type * tree,lang_output_section_statement_type * current_section,lang_phase_type allocation_done)753*007c2a45Smiod exp_fold_tree_no_dot (etree_type *tree,
754*007c2a45Smiod 		      lang_output_section_statement_type *current_section,
755*007c2a45Smiod 		      lang_phase_type allocation_done)
7562159047fSniklas {
757*007c2a45Smiod   return exp_fold_tree (tree, current_section, allocation_done, 0, NULL);
7582159047fSniklas }
7592159047fSniklas 
7602159047fSniklas etree_type *
exp_binop(int code,etree_type * lhs,etree_type * rhs)761*007c2a45Smiod exp_binop (int code, etree_type *lhs, etree_type *rhs)
7622159047fSniklas {
7632159047fSniklas   etree_type value, *new;
7642159047fSniklas   etree_value_type r;
7652159047fSniklas 
7662159047fSniklas   value.type.node_code = code;
7672159047fSniklas   value.binary.lhs = lhs;
7682159047fSniklas   value.binary.rhs = rhs;
7692159047fSniklas   value.type.node_class = etree_binary;
7702159047fSniklas   r = exp_fold_tree_no_dot (&value,
7712159047fSniklas 			    abs_output_section,
7722159047fSniklas 			    lang_first_phase_enum);
773b305b0f1Sespie   if (r.valid_p)
7742159047fSniklas     {
7752159047fSniklas       return exp_intop (r.value);
7762159047fSniklas     }
777*007c2a45Smiod   new = stat_alloc (sizeof (new->binary));
778*007c2a45Smiod   memcpy (new, &value, sizeof (new->binary));
7792159047fSniklas   return new;
7802159047fSniklas }
7812159047fSniklas 
7822159047fSniklas etree_type *
exp_trinop(int code,etree_type * cond,etree_type * lhs,etree_type * rhs)783*007c2a45Smiod exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
7842159047fSniklas {
7852159047fSniklas   etree_type value, *new;
7862159047fSniklas   etree_value_type r;
7872159047fSniklas   value.type.node_code = code;
7882159047fSniklas   value.trinary.lhs = lhs;
7892159047fSniklas   value.trinary.cond = cond;
7902159047fSniklas   value.trinary.rhs = rhs;
7912159047fSniklas   value.type.node_class = etree_trinary;
792*007c2a45Smiod   r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
793b55d4692Sfgsch   if (r.valid_p)
7942159047fSniklas     return exp_intop (r.value);
795c074d1c9Sdrahn 
796*007c2a45Smiod   new = stat_alloc (sizeof (new->trinary));
797*007c2a45Smiod   memcpy (new, &value, sizeof (new->trinary));
7982159047fSniklas   return new;
7992159047fSniklas }
8002159047fSniklas 
8012159047fSniklas etree_type *
exp_unop(int code,etree_type * child)802*007c2a45Smiod exp_unop (int code, etree_type *child)
8032159047fSniklas {
8042159047fSniklas   etree_type value, *new;
8052159047fSniklas 
8062159047fSniklas   etree_value_type r;
8072159047fSniklas   value.unary.type.node_code = code;
8082159047fSniklas   value.unary.child = child;
8092159047fSniklas   value.unary.type.node_class = etree_unary;
8102159047fSniklas   r = exp_fold_tree_no_dot (&value, abs_output_section,
8112159047fSniklas 			    lang_first_phase_enum);
812b55d4692Sfgsch   if (r.valid_p)
8132159047fSniklas     return exp_intop (r.value);
814c074d1c9Sdrahn 
815*007c2a45Smiod   new = stat_alloc (sizeof (new->unary));
816*007c2a45Smiod   memcpy (new, &value, sizeof (new->unary));
8172159047fSniklas   return new;
8182159047fSniklas }
8192159047fSniklas 
8202159047fSniklas etree_type *
exp_nameop(int code,const char * name)821*007c2a45Smiod exp_nameop (int code, const char *name)
8222159047fSniklas {
8232159047fSniklas   etree_type value, *new;
8242159047fSniklas   etree_value_type r;
8252159047fSniklas   value.name.type.node_code = code;
8262159047fSniklas   value.name.name = name;
8272159047fSniklas   value.name.type.node_class = etree_name;
8282159047fSniklas 
829*007c2a45Smiod   r = exp_fold_tree_no_dot (&value, NULL, lang_first_phase_enum);
830b55d4692Sfgsch   if (r.valid_p)
8312159047fSniklas     return exp_intop (r.value);
832c074d1c9Sdrahn 
833*007c2a45Smiod   new = stat_alloc (sizeof (new->name));
834*007c2a45Smiod   memcpy (new, &value, sizeof (new->name));
8352159047fSniklas   return new;
8362159047fSniklas 
8372159047fSniklas }
8382159047fSniklas 
8392159047fSniklas etree_type *
exp_assop(int code,const char * dst,etree_type * src)840*007c2a45Smiod exp_assop (int code, const char *dst, etree_type *src)
8412159047fSniklas {
8422159047fSniklas   etree_type value, *new;
8432159047fSniklas 
8442159047fSniklas   value.assign.type.node_code = code;
8452159047fSniklas 
8462159047fSniklas   value.assign.src = src;
8472159047fSniklas   value.assign.dst = dst;
8482159047fSniklas   value.assign.type.node_class = etree_assign;
8492159047fSniklas 
8502159047fSniklas #if 0
851b55d4692Sfgsch   if (exp_fold_tree_no_dot (&value, &result))
8522159047fSniklas     return exp_intop (result);
8532159047fSniklas #endif
854*007c2a45Smiod   new = stat_alloc (sizeof (new->assign));
855*007c2a45Smiod   memcpy (new, &value, sizeof (new->assign));
8562159047fSniklas   return new;
8572159047fSniklas }
8582159047fSniklas 
8592159047fSniklas /* Handle PROVIDE.  */
8602159047fSniklas 
8612159047fSniklas etree_type *
exp_provide(const char * dst,etree_type * src)862*007c2a45Smiod exp_provide (const char *dst, etree_type *src)
8632159047fSniklas {
8642159047fSniklas   etree_type *n;
8652159047fSniklas 
866*007c2a45Smiod   n = stat_alloc (sizeof (n->assign));
8672159047fSniklas   n->assign.type.node_code = '=';
8682159047fSniklas   n->assign.type.node_class = etree_provide;
8692159047fSniklas   n->assign.src = src;
8702159047fSniklas   n->assign.dst = dst;
8712159047fSniklas   return n;
8722159047fSniklas }
8732159047fSniklas 
874b305b0f1Sespie /* Handle ASSERT.  */
875b305b0f1Sespie 
876b305b0f1Sespie etree_type *
exp_assert(etree_type * exp,const char * message)877*007c2a45Smiod exp_assert (etree_type *exp, const char *message)
878b305b0f1Sespie {
879b305b0f1Sespie   etree_type *n;
880b305b0f1Sespie 
881*007c2a45Smiod   n = stat_alloc (sizeof (n->assert_s));
882b305b0f1Sespie   n->assert_s.type.node_code = '!';
883b305b0f1Sespie   n->assert_s.type.node_class = etree_assert;
884b305b0f1Sespie   n->assert_s.child = exp;
885b305b0f1Sespie   n->assert_s.message = message;
886b305b0f1Sespie   return n;
887b305b0f1Sespie }
888b305b0f1Sespie 
8892159047fSniklas void
exp_print_tree(etree_type * tree)890*007c2a45Smiod exp_print_tree (etree_type *tree)
8912159047fSniklas {
892c074d1c9Sdrahn   if (config.map_file == NULL)
893c074d1c9Sdrahn     config.map_file = stderr;
894c074d1c9Sdrahn 
895c074d1c9Sdrahn   if (tree == NULL)
896c074d1c9Sdrahn     {
897c074d1c9Sdrahn       minfo ("NULL TREE\n");
898c074d1c9Sdrahn       return;
899c074d1c9Sdrahn     }
900c074d1c9Sdrahn 
901b55d4692Sfgsch   switch (tree->type.node_class)
902b55d4692Sfgsch     {
9032159047fSniklas     case etree_value:
904191aa565Sniklas       minfo ("0x%v", tree->value.value);
9052159047fSniklas       return;
9062159047fSniklas     case etree_rel:
9072159047fSniklas       if (tree->rel.section->owner != NULL)
908191aa565Sniklas 	minfo ("%B:", tree->rel.section->owner);
909191aa565Sniklas       minfo ("%s+0x%v", tree->rel.section->name, tree->rel.value);
9102159047fSniklas       return;
9112159047fSniklas     case etree_assign:
9122159047fSniklas #if 0
913*007c2a45Smiod       if (tree->assign.dst->sdefs != NULL)
9142159047fSniklas 	fprintf (config.map_file, "%s (%x) ", tree->assign.dst->name,
9152159047fSniklas 		 tree->assign.dst->sdefs->value);
916b55d4692Sfgsch       else
9172159047fSniklas 	fprintf (config.map_file, "%s (UNDEFINED)", tree->assign.dst->name);
9182159047fSniklas #endif
9192159047fSniklas       fprintf (config.map_file, "%s", tree->assign.dst);
920c074d1c9Sdrahn       exp_print_token (tree->type.node_code, TRUE);
9212159047fSniklas       exp_print_tree (tree->assign.src);
9222159047fSniklas       break;
9232159047fSniklas     case etree_provide:
924b55d4692Sfgsch     case etree_provided:
9252159047fSniklas       fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
9262159047fSniklas       exp_print_tree (tree->assign.src);
9272159047fSniklas       fprintf (config.map_file, ")");
9282159047fSniklas       break;
9292159047fSniklas     case etree_binary:
9302159047fSniklas       fprintf (config.map_file, "(");
9312159047fSniklas       exp_print_tree (tree->binary.lhs);
932c074d1c9Sdrahn       exp_print_token (tree->type.node_code, TRUE);
9332159047fSniklas       exp_print_tree (tree->binary.rhs);
9342159047fSniklas       fprintf (config.map_file, ")");
9352159047fSniklas       break;
9362159047fSniklas     case etree_trinary:
9372159047fSniklas       exp_print_tree (tree->trinary.cond);
9382159047fSniklas       fprintf (config.map_file, "?");
9392159047fSniklas       exp_print_tree (tree->trinary.lhs);
9402159047fSniklas       fprintf (config.map_file, ":");
9412159047fSniklas       exp_print_tree (tree->trinary.rhs);
9422159047fSniklas       break;
9432159047fSniklas     case etree_unary:
944c074d1c9Sdrahn       exp_print_token (tree->unary.type.node_code, FALSE);
9452159047fSniklas       if (tree->unary.child)
9462159047fSniklas 	{
9472159047fSniklas 	  fprintf (config.map_file, " (");
9482159047fSniklas 	  exp_print_tree (tree->unary.child);
9492159047fSniklas 	  fprintf (config.map_file, ")");
9502159047fSniklas 	}
9512159047fSniklas       break;
952b305b0f1Sespie 
953b305b0f1Sespie     case etree_assert:
954b305b0f1Sespie       fprintf (config.map_file, "ASSERT (");
955b305b0f1Sespie       exp_print_tree (tree->assert_s.child);
956b305b0f1Sespie       fprintf (config.map_file, ", %s)", tree->assert_s.message);
957b305b0f1Sespie       break;
958b305b0f1Sespie 
9592159047fSniklas     case etree_undef:
9602159047fSniklas       fprintf (config.map_file, "????????");
9612159047fSniklas       break;
9622159047fSniklas     case etree_name:
963b55d4692Sfgsch       if (tree->type.node_code == NAME)
964b55d4692Sfgsch 	{
9652159047fSniklas 	  fprintf (config.map_file, "%s", tree->name.name);
9662159047fSniklas 	}
967b55d4692Sfgsch       else
968b55d4692Sfgsch 	{
969c074d1c9Sdrahn 	  exp_print_token (tree->type.node_code, FALSE);
9702159047fSniklas 	  if (tree->name.name)
9712159047fSniklas 	    fprintf (config.map_file, " (%s)", tree->name.name);
9722159047fSniklas 	}
9732159047fSniklas       break;
9742159047fSniklas     default:
9752159047fSniklas       FAIL ();
9762159047fSniklas       break;
9772159047fSniklas     }
9782159047fSniklas }
9792159047fSniklas 
9802159047fSniklas bfd_vma
exp_get_vma(etree_type * tree,bfd_vma def,char * name,lang_phase_type allocation_done)981*007c2a45Smiod exp_get_vma (etree_type *tree,
982*007c2a45Smiod 	     bfd_vma def,
983*007c2a45Smiod 	     char *name,
984*007c2a45Smiod 	     lang_phase_type allocation_done)
9852159047fSniklas {
9862159047fSniklas   etree_value_type r;
9872159047fSniklas 
9880c6d0228Sniklas   if (tree != NULL)
9890c6d0228Sniklas     {
9900c6d0228Sniklas       r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
991b305b0f1Sespie       if (! r.valid_p && name != NULL)
992b305b0f1Sespie 	einfo (_("%F%S nonconstant expression for %s\n"), name);
9932159047fSniklas       return r.value;
9942159047fSniklas     }
9950c6d0228Sniklas   else
9962159047fSniklas     return def;
9972159047fSniklas }
9982159047fSniklas 
9992159047fSniklas int
exp_get_value_int(etree_type * tree,int def,char * name,lang_phase_type allocation_done)1000*007c2a45Smiod exp_get_value_int (etree_type *tree,
1001*007c2a45Smiod 		   int def,
1002*007c2a45Smiod 		   char *name,
1003*007c2a45Smiod 		   lang_phase_type allocation_done)
10042159047fSniklas {
1005*007c2a45Smiod   return exp_get_vma (tree, def, name, allocation_done);
10062159047fSniklas }
10072159047fSniklas 
1008c074d1c9Sdrahn fill_type *
exp_get_fill(etree_type * tree,fill_type * def,char * name,lang_phase_type allocation_done)1009*007c2a45Smiod exp_get_fill (etree_type *tree,
1010*007c2a45Smiod 	      fill_type *def,
1011*007c2a45Smiod 	      char *name,
1012*007c2a45Smiod 	      lang_phase_type allocation_done)
1013c074d1c9Sdrahn {
1014c074d1c9Sdrahn   fill_type *fill;
1015c074d1c9Sdrahn   etree_value_type r;
1016c074d1c9Sdrahn   size_t len;
1017c074d1c9Sdrahn   unsigned int val;
1018c074d1c9Sdrahn 
1019c074d1c9Sdrahn   if (tree == NULL)
1020c074d1c9Sdrahn     return def;
1021c074d1c9Sdrahn 
1022c074d1c9Sdrahn   r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
1023c074d1c9Sdrahn   if (! r.valid_p && name != NULL)
1024c074d1c9Sdrahn     einfo (_("%F%S nonconstant expression for %s\n"), name);
1025c074d1c9Sdrahn 
1026c074d1c9Sdrahn   if (r.str != NULL && (len = strlen (r.str)) != 0)
1027c074d1c9Sdrahn     {
1028c074d1c9Sdrahn       unsigned char *dst;
1029c074d1c9Sdrahn       unsigned char *s;
1030*007c2a45Smiod       fill = xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
1031c074d1c9Sdrahn       fill->size = (len + 1) / 2;
1032c074d1c9Sdrahn       dst = fill->data;
1033c074d1c9Sdrahn       s = r.str;
1034c074d1c9Sdrahn       val = 0;
1035c074d1c9Sdrahn       do
1036c074d1c9Sdrahn 	{
1037c074d1c9Sdrahn 	  unsigned int digit;
1038c074d1c9Sdrahn 
1039c074d1c9Sdrahn 	  digit = *s++ - '0';
1040c074d1c9Sdrahn 	  if (digit > 9)
1041c074d1c9Sdrahn 	    digit = (digit - 'A' + '0' + 10) & 0xf;
1042c074d1c9Sdrahn 	  val <<= 4;
1043c074d1c9Sdrahn 	  val += digit;
1044c074d1c9Sdrahn 	  --len;
1045c074d1c9Sdrahn 	  if ((len & 1) == 0)
1046c074d1c9Sdrahn 	    {
1047c074d1c9Sdrahn 	      *dst++ = val;
1048c074d1c9Sdrahn 	      val = 0;
1049c074d1c9Sdrahn 	    }
1050c074d1c9Sdrahn 	}
1051c074d1c9Sdrahn       while (len != 0);
1052c074d1c9Sdrahn     }
1053c074d1c9Sdrahn   else
1054c074d1c9Sdrahn     {
1055*007c2a45Smiod       fill = xmalloc (4 + sizeof (*fill) - 1);
1056c074d1c9Sdrahn       val = r.value;
1057c074d1c9Sdrahn       fill->data[0] = (val >> 24) & 0xff;
1058c074d1c9Sdrahn       fill->data[1] = (val >> 16) & 0xff;
1059c074d1c9Sdrahn       fill->data[2] = (val >>  8) & 0xff;
1060c074d1c9Sdrahn       fill->data[3] = (val >>  0) & 0xff;
1061c074d1c9Sdrahn       fill->size = 4;
1062c074d1c9Sdrahn     }
1063c074d1c9Sdrahn   return fill;
1064c074d1c9Sdrahn }
1065c074d1c9Sdrahn 
10662159047fSniklas bfd_vma
exp_get_abs_int(etree_type * tree,int def ATTRIBUTE_UNUSED,char * name,lang_phase_type allocation_done)1067*007c2a45Smiod exp_get_abs_int (etree_type *tree,
1068*007c2a45Smiod 		 int def ATTRIBUTE_UNUSED,
1069*007c2a45Smiod 		 char *name,
1070*007c2a45Smiod 		 lang_phase_type allocation_done)
10712159047fSniklas {
10722159047fSniklas   etree_value_type res;
10732159047fSniklas   res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
10742159047fSniklas 
1075b305b0f1Sespie   if (res.valid_p)
10762159047fSniklas     res.value += res.section->bfd_section->vma;
1077b55d4692Sfgsch   else
1078b305b0f1Sespie     einfo (_("%F%S non constant expression for %s\n"), name);
1079c074d1c9Sdrahn 
10802159047fSniklas   return res.value;
10812159047fSniklas }
1082c074d1c9Sdrahn 
1083*007c2a45Smiod static bfd_vma
align_n(bfd_vma value,bfd_vma align)1084*007c2a45Smiod align_n (bfd_vma value, bfd_vma align)
1085c074d1c9Sdrahn {
1086c074d1c9Sdrahn   if (align <= 1)
1087c074d1c9Sdrahn     return value;
1088c074d1c9Sdrahn 
1089c074d1c9Sdrahn   value = (value + align - 1) / align;
1090c074d1c9Sdrahn   return value * align;
1091c074d1c9Sdrahn }
1092