X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-mmix.c;h=d3d971de8ee663dbca6cb8eef96d4fc58cb4c4b2;hb=4179a6a209f22354a605413e0de9ac10331c108b;hp=5b6b331a7ca07399217a9a28fccbfc05d8e7f4f5;hpb=87975d2a60adf249212c1c031abb4dd0dbb800ac;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-mmix.c b/gas/config/tc-mmix.c index 5b6b331a7c..d3d971de8e 100644 --- a/gas/config/tc-mmix.c +++ b/gas/config/tc-mmix.c @@ -1,6 +1,5 @@ /* tc-mmix.c -- Assembler for Don Knuth's MMIX. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation. + Copyright (C) 2001-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -27,8 +26,8 @@ compatible syntax, but the main purpose is to serve GCC. */ -#include #include "as.h" +#include #include "subsegs.h" #include "elf/mmix.h" #include "opcode/mmix.h" @@ -40,11 +39,11 @@ for example assert something of what it became or make a relocation. */ enum mmix_fixup_action - { - mmix_fixup_byte, - mmix_fixup_register, - mmix_fixup_register_or_adjust_for_byte - }; +{ + mmix_fixup_byte, + mmix_fixup_register, + mmix_fixup_register_or_adjust_for_byte +}; static int get_spec_regno (char *); static int get_operands (int, char *, expressionS *); @@ -109,6 +108,14 @@ static struct expressionS exp; } mmix_raw_gregs[MAX_GREGS]; +static struct loc_assert_s + { + segT old_seg; + symbolS *loc_sym; + fragS *frag; + 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 @@ -179,7 +186,7 @@ int mmix_next_semicolon_is_eoln = 1; /* Do we have a BSPEC in progress? */ static int doing_bspec = 0; -static char *bspec_file; +static const char *bspec_file; static unsigned int bspec_line; struct option md_longopts[] = @@ -388,9 +395,9 @@ const char line_comment_chars[] = "*#"; const char line_separator_chars[] = ";"; -const char mmix_exp_chars[] = "eE"; +const char EXP_CHARS[] = "eE"; -const char mmix_flt_chars[] = "rf"; +const char FLT_CHARS[] = "rf"; /* Fill in the offset-related part of GETA or Bcc. */ @@ -580,8 +587,10 @@ get_putget_operands (struct mmix_opcode *insn, char *operands, p++; sregp = p; input_line_pointer = sregp; - c = get_symbol_end (); + c = get_symbol_name (&sregp); sregend = input_line_pointer; + if (c == '"') + ++ input_line_pointer; } } else @@ -589,10 +598,10 @@ get_putget_operands (struct mmix_opcode *insn, char *operands, expp_sreg = &exp[0]; expp_reg = &exp[1]; - sregp = p; - c = get_symbol_end (); - sregend = p = input_line_pointer; - *p = c; + c = get_symbol_name (&sregp); + sregend = input_line_pointer; + restore_line_pointer (c); + p = input_line_pointer; /* Skip whitespace */ while (*p == ' ' || *p == '\t') @@ -631,7 +640,7 @@ get_putget_operands (struct mmix_opcode *insn, char *operands, /* Handle MMIX-specific option. */ int -md_parse_option (int c, char *arg ATTRIBUTE_UNUSED) +md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED) { switch (c) { @@ -1468,8 +1477,8 @@ md_assemble (char *str) && ((exp[1].X_op == O_register && exp[1].X_add_number < 512) || (exp[1].X_op == O_constant - && exp[1].X_add_number < 0 - && exp[1].X_add_number > 4) + && (exp[1].X_add_number < 0 + || exp[1].X_add_number > 4)) || (exp[1].X_op != O_register && exp[1].X_op != O_constant)))) { @@ -1932,10 +1941,8 @@ s_prefix (int unused ATTRIBUTE_UNUSED) SKIP_WHITESPACE (); - p = input_line_pointer; - - c = get_symbol_end (); - + c = get_symbol_name (&p); + /* Reseting prefix? */ if (*p == ':' && p[1] == 0) mmix_current_prefix = NULL; @@ -1954,7 +1961,7 @@ s_prefix (int unused ATTRIBUTE_UNUSED) mmix_current_prefix = p; } - *input_line_pointer = c; + (void) restore_line_pointer (c); mmix_handle_rest_of_empty_line (); } @@ -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 @@ -2031,13 +2057,15 @@ s_greg (int unused ATTRIBUTE_UNUSED) { char *p; char c; - p = input_line_pointer; /* This will skip over what can be a symbol and zero out the next character, which we assume is a ',' or other meaningful delimiter. What comes after that is the initializer expression for the register. */ - c = get_symbol_end (); + c = get_symbol_name (&p); + + if (c == '"') + c = * ++ input_line_pointer; if (! is_end_of_line[(unsigned char) c]) input_line_pointer++; @@ -2113,7 +2141,7 @@ s_bspec (int unused ATTRIBUTE_UNUSED) subseg_set (sec, 0); /* Save position for missing ESPEC. */ - as_where (&bspec_file, &bspec_line); + bspec_file = as_where (&bspec_line); doing_bspec = 1; } @@ -2244,12 +2272,12 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) emitted is stored in *sizeP . An error message is returned, or NULL on OK. */ -char * +const char * md_atof (int type, char *litP, int *sizeP) { if (type == 'r') type = 'f'; - /* FIXME: Having 'f' in mmix_flt_chars (and here) makes it + /* FIXME: Having 'f' in FLT_CHARS (and here) makes it problematic to also have a forward reference in an expression. The testsuite wants it, and it's customary. We'll deal with the real problems when they come; we share the @@ -2911,18 +2939,16 @@ mmix_handle_mmixal (void) caller is about to bump the counters. Adjust the error messages. */ if (is_end_of_line[(unsigned int) *s]) { - char *name; unsigned int line; - as_where (&name, &line); + const char * name = as_where (&line); as_bad_where (name, line + 1, _("[0-9]H labels may not appear alone on a line")); current_fb_label = -1; } if (*s == '.') { - char *name; unsigned int line; - as_where (&name, &line); + const char * name = as_where (&line); as_bad_where (name, line + 1, _("[0-9]H labels do not mix with dot-pseudos")); current_fb_label = -1; @@ -2947,7 +2973,7 @@ mmix_handle_mmixal (void) if (*s == 0 || is_end_of_line[(unsigned int) *s]) /* We avoid handling empty lines here. */ return; - + if (is_name_beginner (*s)) label = s; @@ -2981,7 +3007,7 @@ mmix_handle_mmixal (void) it the same alignment and address as the associated instruction. */ /* Make room for the label including the ending nul. */ - int len_0 = s - label + 1; + size_t len_0 = s - label + 1; /* Save this label on the MMIX symbol obstack. Saving it on an obstack is needless for "IS"-pseudos, but it's harmless and we @@ -3387,7 +3413,7 @@ mmix_md_relax_frag (segT seg, fragS *fragP, long stretch) fragP->fr_subtype = ENCODE_RELAX (STATE_PUSHJSTUB, STATE_ZERO); } /* FALLTHROUGH. */ - + /* See if this PUSHJ is redirectable to a stub. */ case ENCODE_RELAX (STATE_PUSHJSTUB, STATE_ZERO): { @@ -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,38 @@ 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) + { + const 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")); + + /* Patch up the generic location data to avoid cascading + error messages from later passes. (See original in + write.c:relax_segment.) */ + fragP = loc_assert->frag; + fragP->fr_type = rs_align; + fragP->fr_subtype = 0; + fragP->fr_offset = 0; + fragP->fr_fix = 0; + } + } + if (n_of_raw_gregs != 0) { /* Emit GREGs. They are collected in order of appearance, but must @@ -3716,7 +3775,7 @@ mmix_frob_file (void) if (gregs == NULL) { - gregs = xmalloc (sizeof (*gregs)); + gregs = XNEW (struct mmix_symbol_gregs); gregs->n_gregs = 0; symbol_set_tc (sym, &gregs); all_greg_symbols[n_greg_symbols++] = gregs; @@ -3892,13 +3951,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 +4046,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 +4059,42 @@ 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; + loc_asserts->frag = frag_now; } p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);