Line 1... |
Line 1... |
/* This module handles expression trees.
|
/* This module handles expression trees.
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
|
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
|
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
|
|
|
This file is part of the GNU Binutils.
|
This file is part of the GNU Binutils.
|
|
|
Line 154... |
Line 154... |
etree_type *
|
etree_type *
|
exp_intop (bfd_vma value)
|
exp_intop (bfd_vma value)
|
{
|
{
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
|
new_e->type.node_code = INT;
|
new_e->type.node_code = INT;
|
|
new_e->type.filename = ldlex_filename ();
|
new_e->type.lineno = lineno;
|
new_e->type.lineno = lineno;
|
new_e->value.value = value;
|
new_e->value.value = value;
|
new_e->value.str = NULL;
|
new_e->value.str = NULL;
|
new_e->type.node_class = etree_value;
|
new_e->type.node_class = etree_value;
|
return new_e;
|
return new_e;
|
Line 166... |
Line 167... |
etree_type *
|
etree_type *
|
exp_bigintop (bfd_vma value, char *str)
|
exp_bigintop (bfd_vma value, char *str)
|
{
|
{
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->value));
|
new_e->type.node_code = INT;
|
new_e->type.node_code = INT;
|
|
new_e->type.filename = ldlex_filename ();
|
new_e->type.lineno = lineno;
|
new_e->type.lineno = lineno;
|
new_e->value.value = value;
|
new_e->value.value = value;
|
new_e->value.str = str;
|
new_e->value.str = str;
|
new_e->type.node_class = etree_value;
|
new_e->type.node_class = etree_value;
|
return new_e;
|
return new_e;
|
Line 180... |
Line 182... |
etree_type *
|
etree_type *
|
exp_relop (asection *section, bfd_vma value)
|
exp_relop (asection *section, bfd_vma value)
|
{
|
{
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->rel));
|
etree_type *new_e = (etree_type *) stat_alloc (sizeof (new_e->rel));
|
new_e->type.node_code = REL;
|
new_e->type.node_code = REL;
|
|
new_e->type.filename = ldlex_filename ();
|
new_e->type.lineno = lineno;
|
new_e->type.lineno = lineno;
|
new_e->type.node_class = etree_rel;
|
new_e->type.node_class = etree_rel;
|
new_e->rel.section = section;
|
new_e->rel.section = section;
|
new_e->rel.value = value;
|
new_e->rel.value = value;
|
return new_e;
|
return new_e;
|
Line 402... |
Line 405... |
case '%':
|
case '%':
|
if (expld.result.value != 0)
|
if (expld.result.value != 0)
|
expld.result.value = ((bfd_signed_vma) lhs.value
|
expld.result.value = ((bfd_signed_vma) lhs.value
|
% (bfd_signed_vma) expld.result.value);
|
% (bfd_signed_vma) expld.result.value);
|
else if (expld.phase != lang_mark_phase_enum)
|
else if (expld.phase != lang_mark_phase_enum)
|
einfo (_("%F%S %% by zero\n"));
|
einfo (_("%F%S %% by zero\n"), tree->binary.rhs);
|
if (expld.result.section == lhs.section)
|
if (expld.result.section == lhs.section)
|
expld.result.section = NULL;
|
expld.result.section = NULL;
|
break;
|
break;
|
|
|
case '/':
|
case '/':
|
if (expld.result.value != 0)
|
if (expld.result.value != 0)
|
expld.result.value = ((bfd_signed_vma) lhs.value
|
expld.result.value = ((bfd_signed_vma) lhs.value
|
/ (bfd_signed_vma) expld.result.value);
|
/ (bfd_signed_vma) expld.result.value);
|
else if (expld.phase != lang_mark_phase_enum)
|
else if (expld.phase != lang_mark_phase_enum)
|
einfo (_("%F%S / by zero\n"));
|
einfo (_("%F%S / by zero\n"), tree->binary.rhs);
|
if (expld.result.section == lhs.section)
|
if (expld.result.section == lhs.section)
|
expld.result.section = NULL;
|
expld.result.section = NULL;
|
break;
|
break;
|
|
|
case MAX_K:
|
case MAX_K:
|
Line 585... |
Line 588... |
asection *output_section;
|
asection *output_section;
|
|
|
output_section = h->u.def.section->output_section;
|
output_section = h->u.def.section->output_section;
|
if (output_section == NULL)
|
if (output_section == NULL)
|
{
|
{
|
if (expld.phase != lang_mark_phase_enum)
|
if (expld.phase == lang_mark_phase_enum)
|
|
new_rel (h->u.def.value, h->u.def.section);
|
|
else
|
einfo (_("%X%S: unresolvable symbol `%s'"
|
einfo (_("%X%S: unresolvable symbol `%s'"
|
" referenced in expression\n"),
|
" referenced in expression\n"),
|
tree->name.name);
|
tree, tree->name.name);
|
}
|
}
|
else if (output_section == bfd_abs_section_ptr
|
else if (output_section == bfd_abs_section_ptr
|
&& (expld.section != bfd_abs_section_ptr
|
&& (expld.section != bfd_abs_section_ptr
|
|| config.sane_expr))
|
|| config.sane_expr))
|
new_number (h->u.def.value + h->u.def.section->output_offset);
|
new_number (h->u.def.value + h->u.def.section->output_offset);
|
Line 600... |
Line 605... |
new_rel (h->u.def.value + h->u.def.section->output_offset,
|
new_rel (h->u.def.value + h->u.def.section->output_offset,
|
output_section);
|
output_section);
|
}
|
}
|
else if (expld.phase == lang_final_phase_enum
|
else if (expld.phase == lang_final_phase_enum
|
|| expld.assigning_to_dot)
|
|| expld.assigning_to_dot)
|
einfo (_("%F%S: undefined symbol `%s' referenced in expression\n"),
|
einfo (_("%F%S: undefined symbol `%s'"
|
tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
else if (h->type == bfd_link_hash_new)
|
else if (h->type == bfd_link_hash_new)
|
{
|
{
|
h->type = bfd_link_hash_undefined;
|
h->type = bfd_link_hash_undefined;
|
h->u.undef.abfd = NULL;
|
h->u.undef.abfd = NULL;
|
if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
|
if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
|
Line 621... |
Line 627... |
|
|
os = lang_output_section_find (tree->name.name);
|
os = lang_output_section_find (tree->name.name);
|
if (os == NULL)
|
if (os == NULL)
|
{
|
{
|
if (expld.phase == lang_final_phase_enum)
|
if (expld.phase == lang_final_phase_enum)
|
einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
|
einfo (_("%F%S: undefined section `%s'"
|
tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
}
|
}
|
else if (os->processed_vma)
|
else if (os->processed_vma)
|
new_rel (0, os->bfd_section);
|
new_rel (0, os->bfd_section);
|
}
|
}
|
break;
|
break;
|
Line 638... |
Line 645... |
|
|
os = lang_output_section_find (tree->name.name);
|
os = lang_output_section_find (tree->name.name);
|
if (os == NULL)
|
if (os == NULL)
|
{
|
{
|
if (expld.phase == lang_final_phase_enum)
|
if (expld.phase == lang_final_phase_enum)
|
einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
|
einfo (_("%F%S: undefined section `%s'"
|
tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
}
|
}
|
else if (os->processed_lma)
|
else if (os->processed_lma)
|
{
|
{
|
if (os->load_base == NULL)
|
if (os->load_base == NULL)
|
new_abs (os->bfd_section->lma);
|
new_abs (os->bfd_section->lma);
|
Line 665... |
Line 673... |
|
|
os = lang_output_section_find (tree->name.name);
|
os = lang_output_section_find (tree->name.name);
|
if (os == NULL)
|
if (os == NULL)
|
{
|
{
|
if (expld.phase == lang_final_phase_enum)
|
if (expld.phase == lang_final_phase_enum)
|
einfo (_("%F%S: undefined section `%s' referenced in expression\n"),
|
einfo (_("%F%S: undefined section `%s'"
|
tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
new_number (0);
|
new_number (0);
|
}
|
}
|
else if (os->processed_vma)
|
else if (os->processed_vma)
|
{
|
{
|
bfd_vma val;
|
bfd_vma val;
|
Line 693... |
Line 702... |
mem = lang_memory_region_lookup (tree->name.name, FALSE);
|
mem = lang_memory_region_lookup (tree->name.name, FALSE);
|
if (mem != NULL)
|
if (mem != NULL)
|
new_number (mem->length);
|
new_number (mem->length);
|
else
|
else
|
einfo (_("%F%S: undefined MEMORY region `%s'"
|
einfo (_("%F%S: undefined MEMORY region `%s'"
|
" referenced in expression\n"), tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
}
|
}
|
break;
|
break;
|
|
|
case ORIGIN:
|
case ORIGIN:
|
if (expld.phase != lang_first_phase_enum)
|
if (expld.phase != lang_first_phase_enum)
|
Line 707... |
Line 717... |
mem = lang_memory_region_lookup (tree->name.name, FALSE);
|
mem = lang_memory_region_lookup (tree->name.name, FALSE);
|
if (mem != NULL)
|
if (mem != NULL)
|
new_rel_from_abs (mem->origin);
|
new_rel_from_abs (mem->origin);
|
else
|
else
|
einfo (_("%F%S: undefined MEMORY region `%s'"
|
einfo (_("%F%S: undefined MEMORY region `%s'"
|
" referenced in expression\n"), tree->name.name);
|
" referenced in expression\n"),
|
|
tree, tree->name.name);
|
}
|
}
|
break;
|
break;
|
|
|
case CONSTANT:
|
case CONSTANT:
|
if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
|
if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
|
new_number (config.maxpagesize);
|
new_number (config.maxpagesize);
|
else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
|
else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
|
new_number (config.commonpagesize);
|
new_number (config.commonpagesize);
|
else
|
else
|
einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
|
einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
|
tree->name.name);
|
tree, tree->name.name);
|
break;
|
break;
|
|
|
default:
|
default:
|
FAIL ();
|
FAIL ();
|
break;
|
break;
|
Line 782... |
Line 793... |
case etree_provide:
|
case etree_provide:
|
case etree_provided:
|
case etree_provided:
|
if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
|
if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
|
{
|
{
|
if (tree->type.node_class != etree_assign)
|
if (tree->type.node_class != etree_assign)
|
einfo (_("%F%S can not PROVIDE assignment to location counter\n"));
|
einfo (_("%F%S can not PROVIDE assignment to"
|
|
" location counter\n"), tree);
|
/* After allocation, assignment to dot should not be done inside
|
/* After allocation, assignment to dot should not be done inside
|
an output section since allocation adds a padding statement
|
an output section since allocation adds a padding statement
|
that effectively duplicates the assignment. */
|
that effectively duplicates the assignment. */
|
if (expld.phase == lang_mark_phase_enum
|
if (expld.phase == lang_mark_phase_enum
|
|| expld.phase == lang_allocating_phase_enum
|
|| expld.phase == lang_allocating_phase_enum
|
Line 800... |
Line 812... |
expld.assigning_to_dot = FALSE;
|
expld.assigning_to_dot = FALSE;
|
|
|
if (!expld.result.valid_p)
|
if (!expld.result.valid_p)
|
{
|
{
|
if (expld.phase != lang_mark_phase_enum)
|
if (expld.phase != lang_mark_phase_enum)
|
einfo (_("%F%S invalid assignment to location counter\n"));
|
einfo (_("%F%S invalid assignment to"
|
|
" location counter\n"), tree);
|
}
|
}
|
else if (expld.dotp == NULL)
|
else if (expld.dotp == NULL)
|
einfo (_("%F%S assignment to location counter"
|
einfo (_("%F%S assignment to location counter"
|
" invalid outside of SECTION\n"));
|
" invalid outside of SECTION\n"), tree);
|
else
|
else
|
{
|
{
|
bfd_vma nextdot;
|
bfd_vma nextdot;
|
|
|
nextdot = expld.result.value;
|
nextdot = expld.result.value;
|
Line 817... |
Line 830... |
else
|
else
|
nextdot += expld.section->vma;
|
nextdot += expld.section->vma;
|
if (nextdot < expld.dot
|
if (nextdot < expld.dot
|
&& expld.section != bfd_abs_section_ptr)
|
&& expld.section != bfd_abs_section_ptr)
|
einfo (_("%F%S cannot move location counter backwards"
|
einfo (_("%F%S cannot move location counter backwards"
|
" (from %V to %V)\n"), expld.dot, nextdot);
|
" (from %V to %V)\n"),
|
|
tree, expld.dot, nextdot);
|
else
|
else
|
{
|
{
|
expld.dot = nextdot;
|
expld.dot = nextdot;
|
*expld.dotp = nextdot;
|
*expld.dotp = nextdot;
|
}
|
}
|
Line 868... |
Line 882... |
pass. Folding does not preserve input sections. */
|
pass. Folding does not preserve input sections. */
|
break;
|
break;
|
|
|
exp_fold_tree_1 (tree->assign.src);
|
exp_fold_tree_1 (tree->assign.src);
|
if (expld.result.valid_p
|
if (expld.result.valid_p
|
|| (expld.phase == lang_first_phase_enum
|
|| (expld.phase <= lang_mark_phase_enum
|
&& tree->type.node_class == etree_assign
|
&& tree->type.node_class == etree_assign
|
&& tree->assign.hidden))
|
&& tree->assign.hidden))
|
{
|
{
|
if (h == NULL)
|
if (h == NULL)
|
{
|
{
|
Line 953... |
Line 967... |
exp_binop (int code, etree_type *lhs, etree_type *rhs)
|
exp_binop (int code, etree_type *lhs, etree_type *rhs)
|
{
|
{
|
etree_type value, *new_e;
|
etree_type value, *new_e;
|
|
|
value.type.node_code = code;
|
value.type.node_code = code;
|
|
value.type.filename = lhs->type.filename;
|
value.type.lineno = lhs->type.lineno;
|
value.type.lineno = lhs->type.lineno;
|
value.binary.lhs = lhs;
|
value.binary.lhs = lhs;
|
value.binary.rhs = rhs;
|
value.binary.rhs = rhs;
|
value.type.node_class = etree_binary;
|
value.type.node_class = etree_binary;
|
exp_fold_tree_no_dot (&value);
|
exp_fold_tree_no_dot (&value);
|
Line 972... |
Line 987... |
exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
|
exp_trinop (int code, etree_type *cond, etree_type *lhs, etree_type *rhs)
|
{
|
{
|
etree_type value, *new_e;
|
etree_type value, *new_e;
|
|
|
value.type.node_code = code;
|
value.type.node_code = code;
|
value.type.lineno = lhs->type.lineno;
|
value.type.filename = cond->type.filename;
|
|
value.type.lineno = cond->type.lineno;
|
value.trinary.lhs = lhs;
|
value.trinary.lhs = lhs;
|
value.trinary.cond = cond;
|
value.trinary.cond = cond;
|
value.trinary.rhs = rhs;
|
value.trinary.rhs = rhs;
|
value.type.node_class = etree_trinary;
|
value.type.node_class = etree_trinary;
|
exp_fold_tree_no_dot (&value);
|
exp_fold_tree_no_dot (&value);
|
Line 992... |
Line 1008... |
exp_unop (int code, etree_type *child)
|
exp_unop (int code, etree_type *child)
|
{
|
{
|
etree_type value, *new_e;
|
etree_type value, *new_e;
|
|
|
value.unary.type.node_code = code;
|
value.unary.type.node_code = code;
|
|
value.unary.type.filename = child->type.filename;
|
value.unary.type.lineno = child->type.lineno;
|
value.unary.type.lineno = child->type.lineno;
|
value.unary.child = child;
|
value.unary.child = child;
|
value.unary.type.node_class = etree_unary;
|
value.unary.type.node_class = etree_unary;
|
exp_fold_tree_no_dot (&value);
|
exp_fold_tree_no_dot (&value);
|
if (expld.result.valid_p)
|
if (expld.result.valid_p)
|
Line 1010... |
Line 1027... |
exp_nameop (int code, const char *name)
|
exp_nameop (int code, const char *name)
|
{
|
{
|
etree_type value, *new_e;
|
etree_type value, *new_e;
|
|
|
value.name.type.node_code = code;
|
value.name.type.node_code = code;
|
|
value.name.type.filename = ldlex_filename ();
|
value.name.type.lineno = lineno;
|
value.name.type.lineno = lineno;
|
value.name.name = name;
|
value.name.name = name;
|
value.name.type.node_class = etree_name;
|
value.name.type.node_class = etree_name;
|
|
|
exp_fold_tree_no_dot (&value);
|
exp_fold_tree_no_dot (&value);
|
Line 1034... |
Line 1052... |
{
|
{
|
etree_type *n;
|
etree_type *n;
|
|
|
n = (etree_type *) stat_alloc (sizeof (n->assign));
|
n = (etree_type *) stat_alloc (sizeof (n->assign));
|
n->assign.type.node_code = '=';
|
n->assign.type.node_code = '=';
|
|
n->assign.type.filename = src->type.filename;
|
n->assign.type.lineno = src->type.lineno;
|
n->assign.type.lineno = src->type.lineno;
|
n->assign.type.node_class = class;
|
n->assign.type.node_class = class;
|
n->assign.src = src;
|
n->assign.src = src;
|
n->assign.dst = dst;
|
n->assign.dst = dst;
|
n->assign.hidden = hidden;
|
n->assign.hidden = hidden;
|
Line 1071... |
Line 1090... |
{
|
{
|
etree_type *n;
|
etree_type *n;
|
|
|
n = (etree_type *) stat_alloc (sizeof (n->assert_s));
|
n = (etree_type *) stat_alloc (sizeof (n->assert_s));
|
n->assert_s.type.node_code = '!';
|
n->assert_s.type.node_code = '!';
|
|
n->assert_s.type.filename = exp->type.filename;
|
n->assert_s.type.lineno = exp->type.lineno;
|
n->assert_s.type.lineno = exp->type.lineno;
|
n->assert_s.type.node_class = etree_assert;
|
n->assert_s.type.node_class = etree_assert;
|
n->assert_s.child = exp;
|
n->assert_s.child = exp;
|
n->assert_s.message = message;
|
n->assert_s.message = message;
|
return n;
|
return n;
|
Line 1186... |
Line 1206... |
{
|
{
|
exp_fold_tree_no_dot (tree);
|
exp_fold_tree_no_dot (tree);
|
if (expld.result.valid_p)
|
if (expld.result.valid_p)
|
return expld.result.value;
|
return expld.result.value;
|
else if (name != NULL && expld.phase != lang_mark_phase_enum)
|
else if (name != NULL && expld.phase != lang_mark_phase_enum)
|
einfo (_("%F%S: nonconstant expression for %s\n"), name);
|
einfo (_("%F%S: nonconstant expression for %s\n"),
|
|
tree, name);
|
}
|
}
|
return def;
|
return def;
|
}
|
}
|
|
|
int
|
int
|
Line 1211... |
Line 1232... |
|
|
exp_fold_tree_no_dot (tree);
|
exp_fold_tree_no_dot (tree);
|
if (!expld.result.valid_p)
|
if (!expld.result.valid_p)
|
{
|
{
|
if (name != NULL && expld.phase != lang_mark_phase_enum)
|
if (name != NULL && expld.phase != lang_mark_phase_enum)
|
einfo (_("%F%S: nonconstant expression for %s\n"), name);
|
einfo (_("%F%S: nonconstant expression for %s\n"),
|
|
tree, name);
|
return def;
|
return def;
|
}
|
}
|
|
|
if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
|
if (expld.result.str != NULL && (len = strlen (expld.result.str)) != 0)
|
{
|
{
|
Line 1270... |
Line 1292... |
expld.result.value += expld.result.section->vma;
|
expld.result.value += expld.result.section->vma;
|
return expld.result.value;
|
return expld.result.value;
|
}
|
}
|
else if (name != NULL && expld.phase != lang_mark_phase_enum)
|
else if (name != NULL && expld.phase != lang_mark_phase_enum)
|
{
|
{
|
lineno = tree->type.lineno;
|
einfo (_("%F%S: nonconstant expression for %s\n"),
|
einfo (_("%F%S: nonconstant expression for %s\n"), name);
|
tree, name);
|
}
|
}
|
}
|
}
|
return def;
|
return def;
|
}
|
}
|
|
|