aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c171
1 files changed, 88 insertions, 83 deletions
diff --git a/gas/read.c b/gas/read.c
index 2939c68..db9c762 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -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 (&notes, *input_line_pointer);
@@ -6509,7 +6514,7 @@ s_include (int arg ATTRIBUTE_UNUSED)
obstack_1grow (&notes, '\0');
filename = (char *) obstack_finish (&notes);
- 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 == '@')