* read.c: Remove unneeded prototypes.

(s_comm): Split out code to..
	(s_comm_internal): ..here.  Tidy error returns.  Rearrange so that
	"name" from input line may be used in more places.  Merge code
	testing for valid size from elf_common.  Merge code from
	s_lcomm_internal.  Call comm_parse_extra.
	(bss_alloc): New function, split out of s_lcomm_internal and
	elf_common.
	(parse_align): Likewise.
	(s_lcomm_internal): Rewrite.
	(s_lcomm, s_lcomm_bytes): Use s_comm_internal.
	* read.h (bss_alloc, parse_align, s_comm_internal): Declare.
	* config/obj-elf.c (elf_common): Split out code to..
	(elf_common_parse): ..here.  Remove code common to s_comm_internal,
	parse_align and bss_alloc.  Rearrange and Tidy.
	* config/tc-alpha.h (TC_IMPLICIT_LCOMM_ALIGNMENT): Define.
This commit is contained in:
Alan Modra 2003-12-13 08:23:05 +00:00
parent 503ff15d38
commit e13bab5a71
5 changed files with 257 additions and 389 deletions

View File

@ -1,3 +1,22 @@
2003-12-13 Alan Modra <amodra@bigpond.net.au>
* read.c: Remove unneeded prototypes.
(s_comm): Split out code to..
(s_comm_internal): ..here. Tidy error returns. Rearrange so that
"name" from input line may be used in more places. Merge code
testing for valid size from elf_common. Merge code from
s_lcomm_internal. Call comm_parse_extra.
(bss_alloc): New function, split out of s_lcomm_internal and
elf_common.
(parse_align): Likewise.
(s_lcomm_internal): Rewrite.
(s_lcomm, s_lcomm_bytes): Use s_comm_internal.
* read.h (bss_alloc, parse_align, s_comm_internal): Declare.
* config/obj-elf.c (elf_common): Split out code to..
(elf_common_parse): ..here. Remove code common to s_comm_internal,
parse_align and bss_alloc. Rearrange and Tidy.
* config/tc-alpha.h (TC_IMPLICIT_LCOMM_ALIGNMENT): Define.
2003-12-10 Zack Weinberg <zack@codesourcery.com>
* tc-ppc.c (md_assemble): Rewrite comment about optional operands

View File

@ -63,7 +63,6 @@ static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
static void build_group_lists PARAMS ((bfd *, asection *, PTR));
static int elf_separate_stab_sections PARAMS ((void));
static void elf_init_stab_section PARAMS ((segT));
static symbolS *elf_common PARAMS ((int));
#ifdef NEED_ECOFF_DEBUG
static bfd_boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
@ -287,185 +286,96 @@ elf_file_symbol (s)
#endif
}
/* Called from read.c:s_comm after we've parsed .comm symbol, size.
Parse a possible alignment value. */
static symbolS *
elf_common (is_common)
int is_common;
elf_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
{
char *name;
char c;
char *p;
offsetT temp, size, sign;
symbolS *symbolP;
int have_align;
expressionS exp;
addressT align = 0;
int is_local = symbol_get_obj (symbolP)->local;
if (flag_mri && is_common)
if (*input_line_pointer == ',')
{
s_mri_common (0);
return NULL;
}
char *save = input_line_pointer;
name = input_line_pointer;
c = get_symbol_end ();
/* just after name is now '\0' */
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("expected comma after symbol-name"));
ignore_rest_of_line ();
return NULL;
}
input_line_pointer++; /* skip ',' */
temp = get_absolute_expr (&exp);
sign = (offsetT) 1 << (stdoutput->arch_info->bits_per_address - 1);
size = temp & ((sign << 1) - 1);
if (temp != size || !exp.X_unsigned)
{
as_bad (_(".COMMon length (%ld) out of range, ignored."), (long) temp);
ignore_rest_of_line ();
return NULL;
}
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
{
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
ignore_rest_of_line ();
return NULL;
}
if (S_GET_VALUE (symbolP) != 0)
{
if (S_GET_VALUE (symbolP) != (valueT) size)
{
as_warn (_("length of .comm \"%s\" is already %ld; not changed to %ld"),
S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP),
(long) size);
}
}
know (symbolP->sy_frag == &zero_address_frag);
if (*input_line_pointer != ',')
have_align = 0;
else
{
have_align = 1;
input_line_pointer++;
SKIP_WHITESPACE ();
}
if (! have_align || *input_line_pointer != '"')
{
if (! have_align)
temp = 0;
else
{
temp = get_absolute_expr (&exp);
if (!exp.X_unsigned)
{
temp = 0;
as_warn (_("common alignment negative; 0 assumed"));
}
}
if (symbol_get_obj (symbolP)->local)
{
segT old_sec;
int old_subsec;
char *pfrag;
int align;
/* allocate_bss: */
old_sec = now_seg;
old_subsec = now_subseg;
if (temp)
{
/* convert to a power of 2 alignment */
for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
if (temp != 1)
{
as_bad (_("common alignment not a power of 2"));
ignore_rest_of_line ();
return NULL;
}
}
if (*input_line_pointer == '"')
{
/* For sparc. Accept .common symbol, length, "bss" */
input_line_pointer++;
/* Some use the dot, some don't. */
if (*input_line_pointer == '.')
input_line_pointer++;
/* Some say data, some say bss. */
if (strncmp (input_line_pointer, "bss\"", 4) == 0)
input_line_pointer += 4;
else if (strncmp (input_line_pointer, "data\"", 5) == 0)
input_line_pointer += 5;
else
align = 0;
record_alignment (bss_section, align);
subseg_set (bss_section, 0);
if (align)
frag_align (align, 0, 0);
if (S_GET_SEGMENT (symbolP) == bss_section)
symbol_get_frag (symbolP)->fr_symbol = 0;
symbol_set_frag (symbolP, frag_now);
pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
(offsetT) size, (char *) 0);
*pfrag = 0;
S_SET_SIZE (symbolP, size);
S_SET_SEGMENT (symbolP, bss_section);
S_CLEAR_EXTERNAL (symbolP);
subseg_set (old_sec, old_subsec);
{
char *p = input_line_pointer;
char c;
while (*--p != '"')
;
while (!is_end_of_line[(unsigned char) *input_line_pointer])
if (*input_line_pointer++ == '"')
break;
c = *input_line_pointer;
*input_line_pointer = '\0';
as_bad (_("bad .common segment %s"), p);
*input_line_pointer = c;
ignore_rest_of_line ();
return NULL;
}
/* ??? Don't ask me why these are always global. */
is_local = 0;
}
else
{
allocate_common:
S_SET_VALUE (symbolP, (valueT) size);
S_SET_ALIGN (symbolP, temp);
S_SET_EXTERNAL (symbolP);
S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
input_line_pointer = save;
align = parse_align (is_local);
if (align == (addressT) -1)
return NULL;
}
}
if (is_local)
{
bss_alloc (symbolP, size, align);
S_CLEAR_EXTERNAL (symbolP);
}
else
{
input_line_pointer++;
/* @@ Some use the dot, some don't. Can we get some consistency?? */
if (*input_line_pointer == '.')
input_line_pointer++;
/* @@ Some say data, some say bss. */
if (strncmp (input_line_pointer, "bss\"", 4)
&& strncmp (input_line_pointer, "data\"", 5))
{
while (*--input_line_pointer != '"')
;
input_line_pointer--;
goto bad_common_segment;
}
while (*input_line_pointer++ != '"')
;
goto allocate_common;
S_SET_VALUE (symbolP, size);
S_SET_ALIGN (symbolP, align);
S_SET_EXTERNAL (symbolP);
S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
}
symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
demand_empty_rest_of_line ();
return symbolP;
{
bad_common_segment:
p = input_line_pointer;
while (*p && *p != '\n')
p++;
c = *p;
*p = '\0';
as_bad (_("bad .common segment %s"), input_line_pointer + 1);
*p = c;
input_line_pointer = p;
ignore_rest_of_line ();
return NULL;
}
}
void
obj_elf_common (is_common)
int is_common;
{
elf_common (is_common);
if (flag_mri && is_common)
s_mri_common (0);
else
s_comm_internal (0, elf_common_parse);
}
static void
obj_elf_tls_common (ignore)
int ignore ATTRIBUTE_UNUSED;
{
symbolS *symbolP = elf_common (0);
symbolS *symbolP = s_comm_internal (0, elf_common_parse);
if (symbolP)
symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;

View File

@ -80,6 +80,21 @@ extern valueT alpha_gp_value;
: BFD_RELOC_ALPHA_LINKAGE);
#endif
#ifndef VMS
#define TC_IMPLICIT_LCOMM_ALIGNMENT(size, align) \
do \
{ \
align = 0; \
if (size > 1) \
{ \
addressT temp = 1; \
while ((size & temp) == 0) \
++align, temp <<= 1; \
} \
} \
while (0)
#endif
#define md_number_to_chars number_to_chars_littleendian
extern int tc_get_register PARAMS ((int frame));

View File

@ -214,22 +214,9 @@ static int dwarf_file_string;
#endif
#endif
static void cons_worker (int, int);
static int scrub_from_string (char *, int);
static void do_align (int, char *, int, int);
static void s_align (int, int);
static void s_lcomm_internal (int, int);
static int hex_float (int, char *);
static inline int sizeof_sleb128 (offsetT);
static inline int sizeof_uleb128 (valueT);
static inline int output_sleb128 (char *, offsetT);
static inline int output_uleb128 (char *, valueT);
static inline int output_big_sleb128 (char *, LITTLENUM_TYPE *, int);
static inline int output_big_uleb128 (char *, LITTLENUM_TYPE *, int);
static int output_big_leb128 (char *, LITTLENUM_TYPE *, int, int);
static void do_org (segT, expressionS *, int);
char *demand_copy_string (int *lenP);
static segT get_segmented_expression (expressionS *expP);
static segT get_known_segmented_expression (expressionS * expP);
static void pobegin (void);
static int get_line_sb (sb *);
@ -1328,16 +1315,18 @@ s_align_ptwo (int arg)
s_align (arg, 0);
}
void
s_comm (int ignore ATTRIBUTE_UNUSED)
symbolS *
s_comm_internal (int param,
symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
{
register char *name;
register char c;
register char *p;
offsetT temp;
register symbolS *symbolP;
char *name;
char c;
char *p;
offsetT temp, size;
symbolS *symbolP = NULL;
char *stop = NULL;
char stopc;
expressionS exp;
if (flag_mri)
stop = mri_comment_field (&stopc);
@ -1352,75 +1341,83 @@ s_comm (int ignore ATTRIBUTE_UNUSED)
{
as_bad (_("expected symbol name"));
discard_rest_of_line ();
return;
goto out;
}
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
*p = 0;
as_bad (_("expected comma after \"%s\""), name);
*p = c;
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
input_line_pointer++; /* skip ',' */
if ((temp = get_absolute_expression ()) < 0)
{
as_warn (_(".COMMon length (%lu) out of range ignored"),
(unsigned long) temp);
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
/* Accept an optional comma after the name. The comma used to be
required, but Irix 5 cc does not generate it for .lcomm. */
if (*input_line_pointer == ',')
input_line_pointer++;
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
temp = get_absolute_expr (&exp);
size = temp;
#ifdef BFD_ASSEMBLER
size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
#endif
if (exp.X_op == O_absent)
{
as_bad (_("missing size expression"));
*p = c;
ignore_rest_of_line ();
goto out;
}
else if (temp != size || !exp.X_unsigned)
{
as_warn (_("size (%ld) out of range, ignored"), (long) temp);
*p = c;
ignore_rest_of_line ();
goto out;
}
symbolP = symbol_find_or_make (name);
if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
{
as_bad (_("symbol `%s' is already defined"),
S_GET_NAME (symbolP));
symbolP = NULL;
as_bad (_("symbol `%s' is already defined"), name);
*p = c;
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
goto out;
}
if (S_GET_VALUE (symbolP))
{
if (S_GET_VALUE (symbolP) != (valueT) temp)
as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"),
S_GET_NAME (symbolP),
(long) S_GET_VALUE (symbolP),
(long) temp);
}
size = S_GET_VALUE (symbolP);
if (size == 0)
size = temp;
else if (size != temp)
as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
name, (long) size, (long) temp);
*p = c;
if (comm_parse_extra != NULL)
symbolP = (*comm_parse_extra) (param, symbolP, size);
else
{
S_SET_VALUE (symbolP, (valueT) temp);
S_SET_VALUE (symbolP, (valueT) size);
S_SET_EXTERNAL (symbolP);
}
#ifdef OBJ_VMS
{
extern int flag_one;
if (!temp || !flag_one)
S_GET_OTHER(symbolP) = const_flag;
}
#endif /* not OBJ_VMS */
know (symbolP->sy_frag == &zero_address_frag);
{
extern int flag_one;
if (size == 0 || !flag_one)
S_GET_OTHER (symbolP) = const_flag;
}
#endif
}
know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag);
demand_empty_rest_of_line ();
out:
if (flag_mri)
mri_comment_end (stop, stopc);
} /* s_comm() */
return symbolP;
}
void
s_comm (int ignore)
{
s_comm_internal (ignore, NULL);
}
/* The MRI COMMON pseudo-op. We handle this by creating a common
symbol with the appropriate name. We make s_space do the right
@ -1917,67 +1914,20 @@ s_linkonce (int ignore ATTRIBUTE_UNUSED)
demand_empty_rest_of_line ();
}
static void
s_lcomm_internal (/* 1 if this was a ".bss" directive, which may
require a 3rd argument (alignment); 0 if it was
an ".lcomm" (2 args only). */
int needs_align,
/* 1 if the alignment value should be interpreted as
the byte boundary, rather than the power of 2. */
int bytes_p)
void
bss_alloc (symbolS *symbolP, addressT size, int align)
{
register char *name;
register char c;
register char *p;
register int temp;
register symbolS *symbolP;
char *pfrag;
segT current_seg = now_seg;
subsegT current_subseg = now_subseg;
const int max_alignment = 15;
int align = 0;
segT bss_seg = bss_section;
name = input_line_pointer;
c = get_symbol_end ();
p = input_line_pointer;
*p = c;
if (name == p)
{
as_bad (_("expected symbol name"));
discard_rest_of_line ();
return;
}
SKIP_WHITESPACE ();
/* Accept an optional comma after the name. The comma used to be
required, but Irix 5 cc does not generate it. */
if (*input_line_pointer == ',')
{
++input_line_pointer;
SKIP_WHITESPACE ();
}
if (is_end_of_line[(unsigned char) *input_line_pointer])
{
as_bad (_("missing size expression"));
return;
}
if ((temp = get_absolute_expression ()) < 0)
{
as_warn (_("BSS length (%d) < 0 ignored"), temp);
ignore_rest_of_line ();
return;
}
#if defined (TC_MIPS) || defined (TC_ALPHA)
if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
|| OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
/* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss. */
if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
if (size <= bfd_get_gp_size (stdoutput))
{
bss_seg = subseg_new (".sbss", 1);
seg_info (bss_seg)->bss = 1;
@ -1989,147 +1939,118 @@ s_lcomm_internal (/* 1 if this was a ".bss" directive, which may
}
}
#endif
subseg_set (bss_seg, 1);
if (!needs_align)
if (align)
{
TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
/* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */
if (align)
record_alignment (bss_seg, align);
record_alignment (bss_seg, align);
frag_align (align, 0, 0);
}
/* Detach from old frag. */
if (S_GET_SEGMENT (symbolP) == bss_seg)
symbol_get_frag (symbolP)->fr_symbol = NULL;
symbol_set_frag (symbolP, frag_now);
pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
*pfrag = 0;
#ifdef S_SET_SIZE
S_SET_SIZE (symbolP, size);
#endif
S_SET_SEGMENT (symbolP, bss_seg);
#ifdef OBJ_COFF
/* The symbol may already have been created with a preceding
".globl" directive -- be careful not to step on storage class
in that case. Otherwise, set it to static. */
if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
S_SET_STORAGE_CLASS (symbolP, C_STAT);
#endif /* OBJ_COFF */
subseg_set (current_seg, current_subseg);
}
offsetT
parse_align (int align_bytes)
{
expressionS exp;
addressT align;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
no_align:
as_bad (_("expected alignment after size"));
ignore_rest_of_line ();
return -1;
}
input_line_pointer++;
SKIP_WHITESPACE ();
align = get_absolute_expr (&exp);
if (exp.X_op == O_absent)
goto no_align;
if (!exp.X_unsigned)
{
as_warn (_("alignment negative; 0 assumed"));
align = 0;
}
if (align_bytes && align != 0)
{
/* convert to a power of 2 alignment */
unsigned int alignp2 = 0;
while ((align & 1) == 0)
align >>= 1, ++alignp2;
if (align != 1)
{
as_bad (_("alignment not a power of 2"));
ignore_rest_of_line ();
return -1;
}
align = alignp2;
}
return align;
}
/* Called from s_comm_internal after symbol name and size have been
parsed. NEEDS_ALIGN is 0 if it was an ".lcomm" (2 args only),
1 if this was a ".bss" directive which has a 3rd argument
(alignment as a power of 2), or 2 if this was a ".bss" directive
with alignment in bytes. */
static symbolS *
s_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
{
addressT align = 0;
if (needs_align)
{
align = 0;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("expected comma after size"));
ignore_rest_of_line ();
return;
}
input_line_pointer++;
SKIP_WHITESPACE ();
if (is_end_of_line[(unsigned char) *input_line_pointer])
{
as_bad (_("missing alignment"));
return;
}
align = get_absolute_expression ();
if (bytes_p)
{
/* Convert to a power of 2. */
if (align != 0)
{
unsigned int i;
for (i = 0; (align & 1) == 0; align >>= 1, ++i)
;
if (align != 1)
as_bad (_("alignment not a power of 2"));
align = i;
}
}
if (align > max_alignment)
{
align = max_alignment;
as_warn (_("alignment too large; %d assumed"), align);
}
else if (align < 0)
{
align = 0;
as_warn (_("alignment negative; 0 assumed"));
}
record_alignment (bss_seg, align);
align = parse_align (needs_align - 1);
if (align == (addressT) -1)
return NULL;
}
else
{
/* Assume some objects may require alignment on some systems. */
#if defined (TC_ALPHA) && ! defined (VMS)
if (temp > 1)
{
align = ffs (temp) - 1;
if (temp % (1 << align))
abort ();
}
#endif
}
/* Assume some objects may require alignment on some systems. */
TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
*p = 0;
symbolP = symbol_find_or_make (name);
*p = c;
if (
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
|| defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
#ifdef BFD_ASSEMBLER
(OUTPUT_FLAVOR != bfd_target_aout_flavour
|| (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
#else
(S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
#endif
#endif
(S_GET_SEGMENT (symbolP) == bss_seg
|| (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
{
char *pfrag;
subseg_set (bss_seg, 1);
if (align)
frag_align (align, 0, 0);
/* Detach from old frag. */
if (S_GET_SEGMENT (symbolP) == bss_seg)
symbol_get_frag (symbolP)->fr_symbol = NULL;
symbol_set_frag (symbolP, frag_now);
pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
(offsetT) temp, (char *) 0);
*pfrag = 0;
S_SET_SEGMENT (symbolP, bss_seg);
#ifdef OBJ_COFF
/* The symbol may already have been created with a preceding
".globl" directive -- be careful not to step on storage class
in that case. Otherwise, set it to static. */
if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
{
S_SET_STORAGE_CLASS (symbolP, C_STAT);
}
#endif /* OBJ_COFF */
#ifdef S_SET_SIZE
S_SET_SIZE (symbolP, temp);
#endif
}
else
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
subseg_set (current_seg, current_subseg);
demand_empty_rest_of_line ();
bss_alloc (symbolP, size, align);
return symbolP;
}
void
s_lcomm (int needs_align)
{
s_lcomm_internal (needs_align, 0);
s_comm_internal (needs_align, s_lcomm_internal);
}
void
s_lcomm_bytes (int needs_align)
{
s_lcomm_internal (needs_align, 1);
s_comm_internal (needs_align * 2, s_lcomm_internal);
}
void

View File

@ -139,6 +139,9 @@ extern void generate_lineno_debug (void);
extern void s_abort (int) ATTRIBUTE_NORETURN;
extern void s_align_bytes (int arg);
extern void s_align_ptwo (int);
extern void bss_alloc (symbolS *, addressT, int);
extern offsetT parse_align (int);
extern symbolS *s_comm_internal (int, symbolS *(*) (int, symbolS *, addressT));
extern void s_app_file_string (char *);
extern void s_app_file (int);
extern void s_app_line (int);