diff options
Diffstat (limited to 'gas/read.c')
-rw-r--r-- | gas/read.c | 367 |
1 files changed, 215 insertions, 152 deletions
@@ -76,6 +76,12 @@ bool input_from_string = false; die horribly; #endif +#ifndef CR_EOL +#define LEX_CR LEX_WHITE +#else +#define LEX_CR LEX_EOL +#endif + #ifndef LEX_AT #define LEX_AT 0 #endif @@ -112,9 +118,9 @@ die horribly; /* Used by is_... macros. our ctype[]. */ char lex_type[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */ + 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0x20, 0, 0, LEX_CR, 0, 0, /* @ABCDEFGHIJKLMNO */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */ - 0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ + 8, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */ LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */ @@ -130,32 +136,6 @@ char lex_type[256] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; -/* In: a character. - Out: 1 if this character ends a line. - 2 if this character is a line separator. */ -char is_end_of_line[256] = { -#ifdef CR_EOL - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, /* @abcdefghijklmno */ -#else - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* @abcdefghijklmno */ -#endif - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* _!"#$%&'()*+,-./ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* */ -}; - #ifndef TC_CASE_SENSITIVE char original_case_string[128]; #endif @@ -254,9 +234,9 @@ static unsigned int bundle_lock_depth; #endif static void do_s_func (int end_p, const char *default_prefix); -static void s_align (int, int); static void s_altmacro (int); static void s_bad_end (int); +static void s_errwarn_if (int); static void s_reloc (int); static int hex_float (int, char *); static segT get_known_segmented_expression (expressionS * expP); @@ -284,8 +264,7 @@ read_begin (void) #endif /* Use machine dependent syntax. */ for (p = tc_line_separator_chars; *p; p++) - is_end_of_line[(unsigned char) *p] = 2; - /* Use more. FIXME-SOMEDAY. */ + lex_type[(unsigned char) *p] = LEX_EOS; if (flag_mri) lex_type['?'] = LEX_BEGIN_NAME | LEX_NAME; @@ -423,6 +402,7 @@ static const pseudo_typeS potable[] = { {"equiv", s_set, 1}, {"eqv", s_set, -1}, {"err", s_err, 0}, + {"errif", s_errwarn_if, 1}, {"error", s_errwarn, 1}, {"exitm", s_mexit, 0}, /* extend */ @@ -537,6 +517,7 @@ static const pseudo_typeS potable[] = { {"xdef", s_globl, 0}, {"xref", s_ignore, 0}, {"xstabs", s_xstab, 's'}, + {"warnif", s_errwarn_if, 0}, {"warning", s_errwarn, 0}, {"weakref", s_weakref, 0}, {"word", cons, 2}, @@ -689,23 +670,26 @@ start_bundle (void) { fragS *frag = frag_now; - frag_align_code (0, 0); + frag_align_code (bundle_align_p2, 0); while (frag->fr_type != rs_align_code) frag = frag->fr_next; gas_assert (frag != frag_now); + /* Set initial alignment to zero. */ + frag->fr_offset = 0; + return frag; } /* Calculate the maximum size after relaxation of the region starting at the given frag and extending through frag_now (which is unfinished). */ -static unsigned int +static valueT pending_bundle_size (fragS *frag) { - unsigned int offset = frag->fr_fix; - unsigned int size = 0; + valueT offset = frag->fr_fix; + valueT size = 0; gas_assert (frag != frag_now); gas_assert (frag->fr_type == rs_align_code); @@ -728,23 +712,23 @@ pending_bundle_size (fragS *frag) if (frag->fr_type == rs_machine_dependent) size += md_frag_max_var (frag); - gas_assert (size >= offset); + gas_assert (size >= offset || now_seg == absolute_section); return size - offset; } /* Finish off the frag created to ensure bundle alignment. */ static void -finish_bundle (fragS *frag, unsigned int size) +finish_bundle (fragS *frag, valueT size) { gas_assert (bundle_align_p2 > 0); gas_assert (frag->fr_type == rs_align_code); if (size > 1) { - /* If there is more than a single byte, then we need to set up the - alignment frag. Otherwise we leave it at its initial state from - calling frag_align_code (0, 0), so that it does nothing. */ + /* If there is more than a single byte, then we need to set up + the alignment frag. Otherwise we leave it at its initial + state with zero alignment so that it does nothing. */ frag->fr_offset = bundle_align_p2; frag->fr_subtype = size - 1; } @@ -779,20 +763,20 @@ assemble_one (char *line) { /* Make sure this hasn't pushed the locked sequence past the bundle size. */ - unsigned int bundle_size = pending_bundle_size (bundle_lock_frag); + valueT bundle_size = pending_bundle_size (bundle_lock_frag); if (bundle_size > 1U << bundle_align_p2) - as_bad (_ (".bundle_lock sequence at %u bytes, " + as_bad (_ (".bundle_lock sequence at %" PRIu64 " bytes, " "but .bundle_align_mode limit is %u bytes"), - bundle_size, 1U << bundle_align_p2); + (uint64_t) bundle_size, 1U << bundle_align_p2); } else if (bundle_align_p2 > 0) { - unsigned int insn_size = pending_bundle_size (insn_start_frag); + valueT insn_size = pending_bundle_size (insn_start_frag); if (insn_size > 1U << bundle_align_p2) - as_bad (_("single instruction is %u bytes long, " + as_bad (_("single instruction is %" PRIu64 " bytes long, " "but .bundle_align_mode limit is %u bytes"), - insn_size, 1U << bundle_align_p2); + (uint64_t) insn_size, 1U << bundle_align_p2); finish_bundle (insn_start_frag, insn_size); } @@ -938,7 +922,8 @@ read_a_source_file (const char *name) /* We now have input_line_pointer->1st char of next line. If input_line_pointer [-1] == '\n' then we just scanned another line: so bump line counters. */ - was_new_line = is_end_of_line[(unsigned char) input_line_pointer[-1]]; + was_new_line = lex_type[(unsigned char) input_line_pointer[-1]] + & (LEX_EOL | LEX_EOS); if (was_new_line) { symbol_set_value_now (&dot_symbol); @@ -987,7 +972,7 @@ read_a_source_file (const char *name) #endif next_char = *input_line_pointer; - if (was_new_line == 1 + if ((was_new_line & LEX_EOL) && (strchr (line_comment_chars, '#') ? next_char == '#' : next_char && strchr (line_comment_chars, next_char))) @@ -1068,11 +1053,11 @@ read_a_source_file (const char *name) if (*rest == ':') ++rest; - if (*rest == ' ' || *rest == '\t') + if (is_whitespace (*rest)) ++rest; if ((strncasecmp (rest, "EQU", 3) == 0 || strncasecmp (rest, "SET", 3) == 0) - && (rest[3] == ' ' || rest[3] == '\t')) + && is_whitespace (rest[3])) { input_line_pointer = rest + 3; equals (line_start, @@ -1080,9 +1065,8 @@ read_a_source_file (const char *name) continue; } if (strncasecmp (rest, "MACRO", 5) == 0 - && (rest[5] == ' ' - || rest[5] == '\t' - || is_end_of_line[(unsigned char) rest[5]])) + && (is_whitespace (rest[5]) + || is_end_of_stmt (rest[5]))) mri_line_macro = 1; } @@ -1117,7 +1101,7 @@ read_a_source_file (const char *name) level. */ do nul_char = next_char = *input_line_pointer++; - while (next_char == '\t' || next_char == ' ' || next_char == '\f'); + while (is_whitespace (next_char) || next_char == '\f'); /* C is the 1st significant character. Input_line_pointer points after that character. */ @@ -1146,12 +1130,12 @@ read_a_source_file (const char *name) if (*rest == ':') ++rest; - if (*rest == ' ' || *rest == '\t') + if (is_whitespace (*rest)) ++rest; if ((strncasecmp (rest, "EQU", 3) == 0 || strncasecmp (rest, "SET", 3) == 0) - && (rest[3] == ' ' || rest[3] == '\t')) + && is_whitespace (rest[3])) { input_line_pointer = rest + 3; equals (s, 1); @@ -1169,7 +1153,7 @@ read_a_source_file (const char *name) SKIP_WHITESPACE (); } else if ((next_char == '=' && *rest == '=') - || ((next_char == ' ' || next_char == '\t') + || (is_whitespace (next_char) && rest[0] == '=' && rest[1] == '=')) { @@ -1177,7 +1161,7 @@ read_a_source_file (const char *name) demand_empty_rest_of_line (); } else if ((next_char == '=' - || ((next_char == ' ' || next_char == '\t') + || (is_whitespace (next_char) && *rest == '=')) #ifdef TC_EQUAL_IN_INSN && !TC_EQUAL_IN_INSN (next_char, s) @@ -1251,7 +1235,7 @@ read_a_source_file (const char *name) || pop->poc_handler == s_globl || pop->poc_handler == s_ignore))) { - do_align (1, (char *) NULL, 0, 0); + do_align (1, NULL, 0, 0); mri_pending_align = 0; if (line_label != NULL) @@ -1284,7 +1268,7 @@ read_a_source_file (const char *name) /* The following skip of whitespace is compulsory. A well shaped space is sometimes all that separates keyword from operands. */ - if (next_char == ' ' || next_char == '\t') + if (is_whitespace (next_char)) input_line_pointer++; /* Input_line is restored. @@ -1312,7 +1296,7 @@ read_a_source_file (const char *name) if (mri_pending_align) { - do_align (1, (char *) NULL, 0, 0); + do_align (1, NULL, 0, 0); mri_pending_align = 0; if (line_label != NULL) { @@ -1338,7 +1322,7 @@ read_a_source_file (const char *name) } /* Empty statement? */ - if (is_end_of_line[(unsigned char) next_char]) + if (is_end_of_stmt (next_char)) continue; if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (next_char)) @@ -1456,14 +1440,15 @@ read_a_source_file (const char *name) #endif } -/* Convert O_constant expression EXP into the equivalent O_big representation. - Take the sign of the number from SIGN rather than X_add_number. */ +/* Convert O_constant expression EXP into the equivalent O_big + representation. */ -static void -convert_to_bignum (expressionS *exp, int sign) +static bool +convert_to_bignum (expressionS *exp) { valueT value; unsigned int i; + bool sign = !exp->X_unsigned && exp->X_extrabit; value = exp->X_add_number; for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++) @@ -1477,6 +1462,9 @@ convert_to_bignum (expressionS *exp, int sign) generic_bignum[i++] = sign ? LITTLENUM_MASK : 0; exp->X_op = O_big; exp->X_add_number = i; + exp->X_unsigned = !sign; + + return sign; } /* For most MRI pseudo-ops, the line actually ends at the first @@ -1497,7 +1485,7 @@ mri_comment_field (char *stopcp) know (flag_m68k_mri); for (s = input_line_pointer; - ((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t') + ((!is_end_of_stmt (*s) && !is_whitespace (*s)) || inquote); s++) { @@ -1506,7 +1494,7 @@ mri_comment_field (char *stopcp) } #else for (s = input_line_pointer; - !is_end_of_line[(unsigned char) *s]; + !is_end_of_stmt (*s); s++) ; #endif @@ -1525,7 +1513,7 @@ mri_comment_end (char *stop, int stopc) input_line_pointer = stop; *stop = stopc; - while (!is_end_of_line[(unsigned char) *input_line_pointer]) + while (!is_end_of_stmt (*input_line_pointer)) ++input_line_pointer; } @@ -1535,13 +1523,14 @@ s_abort (int ignore ATTRIBUTE_UNUSED) as_fatal (_(".abort detected. Abandoning ship.")); } +#ifndef TC_ALIGN_LIMIT +#define TC_ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1) +#endif + /* Handle the .align pseudo-op. A positive ARG is a default alignment (in bytes). A negative ARG is the negative of the length of the fill pattern. BYTES_P is non-zero if the alignment value should be interpreted as the byte boundary, rather than the power of 2. */ -#ifndef TC_ALIGN_LIMIT -#define TC_ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1) -#endif static void s_align (signed int arg, int bytes_p) @@ -1557,7 +1546,7 @@ s_align (signed int arg, int bytes_p) if (flag_mri) stop = mri_comment_field (&stopc); - if (is_end_of_line[(unsigned char) *input_line_pointer]) + if (is_end_of_stmt (*input_line_pointer)) { if (arg < 0) align = 0; @@ -1594,7 +1583,8 @@ s_align (signed int arg, int bytes_p) if (align > align_limit) { align = align_limit; - as_warn (_("alignment too large: %u assumed"), align_limit); + as_warn (_("alignment too large: %u assumed"), + bytes_p ? 1u << align_limit : align_limit); } if (*input_line_pointer != ',') @@ -1619,7 +1609,13 @@ s_align (signed int arg, int bytes_p) else { ++input_line_pointer; - max = get_absolute_expression (); + offsetT val = get_absolute_expression (); + max = val; + if (val < 0 || max != (valueT) val) + { + as_warn (_("ignoring out of range alignment maximum")); + max = 0; + } } } @@ -1627,7 +1623,7 @@ s_align (signed int arg, int bytes_p) { if (arg < 0) as_warn (_("expected fill pattern missing")); - do_align (align, (char *) NULL, 0, max); + do_align (align, NULL, 0, max); } else { @@ -1860,7 +1856,7 @@ s_comm_internal (int param, symbolP = (*comm_parse_extra) (param, symbolP, size); else { - S_SET_VALUE (symbolP, (valueT) size); + S_SET_VALUE (symbolP, size); S_SET_EXTERNAL (symbolP); S_SET_SEGMENT (symbolP, bfd_com_section_ptr); } @@ -1997,7 +1993,7 @@ s_data (int ignore ATTRIBUTE_UNUSED) else section = data_section; - subseg_set (section, (subsegT) temp); + subseg_set (section, temp); demand_empty_rest_of_line (); } @@ -2033,7 +2029,7 @@ s_file (int ignore ATTRIBUTE_UNUSED) backquote. */ if (flag_m68k_mri && *input_line_pointer == '\'' - && is_end_of_line[(unsigned char) input_line_pointer[1]]) + && is_end_of_stmt (input_line_pointer[1])) ++input_line_pointer; demand_empty_rest_of_line (); @@ -2156,7 +2152,7 @@ s_linefile (int ignore ATTRIBUTE_UNUSED) break; } - if (!is_end_of_line[(unsigned char)*input_line_pointer]) + if (!is_end_of_stmt (*input_line_pointer)) file = NULL; } @@ -2191,7 +2187,7 @@ s_end (int ignore ATTRIBUTE_UNUSED) /* The MRI assembler permits the start symbol to follow .end, but we don't support that. */ SKIP_WHITESPACE (); - if (!is_end_of_line[(unsigned char) *input_line_pointer] + if (!is_end_of_stmt (*input_line_pointer) && *input_line_pointer != '*' && *input_line_pointer != '!') as_warn (_("start address not supported")); @@ -2244,6 +2240,62 @@ s_errwarn (int err) demand_empty_rest_of_line (); } +/* Handle the .errif and .warnif pseudo-ops. */ + +static struct deferred_diag { + struct deferred_diag *next; + const char *file; + unsigned int lineno; + bool err; + expressionS exp; +} *deferred_diags, *last_deferred_diag; + +static void +s_errwarn_if (int err) +{ + struct deferred_diag *diag = XNEW (struct deferred_diag); + int errcnt = had_errors (); + + deferred_expression (&diag->exp); + if (errcnt != had_errors ()) + { + ignore_rest_of_line (); + return; + } + + diag->err = err; + diag->file = as_where (&diag->lineno); + diag->next = NULL; + if ( deferred_diags == NULL ) + deferred_diags = diag; + else + last_deferred_diag->next = diag; + last_deferred_diag = diag; + + demand_empty_rest_of_line (); +} + +void +evaluate_deferred_diags (void) +{ + struct deferred_diag *diag; + + for (diag = deferred_diags; diag != NULL; diag = diag->next) + { + if (!resolve_expression (&diag->exp) || diag->exp.X_op != O_constant) + as_warn_where (diag->file, diag->lineno, + _("expression does not evaluate to a constant")); + else if (diag->exp.X_add_number == 0) + continue; + else if (diag->err) + as_bad_where (diag->file, diag->lineno, + _(".errif expression evaluates to true")); + else + as_warn_where (diag->file, diag->lineno, + _(".warnif expression evaluates to true")); + } +} + /* Handle the MRI fail pseudo-op. */ void @@ -2272,8 +2324,8 @@ void s_fill (int ignore ATTRIBUTE_UNUSED) { expressionS rep_exp; - long size = 1; - long fill = 0; + offsetT size = 1; + valueT fill = 0; char *p; #ifdef md_flush_pending_output @@ -2339,14 +2391,12 @@ s_fill (int ignore ATTRIBUTE_UNUSED) if (size && !need_pass_2) { if (now_seg == absolute_section) - abs_section_offset += rep_exp.X_add_number * size; + abs_section_offset += (valueT) rep_exp.X_add_number * size; if (rep_exp.X_op == O_constant) { - p = frag_var (rs_fill, (int) size, (int) size, - (relax_substateT) 0, (symbolS *) 0, - (offsetT) rep_exp.X_add_number, - (char *) 0); + p = frag_var (rs_fill, size, size, 0, NULL, + rep_exp.X_add_number, NULL); } else { @@ -2370,11 +2420,10 @@ s_fill (int ignore ATTRIBUTE_UNUSED) rep_sym = make_expr_symbol (&rep_exp); } - p = frag_var (rs_space, (int) size, (int) size, - (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0); + p = frag_var (rs_space, size, size, 0, rep_sym, 0, NULL); } - memset (p, 0, (unsigned int) size); + memset (p, 0, size); /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX flavoured AS. The following bizarre behaviour is to be @@ -2382,10 +2431,10 @@ s_fill (int ignore ATTRIBUTE_UNUSED) bytes from a 4-byte expression and they forgot to sign extend. */ #define BSD_FILL_SIZE_CROCK_4 (4) - md_number_to_chars (p, (valueT) fill, + md_number_to_chars (p, fill, (size > BSD_FILL_SIZE_CROCK_4 ? BSD_FILL_SIZE_CROCK_4 - : (int) size)); + : size)); /* Note: .fill (),0 emits no frag (since we are asked to .fill 0 bytes) but emits no error message because it seems a legal thing to do. It is a degenerate case of .fill but could be emitted by a @@ -2420,7 +2469,7 @@ s_globl (int ignore ATTRIBUTE_UNUSED) { input_line_pointer++; SKIP_WHITESPACE (); - if (is_end_of_line[(unsigned char) *input_line_pointer]) + if (is_end_of_stmt (*input_line_pointer)) c = '\n'; } @@ -2480,7 +2529,7 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED) type = LINKONCE_DISCARD; - if (!is_end_of_line[(unsigned char) *input_line_pointer]) + if (!is_end_of_stmt (*input_line_pointer)) { char *s; char c; @@ -2711,7 +2760,7 @@ s_lsym (int ignore ATTRIBUTE_UNUSED) (exp.X_op == O_constant ? absolute_section : reg_section)); - S_SET_VALUE (symbolP, (valueT) exp.X_add_number); + S_SET_VALUE (symbolP, exp.X_add_number); } else { @@ -2920,7 +2969,7 @@ do_org (segT segment, expressionS *exp, int fill) off = 0; } - p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0); + p = frag_var (rs_org, 1, 1, 0, sym, off, NULL); *p = fill; } } @@ -3125,7 +3174,7 @@ s_rept (int expand_count) { size_t count; - count = (size_t) get_absolute_expression (); + count = get_absolute_expression (); do_repeat (count, "REPT", "ENDR", expand_count ? "" : NULL); } @@ -3291,7 +3340,6 @@ assign_symbol (char *name, int mode) for this symbol. */ if (listing & LISTING_SYMBOLS) { - extern struct list_info_struct *listing_tail; fragS *dummy_frag = notes_calloc (1, sizeof (*dummy_frag)); dummy_frag->line = listing_tail; dummy_frag->fr_symbol = symbolP; @@ -3318,6 +3366,7 @@ assign_symbol (char *name, int mode) retain the value of the symbol at the point of use. */ else if (S_IS_VOLATILE (symbolP)) symbolP = symbol_clone (symbolP, 1); + S_CLEAR_WEAKREFR (symbolP); } if (mode == 0) @@ -3433,7 +3482,7 @@ s_space (int mult) } else { - do_align (1, (char *) NULL, 0, 0); + do_align (1, NULL, 0, 0); if (line_label != NULL) { symbol_set_frag (line_label, frag_now); @@ -3539,8 +3588,7 @@ s_space (int mult) } if (!need_pass_2) - p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, - (offsetT) total, (char *) 0); + p = frag_var (rs_fill, 1, 1, 0, NULL, total, NULL); } else { @@ -3557,8 +3605,7 @@ s_space (int mult) } if (!need_pass_2) - p = frag_var (rs_space, 1, 1, (relax_substateT) 0, - make_expr_symbol (&exp), (offsetT) 0, (char *) 0); + p = frag_var (rs_space, 1, 1, 0, make_expr_symbol (&exp), 0, NULL); } if ((val.X_op != O_constant || val.X_add_number != 0) && in_bss ()) @@ -3632,6 +3679,13 @@ s_nop (int ignore ATTRIBUTE_UNUSED) && frag_off + frag_now_fix () < start_off + exp.X_add_number); } +/* Use this to specify the amount of memory allocated for representing + the nops. Needs to be large enough to hold any fixed size prologue + plus the replicating portion. */ +#ifndef MAX_MEM_FOR_RS_SPACE_NOP +# define MAX_MEM_FOR_RS_SPACE_NOP 1 +#endif + void s_nops (int ignore ATTRIBUTE_UNUSED) { @@ -3680,8 +3734,7 @@ s_nops (int ignore ATTRIBUTE_UNUSED) /* Store the no-op instruction control byte in the first byte of frag. */ char *p; symbolS *sym = make_expr_symbol (&exp); - p = frag_var (rs_space_nop, 1, 1, (relax_substateT) 0, - sym, (offsetT) 0, (char *) 0); + p = frag_var (rs_space_nop, MAX_MEM_FOR_RS_SPACE_NOP, 1, 0, sym, 0, NULL); *p = val.X_add_number; } @@ -3842,7 +3895,7 @@ s_float_space (int float_type) char *p; p = frag_more (flen); - memcpy (p, temp, (unsigned int) flen); + memcpy (p, temp, flen); } demand_empty_rest_of_line (); @@ -3880,7 +3933,7 @@ s_text (int ignore ATTRIBUTE_UNUSED) int temp; temp = get_absolute_expression (); - subseg_set (text_section, (subsegT) temp); + subseg_set (text_section, temp); demand_empty_rest_of_line (); } @@ -4011,7 +4064,7 @@ demand_empty_rest_of_line (void) SKIP_WHITESPACE (); if (input_line_pointer > buffer_limit) return; - if (is_end_of_line[(unsigned char) *input_line_pointer]) + if (is_end_of_stmt (*input_line_pointer)) input_line_pointer++; else { @@ -4132,6 +4185,8 @@ pseudo_set (symbolS *symbolP) case O_symbol: seg = S_GET_SEGMENT (exp.X_add_symbol); + if (seg == expr_section) + goto expr; /* For x=undef+const, create an expression symbol. For x=x+const, just update x except when x is an undefined symbol For x=defined+const, evaluate x. */ @@ -4163,6 +4218,7 @@ pseudo_set (symbolS *symbolP) break; default: + expr: /* The value is some complex expression. */ S_SET_SEGMENT (symbolP, expr_section); symbol_set_value_expression (symbolP, &exp); @@ -4198,6 +4254,21 @@ static void parse_mri_cons (expressionS *exp, unsigned int nbytes); #endif +/* This function is used by .cfi_* directive handling, and hence must not + invoke parse_repeat_cons(). */ + +TC_PARSE_CONS_RETURN_TYPE +do_parse_cons_expression (expressionS *exp, + int nbytes ATTRIBUTE_UNUSED) +{ +#ifdef TC_PARSE_CONS_EXPRESSION + return TC_PARSE_CONS_EXPRESSION (exp, nbytes); +#else + expression (exp); + return TC_PARSE_CONS_RETURN_NONE; +#endif +} + #ifndef TC_PARSE_CONS_EXPRESSION #ifdef REPEAT_CONS_EXPRESSIONS #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \ @@ -4213,14 +4284,6 @@ parse_repeat_cons (expressionS *exp, unsigned int nbytes); #endif #endif -void -do_parse_cons_expression (expressionS *exp, - int nbytes ATTRIBUTE_UNUSED) -{ - (void) TC_PARSE_CONS_EXPRESSION (exp, nbytes); -} - - /* Worker to do .byte etc statements. Clobbers input_line_pointer and checks end-of-line. */ @@ -4268,7 +4331,7 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ #ifdef TC_M68K if (flag_m68k_mri) - parse_mri_cons (&exp, (unsigned int) nbytes); + parse_mri_cons (&exp, nbytes); else #endif { @@ -4280,7 +4343,7 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ return; } #endif - ret = TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes); + ret = TC_PARSE_CONS_EXPRESSION (&exp, nbytes); } if (rva) @@ -4290,7 +4353,7 @@ cons_worker (int nbytes, /* 1=.byte, 2=.word, 4=.long. */ else as_fatal (_("rva without symbol")); } - emit_expr_with_reloc (&exp, (unsigned int) nbytes, ret); + emit_expr_with_reloc (&exp, nbytes, ret); #ifdef TC_CONS_FIX_CHECK TC_CONS_FIX_CHECK (&exp, nbytes, *cur_fix); #endif @@ -4496,7 +4559,7 @@ emit_expr_with_reloc (expressionS *exp, && nbytes == 2 && exp->X_op == O_constant && (exp->X_add_number == -1 || exp->X_add_number == 0xffff)) - listing_source_line ((unsigned int) dwarf_line); + listing_source_line (dwarf_line); else if (nbytes == 4 && exp->X_op == O_constant && exp->X_add_number >= 0) @@ -4573,7 +4636,7 @@ emit_expr_with_reloc (expressionS *exp, /* We can ignore any carry out, because it will be handled by extra_digit if it is needed. */ - extra_digit = (valueT) -1; + extra_digit = -1; op = O_big; } @@ -4609,7 +4672,7 @@ emit_expr_with_reloc (expressionS *exp, as_bad (_("attempt to store non-zero value in section `%s'"), segment_name (now_seg)); - p = frag_more ((int) nbytes); + p = frag_more (nbytes); if (reloc != TC_PARSE_CONS_RETURN_NONE) { @@ -4646,8 +4709,7 @@ emit_expr_with_reloc (expressionS *exp, pass to md_number_to_chars, handle it as a bignum. */ if (op == O_constant && nbytes > sizeof (valueT)) { - extra_digit = exp->X_unsigned ? 0 : -1; - convert_to_bignum (exp, !exp->X_unsigned); + extra_digit = -convert_to_bignum (exp); op = O_big; } @@ -4687,7 +4749,7 @@ emit_expr_with_reloc (expressionS *exp, (uint64_t) get, (uint64_t) use); } /* Put bytes in right order. */ - md_number_to_chars (p, use, (int) nbytes); + md_number_to_chars (p, use, nbytes); } else if (op == O_big) { @@ -4736,7 +4798,7 @@ emit_expr_with_reloc (expressionS *exp, if (nbytes == 1) { - md_number_to_chars (p, (valueT) generic_bignum[0], 1); + md_number_to_chars (p, generic_bignum[0], 1); return; } know (nbytes % CHARS_PER_LITTLENUM == 0); @@ -4754,7 +4816,7 @@ emit_expr_with_reloc (expressionS *exp, while (size >= CHARS_PER_LITTLENUM) { --nums; - md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); + md_number_to_chars (p, *nums, CHARS_PER_LITTLENUM); size -= CHARS_PER_LITTLENUM; p += CHARS_PER_LITTLENUM; } @@ -4764,7 +4826,7 @@ emit_expr_with_reloc (expressionS *exp, nums = generic_bignum; while (size >= CHARS_PER_LITTLENUM) { - md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM); + md_number_to_chars (p, *nums, CHARS_PER_LITTLENUM); ++nums; size -= CHARS_PER_LITTLENUM; p += CHARS_PER_LITTLENUM; @@ -5096,7 +5158,7 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line. */ while (--count >= 0) { p = frag_more (length); - memcpy (p, temp, (unsigned int) length); + memcpy (p, temp, length); } } SKIP_WHITESPACE (); @@ -5166,7 +5228,7 @@ unsigned int sizeof_leb128 (valueT value, int sign) { if (sign) - return sizeof_sleb128 ((offsetT) value); + return sizeof_sleb128 (value); else return sizeof_uleb128 (value); } @@ -5225,7 +5287,7 @@ unsigned int output_leb128 (char *p, valueT value, int sign) { if (sign) - return output_sleb128 (p, (offsetT) value); + return output_sleb128 (p, value); else return output_uleb128 (p, value); } @@ -5366,12 +5428,14 @@ emit_leb128_expr (expressionS *exp, int sign) } else if (op == O_constant && sign - && (exp->X_add_number < 0) == !exp->X_extrabit) + && (exp->X_unsigned + ? exp->X_add_number < 0 + : (exp->X_add_number < 0) != exp->X_extrabit)) { /* We're outputting a signed leb128 and the sign of X_add_number doesn't reflect the sign of the original value. Convert EXP to a correctly-extended bignum instead. */ - convert_to_bignum (exp, exp->X_extrabit); + convert_to_bignum (exp); op = O_big; } @@ -5389,7 +5453,7 @@ emit_leb128_expr (expressionS *exp, int sign) /* Let check_eh_frame know that data is being emitted. nbytes == -1 is a signal that this is leb128 data. It shouldn't optimize this away. */ - nbytes = (unsigned int) -1; + nbytes = -1u; if (check_eh_frame (exp, &nbytes)) abort (); @@ -5437,7 +5501,7 @@ emit_leb128_expr (expressionS *exp, int sign) resolve things later. */ frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign, - make_expr_symbol (exp), 0, (char *) NULL); + make_expr_symbol (exp), 0, NULL); } } @@ -5779,7 +5843,7 @@ s_base64 (int dummy ATTRIBUTE_UNUSED) { c = * input_line_pointer ++; - if (c >= 256 || is_end_of_line [c]) + if (c >= 256 || is_end_of_stmt (c)) { as_bad (_("end of line encountered inside .base64 string")); ignore_rest_of_line (); @@ -6229,7 +6293,7 @@ char /* Return terminator. */ get_absolute_expression_and_terminator (long *val_pointer /* Return value of expression. */) { /* FIXME: val_pointer should probably be offsetT *. */ - *val_pointer = (long) get_absolute_expression (); + *val_pointer = get_absolute_expression (); return (*input_line_pointer++); } @@ -6284,7 +6348,7 @@ demand_copy_string (int *lenP) /* JF this next line is so demand_copy_C_string will return a null terminated string. */ obstack_1grow (¬es, '\0'); - retval = (char *) obstack_finish (¬es); + retval = obstack_finish (¬es); } else { @@ -6293,7 +6357,7 @@ demand_copy_string (int *lenP) ignore_rest_of_line (); } *lenP = len; - return (retval); + return retval; } /* In: Input_line_pointer->next character. @@ -6306,7 +6370,7 @@ int is_it_end_of_statement (void) { SKIP_WHITESPACE (); - return (is_end_of_line[(unsigned char) *input_line_pointer]); + return is_end_of_stmt (*input_line_pointer); } void @@ -6321,7 +6385,7 @@ equals (char *sym_name, int reassign) if (reassign < 0 && *input_line_pointer == '=') input_line_pointer++; - while (*input_line_pointer == ' ' || *input_line_pointer == '\t') + while (is_whitespace (*input_line_pointer)) input_line_pointer++; if (flag_mri) @@ -6494,9 +6558,8 @@ s_include (int arg ATTRIBUTE_UNUSED) { SKIP_WHITESPACE (); i = 0; - while (!is_end_of_line[(unsigned char) *input_line_pointer] - && *input_line_pointer != ' ' - && *input_line_pointer != '\t') + while (!is_end_of_stmt (*input_line_pointer) + && !is_whitespace (*input_line_pointer)) { obstack_1grow (¬es, *input_line_pointer); ++input_line_pointer; @@ -6504,8 +6567,8 @@ s_include (int arg ATTRIBUTE_UNUSED) } obstack_1grow (¬es, '\0'); - filename = (char *) obstack_finish (¬es); - while (!is_end_of_line[(unsigned char) *input_line_pointer]) + filename = obstack_finish (¬es); + while (!is_end_of_stmt (*input_line_pointer)) ++input_line_pointer; } @@ -6704,7 +6767,7 @@ s_bundle_lock (int arg ATTRIBUTE_UNUSED) void s_bundle_unlock (int arg ATTRIBUTE_UNUSED) { - unsigned int size; + valueT size; demand_empty_rest_of_line (); @@ -6723,9 +6786,9 @@ s_bundle_unlock (int arg ATTRIBUTE_UNUSED) size = pending_bundle_size (bundle_lock_frag); if (size > 1U << bundle_align_p2) - as_bad (_(".bundle_lock sequence is %u bytes, " + as_bad (_(".bundle_lock sequence is %" PRIu64 " bytes, " "but bundle size is only %u bytes"), - size, 1u << bundle_align_p2); + (uint64_t) size, 1u << bundle_align_p2); else finish_bundle (bundle_lock_frag, size); @@ -6791,7 +6854,7 @@ _find_end_of_line (char *s, int mri_string, int insn ATTRIBUTE_UNUSED, char inquote = '\0'; int inescape = 0; - while (!is_end_of_line[(unsigned char) *s] + while (!is_end_of_stmt (*s) || (inquote && !ISCNTRL (*s)) || (inquote == '\'' && flag_mri) #ifdef TC_EOL_IN_INSN @@ -6800,7 +6863,7 @@ _find_end_of_line (char *s, int mri_string, int insn ATTRIBUTE_UNUSED, /* PR 6926: When we are parsing the body of a macro the sequence \@ is special - it refers to the invocation count. If the @ character happens to be registered as a line-separator character - by the target, then the is_end_of_line[] test above will have + by the target, then the is_end_of_stmt() test above will have returned true, but we need to ignore the line separating semantics in this particular case. */ || (in_macro && inescape && *s == '@') |