PR ld/14962
* ldexp.h (struct ldexp_control): Add "assign_name". * ldexp.c (fold_name <NAME>): Compare and clear assign_name on match. (exp_fold_tree_1): Remove existing code testing for self assignment. Instead set and test expld.assign_name. * ldlang.c (scan_for_self_assignment): Delete. (print_assignment): Instead set and test expld.assign_name.
This commit is contained in:
parent
faa7371af5
commit
4194268f43
10
ld/ChangeLog
10
ld/ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2012-12-17 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
PR ld/14962
|
||||||
|
* ldexp.h (struct ldexp_control): Add "assign_name".
|
||||||
|
* ldexp.c (fold_name <NAME>): Compare and clear assign_name on match.
|
||||||
|
(exp_fold_tree_1): Remove existing code testing for self assignment.
|
||||||
|
Instead set and test expld.assign_name.
|
||||||
|
* ldlang.c (scan_for_self_assignment): Delete.
|
||||||
|
(print_assignment): Instead set and test expld.assign_name.
|
||||||
|
|
||||||
2012-12-11 Roland McGrath <mcgrathr@google.com>
|
2012-12-11 Roland McGrath <mcgrathr@google.com>
|
||||||
|
|
||||||
* emulparams/elf_nacl.sh (nacl_rodata_addr): New shell function.
|
* emulparams/elf_nacl.sh (nacl_rodata_addr): New shell function.
|
||||||
|
37
ld/ldexp.c
37
ld/ldexp.c
@ -572,6 +572,9 @@ fold_name (etree_type *tree)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME:
|
case NAME:
|
||||||
|
if (expld.assign_name != NULL
|
||||||
|
&& strcmp (expld.assign_name, tree->name.name) == 0)
|
||||||
|
expld.assign_name = NULL;
|
||||||
if (expld.phase == lang_first_phase_enum)
|
if (expld.phase == lang_first_phase_enum)
|
||||||
;
|
;
|
||||||
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
|
else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
|
||||||
@ -852,8 +855,6 @@ exp_fold_tree_1 (etree_type *tree)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
etree_type *name;
|
|
||||||
|
|
||||||
struct bfd_link_hash_entry *h = NULL;
|
struct bfd_link_hash_entry *h = NULL;
|
||||||
|
|
||||||
if (tree->type.node_class == etree_provide)
|
if (tree->type.node_class == etree_provide)
|
||||||
@ -871,25 +872,20 @@ exp_fold_tree_1 (etree_type *tree)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name = tree->assign.src;
|
expld.assign_name = tree->assign.dst;
|
||||||
if (name->type.node_class == etree_trinary)
|
|
||||||
{
|
|
||||||
exp_fold_tree_1 (name->trinary.cond);
|
|
||||||
if (expld.result.valid_p)
|
|
||||||
name = (expld.result.value
|
|
||||||
? name->trinary.lhs : name->trinary.rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name->type.node_class == etree_name
|
|
||||||
&& name->type.node_code == NAME
|
|
||||||
&& strcmp (tree->assign.dst, name->name.name) == 0)
|
|
||||||
/* Leave it alone. Do not replace a symbol with its own
|
|
||||||
output address, in case there is another section sizing
|
|
||||||
pass. Folding does not preserve input sections. */
|
|
||||||
break;
|
|
||||||
|
|
||||||
exp_fold_tree_1 (tree->assign.src);
|
exp_fold_tree_1 (tree->assign.src);
|
||||||
if (expld.result.valid_p
|
/* expld.assign_name remaining equal to tree->assign.dst
|
||||||
|
below indicates the evaluation of tree->assign.src did
|
||||||
|
not use the value of tree->assign.dst. We don't allow
|
||||||
|
self assignment until the final phase for two reasons:
|
||||||
|
1) Expressions are evaluated multiple times. With
|
||||||
|
relaxation, the number of times may vary.
|
||||||
|
2) Section relative symbol values cannot be correctly
|
||||||
|
converted to absolute values, as is required by many
|
||||||
|
expressions, until final section sizing is complete. */
|
||||||
|
if ((expld.result.valid_p
|
||||||
|
&& (expld.phase == lang_final_phase_enum
|
||||||
|
|| expld.assign_name != NULL))
|
||||||
|| (expld.phase <= lang_mark_phase_enum
|
|| (expld.phase <= lang_mark_phase_enum
|
||||||
&& tree->type.node_class == etree_assign
|
&& tree->type.node_class == etree_assign
|
||||||
&& tree->assign.defsym))
|
&& tree->assign.defsym))
|
||||||
@ -937,6 +933,7 @@ exp_fold_tree_1 (etree_type *tree)
|
|||||||
&& h->type == bfd_link_hash_new)
|
&& h->type == bfd_link_hash_new)
|
||||||
h->type = bfd_link_hash_undefined;
|
h->type = bfd_link_hash_undefined;
|
||||||
}
|
}
|
||||||
|
expld.assign_name = NULL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -139,6 +139,11 @@ struct ldexp_control {
|
|||||||
|
|
||||||
/* Principally used for diagnostics. */
|
/* Principally used for diagnostics. */
|
||||||
bfd_boolean assigning_to_dot;
|
bfd_boolean assigning_to_dot;
|
||||||
|
/* If evaluating an assignment, the destination. Cleared if an
|
||||||
|
etree_name NAME matches this, to signal a self-assignment.
|
||||||
|
Note that an etree_name DEFINED does not clear this field, nor
|
||||||
|
does the false branch of a trinary expression. */
|
||||||
|
const char *assign_name;
|
||||||
|
|
||||||
/* Working results. */
|
/* Working results. */
|
||||||
etree_value_type result;
|
etree_value_type result;
|
||||||
|
59
ld/ldlang.c
59
ld/ldlang.c
@ -3951,63 +3951,12 @@ print_output_section_statement
|
|||||||
output_section_statement);
|
output_section_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan for the use of the destination in the right hand side
|
|
||||||
of an expression. In such cases we will not compute the
|
|
||||||
correct expression, since the value of DST that is used on
|
|
||||||
the right hand side will be its final value, not its value
|
|
||||||
just before this expression is evaluated. */
|
|
||||||
|
|
||||||
static bfd_boolean
|
|
||||||
scan_for_self_assignment (const char * dst, etree_type * rhs)
|
|
||||||
{
|
|
||||||
if (rhs == NULL || dst == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
switch (rhs->type.node_class)
|
|
||||||
{
|
|
||||||
case etree_binary:
|
|
||||||
return (scan_for_self_assignment (dst, rhs->binary.lhs)
|
|
||||||
|| scan_for_self_assignment (dst, rhs->binary.rhs));
|
|
||||||
|
|
||||||
case etree_trinary:
|
|
||||||
return (scan_for_self_assignment (dst, rhs->trinary.lhs)
|
|
||||||
|| scan_for_self_assignment (dst, rhs->trinary.rhs));
|
|
||||||
|
|
||||||
case etree_assign:
|
|
||||||
case etree_provided:
|
|
||||||
case etree_provide:
|
|
||||||
if (strcmp (dst, rhs->assign.dst) == 0)
|
|
||||||
return TRUE;
|
|
||||||
return scan_for_self_assignment (dst, rhs->assign.src);
|
|
||||||
|
|
||||||
case etree_unary:
|
|
||||||
return scan_for_self_assignment (dst, rhs->unary.child);
|
|
||||||
|
|
||||||
case etree_value:
|
|
||||||
if (rhs->value.str)
|
|
||||||
return strcmp (dst, rhs->value.str) == 0;
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
case etree_name:
|
|
||||||
if (rhs->name.name)
|
|
||||||
return strcmp (dst, rhs->name.name) == 0;
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_assignment (lang_assignment_statement_type *assignment,
|
print_assignment (lang_assignment_statement_type *assignment,
|
||||||
lang_output_section_statement_type *output_section)
|
lang_output_section_statement_type *output_section)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bfd_boolean is_dot;
|
bfd_boolean is_dot;
|
||||||
bfd_boolean computation_is_valid = TRUE;
|
|
||||||
etree_type *tree;
|
etree_type *tree;
|
||||||
asection *osec;
|
asection *osec;
|
||||||
|
|
||||||
@ -4018,15 +3967,14 @@ print_assignment (lang_assignment_statement_type *assignment,
|
|||||||
{
|
{
|
||||||
is_dot = FALSE;
|
is_dot = FALSE;
|
||||||
tree = assignment->exp->assert_s.child;
|
tree = assignment->exp->assert_s.child;
|
||||||
computation_is_valid = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char *dst = assignment->exp->assign.dst;
|
const char *dst = assignment->exp->assign.dst;
|
||||||
|
|
||||||
is_dot = (dst[0] == '.' && dst[1] == 0);
|
is_dot = (dst[0] == '.' && dst[1] == 0);
|
||||||
|
expld.assign_name = dst;
|
||||||
tree = assignment->exp->assign.src;
|
tree = assignment->exp->assign.src;
|
||||||
computation_is_valid = is_dot || !scan_for_self_assignment (dst, tree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osec = output_section->bfd_section;
|
osec = output_section->bfd_section;
|
||||||
@ -4037,7 +3985,9 @@ print_assignment (lang_assignment_statement_type *assignment,
|
|||||||
{
|
{
|
||||||
bfd_vma value;
|
bfd_vma value;
|
||||||
|
|
||||||
if (computation_is_valid)
|
if (assignment->exp->type.node_class == etree_assert
|
||||||
|
|| is_dot
|
||||||
|
|| expld.assign_name != NULL)
|
||||||
{
|
{
|
||||||
value = expld.result.value;
|
value = expld.result.value;
|
||||||
|
|
||||||
@ -4073,6 +4023,7 @@ print_assignment (lang_assignment_statement_type *assignment,
|
|||||||
minfo (" ");
|
minfo (" ");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
expld.assign_name = NULL;
|
||||||
|
|
||||||
minfo (" ");
|
minfo (" ");
|
||||||
exp_print_tree (assignment->exp);
|
exp_print_tree (assignment->exp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user