mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-09 04:21:49 +08:00
* config/tc-mmix.c (loc_asserts): New variable.
(mmix_greg_internal): Handle expressions not determinable at first pass. (s_loc): Ditto. Record expressions where the section isn't determinable at the first pass, and assume they don't refer to other sections. (mmix_md_end): Verify that recorded LOC expressions weren't to other sections, else emit error messages.
This commit is contained in:
parent
6ce7895693
commit
c3330fbecc
@ -1,3 +1,14 @@
|
||||
2012-08-14 Hans-Peter Nilsson <hp@bitrange.com>
|
||||
|
||||
* config/tc-mmix.c (loc_asserts): New variable.
|
||||
(mmix_greg_internal): Handle expressions not determinable at first
|
||||
pass.
|
||||
(s_loc): Ditto. Record expressions where the section isn't
|
||||
determinable at the first pass, and assume they don't refer to
|
||||
other sections.
|
||||
(mmix_md_end): Verify that recorded LOC expressions weren't
|
||||
to other sections, else emit error messages.
|
||||
|
||||
2012-08-13 Ian Bolton <ian.bolton@arm.com>
|
||||
Laurent Desnogues <laurent.desnogues@arm.com>
|
||||
Jim MacArthur <jim.macarthur@arm.com>
|
||||
|
@ -109,6 +109,13 @@ static struct
|
||||
expressionS exp;
|
||||
} mmix_raw_gregs[MAX_GREGS];
|
||||
|
||||
static struct loc_assert_s
|
||||
{
|
||||
segT old_seg;
|
||||
symbolS *loc_sym;
|
||||
struct loc_assert_s *next;
|
||||
} *loc_asserts = NULL;
|
||||
|
||||
/* Fixups for all unique GREG registers. We store the fixups here in
|
||||
md_convert_frag, then we use the array to convert
|
||||
BFD_RELOC_MMIX_BASE_PLUS_OFFSET fixups in tc_gen_reloc. The index is
|
||||
@ -1994,10 +2001,11 @@ static void
|
||||
mmix_greg_internal (char *label)
|
||||
{
|
||||
expressionS *expP = &mmix_raw_gregs[n_of_raw_gregs].exp;
|
||||
segT section;
|
||||
|
||||
/* Don't set the section to register contents section before the
|
||||
expression has been parsed; it may refer to the current position. */
|
||||
expression (expP);
|
||||
section = expression (expP);
|
||||
|
||||
/* FIXME: Check that no expression refers to the register contents
|
||||
section. May need to be done in elf64-mmix.c. */
|
||||
@ -2011,6 +2019,24 @@ mmix_greg_internal (char *label)
|
||||
expP->X_op_symbol = NULL;
|
||||
}
|
||||
|
||||
if (section == undefined_section)
|
||||
{
|
||||
/* This is an error or a LOC with an expression involving
|
||||
forward references. For the expression to be correctly
|
||||
evaluated, we need to force a proper symbol; gas loses track
|
||||
of the segment for "local symbols". */
|
||||
if (expP->X_op == O_add)
|
||||
{
|
||||
symbol_get_value_expression (expP->X_op_symbol);
|
||||
symbol_get_value_expression (expP->X_add_symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
gas_assert (expP->X_op == O_symbol);
|
||||
symbol_get_value_expression (expP->X_add_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
/* We must handle prefixes here, as we save the labels and expressions
|
||||
to be output later. */
|
||||
mmix_raw_gregs[n_of_raw_gregs].label
|
||||
@ -3457,6 +3483,7 @@ mmix_md_end (void)
|
||||
fragS *fragP;
|
||||
symbolS *mainsym;
|
||||
asection *regsec;
|
||||
struct loc_assert_s *loc_assert;
|
||||
int i;
|
||||
|
||||
/* The first frag of GREG:s going into the register contents section. */
|
||||
@ -3514,6 +3541,29 @@ mmix_md_end (void)
|
||||
S_SET_EXTERNAL (mainsym);
|
||||
}
|
||||
|
||||
/* Check that we didn't LOC into the unknown, or rather that when it
|
||||
was unknown, we actually change sections. */
|
||||
for (loc_assert = loc_asserts;
|
||||
loc_assert != NULL;
|
||||
loc_assert = loc_assert->next)
|
||||
{
|
||||
segT actual_seg;
|
||||
|
||||
resolve_symbol_value (loc_assert->loc_sym);
|
||||
actual_seg = S_GET_SEGMENT (loc_assert->loc_sym);
|
||||
if (actual_seg != loc_assert->old_seg)
|
||||
{
|
||||
char *fnam;
|
||||
unsigned int line;
|
||||
int e_valid = expr_symbol_where (loc_assert->loc_sym, &fnam, &line);
|
||||
|
||||
gas_assert (e_valid == 1);
|
||||
as_bad_where (fnam, line,
|
||||
_("LOC to section unknown or indeterminable "
|
||||
"at first pass"));
|
||||
}
|
||||
}
|
||||
|
||||
if (n_of_raw_gregs != 0)
|
||||
{
|
||||
/* Emit GREGs. They are collected in order of appearance, but must
|
||||
@ -3892,13 +3942,30 @@ s_loc (int ignore ATTRIBUTE_UNUSED)
|
||||
|
||||
if (exp.X_op == O_illegal
|
||||
|| exp.X_op == O_absent
|
||||
|| exp.X_op == O_big
|
||||
|| section == undefined_section)
|
||||
|| exp.X_op == O_big)
|
||||
{
|
||||
as_bad (_("invalid LOC expression"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (section == undefined_section)
|
||||
{
|
||||
/* This is an error or a LOC with an expression involving
|
||||
forward references. For the expression to be correctly
|
||||
evaluated, we need to force a proper symbol; gas loses track
|
||||
of the segment for "local symbols". */
|
||||
if (exp.X_op == O_add)
|
||||
{
|
||||
symbol_get_value_expression (exp.X_op_symbol);
|
||||
symbol_get_value_expression (exp.X_add_symbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
gas_assert (exp.X_op == O_symbol);
|
||||
symbol_get_value_expression (exp.X_add_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
if (section == absolute_section)
|
||||
{
|
||||
/* Translate a constant into a suitable section. */
|
||||
@ -3970,7 +4037,9 @@ s_loc (int ignore ATTRIBUTE_UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
if (section != now_seg)
|
||||
/* If we can't deduce the section, it must be the current one.
|
||||
Below, we arrange to assert this. */
|
||||
if (section != now_seg && section != undefined_section)
|
||||
{
|
||||
obj_elf_section_change_hook ();
|
||||
subseg_set (section, 0);
|
||||
@ -3981,16 +4050,41 @@ s_loc (int ignore ATTRIBUTE_UNUSED)
|
||||
|
||||
if (exp.X_op != O_absent)
|
||||
{
|
||||
symbolS *esym = NULL;
|
||||
|
||||
if (exp.X_op != O_constant && exp.X_op != O_symbol)
|
||||
{
|
||||
/* Handle complex expressions. */
|
||||
sym = make_expr_symbol (&exp);
|
||||
esym = sym = make_expr_symbol (&exp);
|
||||
off = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sym = exp.X_add_symbol;
|
||||
off = exp.X_add_number;
|
||||
|
||||
if (section == undefined_section)
|
||||
{
|
||||
/* We need an expr_symbol when tracking sections. In
|
||||
order to make this an expr_symbol with file and line
|
||||
tracked, we have to make the exp non-trivial; not an
|
||||
O_symbol with .X_add_number == 0. The constant part
|
||||
is unused. */
|
||||
exp.X_add_number = 1;
|
||||
esym = make_expr_symbol (&exp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Track the LOC's where we couldn't deduce the section: assert
|
||||
that we weren't supposed to change section. */
|
||||
if (section == undefined_section)
|
||||
{
|
||||
struct loc_assert_s *next = loc_asserts;
|
||||
loc_asserts
|
||||
= (struct loc_assert_s *) xmalloc (sizeof (*loc_asserts));
|
||||
loc_asserts->next = next;
|
||||
loc_asserts->old_seg = now_seg;
|
||||
loc_asserts->loc_sym = esym;
|
||||
}
|
||||
|
||||
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
|
||||
|
Loading…
Reference in New Issue
Block a user