diff options
Diffstat (limited to 'gas/read.c')
-rw-r--r-- | gas/read.c | 171 |
1 files changed, 88 insertions, 83 deletions
@@ -79,7 +79,7 @@ die horribly; #ifndef CR_EOL #define LEX_CR LEX_WHITE #else -#define LEX_CR 0 +#define LEX_CR LEX_EOL #endif #ifndef LEX_AT @@ -118,7 +118,7 @@ die horribly; /* Used by is_... macros. our ctype[]. */ char lex_type[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, LEX_CR, 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[\]^_ */ 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:;<=>? */ @@ -136,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 @@ -260,7 +234,6 @@ 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_reloc (int); @@ -290,8 +263,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; @@ -695,13 +667,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; } @@ -748,9 +723,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; } @@ -944,7 +919,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); @@ -993,7 +969,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))) @@ -1087,7 +1063,7 @@ read_a_source_file (const char *name) } if (strncasecmp (rest, "MACRO", 5) == 0 && (is_whitespace (rest[5]) - || is_end_of_line[(unsigned char) rest[5]])) + || is_end_of_stmt (rest[5]))) mri_line_macro = 1; } @@ -1343,7 +1319,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)) @@ -1461,14 +1437,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++) @@ -1482,6 +1459,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 @@ -1502,7 +1482,7 @@ mri_comment_field (char *stopcp) know (flag_m68k_mri); for (s = input_line_pointer; - ((!is_end_of_line[(unsigned char) *s] && !is_whitespace (*s)) + ((!is_end_of_stmt (*s) && !is_whitespace (*s)) || inquote); s++) { @@ -1511,7 +1491,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 @@ -1530,7 +1510,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; } @@ -1540,13 +1520,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) @@ -1562,7 +1543,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; @@ -1599,7 +1580,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 != ',') @@ -1624,7 +1606,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; + } } } @@ -2038,7 +2026,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 (); @@ -2161,7 +2149,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; } @@ -2196,7 +2184,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")); @@ -2277,8 +2265,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 @@ -2344,7 +2332,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) { @@ -2387,7 +2375,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)); @@ -2425,7 +2413,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'; } @@ -2485,7 +2473,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; @@ -3296,7 +3284,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; @@ -3323,6 +3310,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) @@ -3637,6 +3625,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) { @@ -3685,8 +3680,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; } @@ -4016,7 +4010,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 { @@ -4137,6 +4131,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. */ @@ -4168,6 +4164,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); @@ -4203,6 +4200,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) \ @@ -4218,14 +4230,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. */ @@ -4651,8 +4655,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; } @@ -5371,12 +5374,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; } @@ -5784,7 +5789,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 (); @@ -6311,7 +6316,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 @@ -6499,7 +6504,7 @@ s_include (int arg ATTRIBUTE_UNUSED) { SKIP_WHITESPACE (); i = 0; - while (!is_end_of_line[(unsigned char) *input_line_pointer] + while (!is_end_of_stmt (*input_line_pointer) && !is_whitespace (*input_line_pointer)) { obstack_1grow (¬es, *input_line_pointer); @@ -6509,7 +6514,7 @@ 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]) + while (!is_end_of_stmt (*input_line_pointer)) ++input_line_pointer; } @@ -6795,7 +6800,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 @@ -6804,7 +6809,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 == '@') |