diff options
Diffstat (limited to 'gas/read.c')
-rw-r--r-- | gas/read.c | 129 |
1 files changed, 105 insertions, 24 deletions
@@ -234,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); @@ -402,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 */ @@ -516,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}, @@ -668,13 +670,16 @@ 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; } @@ -721,9 +726,9 @@ finish_bundle (fragS *frag, unsigned int size) 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; } @@ -1435,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++) @@ -1456,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 @@ -1514,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) @@ -1573,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 != ',') @@ -1598,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; + } } } @@ -2223,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 @@ -2251,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 @@ -2318,7 +2391,7 @@ 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) { @@ -2361,7 +2434,7 @@ 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)); @@ -3296,6 +3369,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) @@ -3610,6 +3684,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) { @@ -3658,8 +3739,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; } @@ -4634,8 +4714,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; } @@ -5354,12 +5433,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; } |