aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c236
1 files changed, 156 insertions, 80 deletions
diff --git a/gas/read.c b/gas/read.c
index 31b89b7..d604d95 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -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,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);
@@ -707,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;
}
@@ -758,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);
}
@@ -1230,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)
@@ -1291,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)
{
@@ -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;
+ }
}
}
@@ -1606,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
{
@@ -1839,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);
}
@@ -1976,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 ();
}
@@ -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,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
{
@@ -2349,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
@@ -2361,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
@@ -2690,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
{
@@ -2899,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;
}
}
@@ -3104,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);
}
@@ -3296,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)
@@ -3411,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);
@@ -3517,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
{
@@ -3535,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 ())
@@ -3610,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)
{
@@ -3658,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;
}
@@ -3820,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 ();
@@ -3858,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 ();
}
@@ -4256,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
{
@@ -4268,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)
@@ -4278,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
@@ -4484,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)
@@ -4561,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;
}
@@ -4597,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)
{
@@ -4634,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;
}
@@ -4675,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)
{
@@ -4724,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);
@@ -4742,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;
}
@@ -4752,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;
@@ -5084,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 ();
@@ -5154,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);
}
@@ -5213,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);
}
@@ -5354,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;
}
@@ -5377,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 ();
@@ -5425,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);
}
}
@@ -6217,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++);
}
@@ -6272,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 (&notes, '\0');
- retval = (char *) obstack_finish (&notes);
+ retval = obstack_finish (&notes);
}
else
{
@@ -6281,7 +6357,7 @@ demand_copy_string (int *lenP)
ignore_rest_of_line ();
}
*lenP = len;
- return (retval);
+ return retval;
}
/* In: Input_line_pointer->next character.
@@ -6491,7 +6567,7 @@ s_include (int arg ATTRIBUTE_UNUSED)
}
obstack_1grow (&notes, '\0');
- filename = (char *) obstack_finish (&notes);
+ filename = obstack_finish (&notes);
while (!is_end_of_stmt (*input_line_pointer))
++input_line_pointer;
}
@@ -6691,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 ();
@@ -6710,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);