From cd924033054232730762c6ecf91c4dfd4d9f9cc7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 15 Aug 1997 18:19:27 +0000 Subject: * as.h (enum debug_info_type): Define. (debug_type): Declare. * as.c (debug_type): New global variable. (show_usage): Add --gstabs. (parse_args): Handle --gstabs. * read.c (generate_asm_lineno): Remove. (read_a_source_file): Output stabs debugging if appropriate. Change checks of generate_asm_lineno to check debug_type. Only generate ECOFF debugging if ECOFF_DEBUGGING is defined. * read.h (generate_asm_lineno): Don't declare. (stabs_generate_asm_lineno): Declare. * stabs.c (stabs_generate_asm_lineno): New function. * ecoff.c (add_file): Use debug_type, not generate_asm_lineno. Don't turn off debugging. (add_file): Remove old #if 0 code. (ecoff_new_file): Set debug_type, not generate_asm_lineno. (ecoff_directive_end): Don't generate stabs line symbols. (ecoff_generate_asm_lineno): Don't check stabs_seen. Don't set generate_asm_lineno. (line_label_cnt): Remove. (ecoff_generate_asm_line_stab): Remove. * ecoff.h (ecoff_generate_asm_line_stab): Don't declare. * doc/as.texinfo, doc/as.1: Document --gstabs. --- gas/ChangeLog | 26 ++++ gas/as.c | 36 ++++- gas/doc/as.1 | 5 + gas/doc/as.texinfo | 6 +- gas/ecoff.c | 103 ++++---------- gas/ecoff.h | 29 ++-- gas/read.c | 384 +++++++++++++++++++++++++++++++++++++++++++++++++---- gas/read.h | 140 +++++++++++-------- 8 files changed, 556 insertions(+), 173 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 4b0b74f..4c02377 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,29 @@ +Fri Aug 15 14:00:13 1997 Ian Lance Taylor + + * as.h (enum debug_info_type): Define. + (debug_type): Declare. + * as.c (debug_type): New global variable. + (show_usage): Add --gstabs. + (parse_args): Handle --gstabs. + * read.c (generate_asm_lineno): Remove. + (read_a_source_file): Output stabs debugging if appropriate. + Change checks of generate_asm_lineno to check debug_type. Only + generate ECOFF debugging if ECOFF_DEBUGGING is defined. + * read.h (generate_asm_lineno): Don't declare. + (stabs_generate_asm_lineno): Declare. + * stabs.c (stabs_generate_asm_lineno): New function. + * ecoff.c (add_file): Use debug_type, not generate_asm_lineno. + Don't turn off debugging. + (add_file): Remove old #if 0 code. + (ecoff_new_file): Set debug_type, not generate_asm_lineno. + (ecoff_directive_end): Don't generate stabs line symbols. + (ecoff_generate_asm_lineno): Don't check stabs_seen. Don't set + generate_asm_lineno. + (line_label_cnt): Remove. + (ecoff_generate_asm_line_stab): Remove. + * ecoff.h (ecoff_generate_asm_line_stab): Don't declare. + * doc/as.texinfo, doc/as.1: Document --gstabs. + start-sanitize-v850 Wed Aug 13 18:58:56 1997 Nick Clifton diff --git a/gas/as.c b/gas/as.c index e1929e6..e5da509 100644 --- a/gas/as.c +++ b/gas/as.c @@ -64,6 +64,10 @@ int listing; /* true if a listing is wanted */ static char *listing_filename = NULL; /* Name of listing file. */ +/* Type of debugging to generate. */ + +enum debug_info_type debug_type = DEBUG_NONE; + /* Maximum level of macro nesting. */ int max_macro_nest = 100; @@ -110,7 +114,7 @@ print_version_id () return; printed = 1; - fprintf (stderr, "GNU assembler version %s (%s)", GAS_VERSION, TARGET_ALIAS); + fprintf (stderr, "GNU assembler version %s (%s)", VERSION, TARGET_ALIAS); #ifdef BFD_ASSEMBLER fprintf (stderr, ", using BFD version %s", BFD_VERSION); #endif @@ -138,6 +142,7 @@ Options:\n\ -D produce assembler debugging messages\n\ --defsym SYM=VAL define symbol SYM to given value\n\ -f skip whitespace and comment preprocessing\n\ +--gstabs generate stabs debugging information\n\ --help show this message and exit\n\ -I DIR add DIR to search list for .include directives\n\ -J don't warn about signed overflow\n\ @@ -145,6 +150,7 @@ Options:\n\ -L keep local symbols (starting with `L')\n"); fprintf (stream, "\ -M,--mri assemble in MRI compatibility mode\n\ +--MD FILE write dependency information in FILE (default none)\n\ -nocpp ignored\n\ -o OBJFILE name the object-file output OBJFILE (default a.out)\n\ -R fold data section into text section\n\ @@ -290,7 +296,7 @@ parse_args (pargc, pargv) #endif 'w', 'X', /* New option for extending instruction set (see also --itbl below) */ - 't', + 't', ':', '\0' }; struct option *longopts; @@ -321,7 +327,11 @@ parse_args (pargc, pargv) list of instruction formats. The additional opcodes and their formats are added to the built-in set of instructions, and mnemonics for new registers may also be defined. */ - {"itbl", required_argument, NULL, OPTION_INSTTBL} + {"itbl", required_argument, NULL, OPTION_INSTTBL}, +#define OPTION_DEPFILE (OPTION_STD_BASE + 9) + {"MD", required_argument, NULL, OPTION_DEPFILE}, +#define OPTION_GSTABS (OPTION_STD_BASE + 10) + {"gstabs", no_argument, NULL, OPTION_GSTABS} }; /* Construct the option lists from the standard list and the @@ -404,7 +414,7 @@ parse_args (pargc, pargv) case OPTION_VERSION: /* This output is intended to follow the GNU standards document. */ - printf ("GNU assembler %s\n", GAS_VERSION); + printf ("GNU assembler %s\n", VERSION); printf ("Copyright 1997 Free Software Foundation, Inc.\n"); printf ("\ This program is free software; you may redistribute it under the terms of\n\ @@ -461,6 +471,12 @@ the GNU General Public License. This program has absolutely no warranty.\n"); formats, opcodes, register names, etc. */ struct itbl_file_list *n; + if (optarg == NULL) + { + as_warn ( "No file name following -t option\n" ); + break; + } + n = (struct itbl_file_list *) xmalloc (sizeof *n); n->next = itbl_files; n->name = optarg; @@ -480,6 +496,14 @@ the GNU General Public License. This program has absolutely no warranty.\n"); } break; + case OPTION_DEPFILE: + start_dependencies (optarg); + break; + + case OPTION_GSTABS: + debug_type = DEBUG_STABS; + break; + case 'J': flag_signed_overflow_ok = 1; break; @@ -737,6 +761,10 @@ main (argc, argv) may not place the same interpretation on the value given. */ if (had_errors () > 0) xexit (EXIT_FAILURE); + + /* Only generate dependency file if assembler was successful. */ + print_dependencies (); + xexit (EXIT_SUCCESS); } diff --git a/gas/doc/as.1 b/gas/doc/as.1 index 1ff0d0b..8aa32a8 100644 --- a/gas/doc/as.1 +++ b/gas/doc/as.1 @@ -15,6 +15,7 @@ GNU as \- the portable GNU assembler. .RB "[\|" \-D "\|]" .RB "[\|" \-\-defsym\ SYM=VAL "\|]" .RB "[\|" \-f "\|]" +.RB "[\|" \-\-gstabs "\|]" .RB "[\|" \-I .I path\c \&\|] @@ -163,6 +164,10 @@ to the search list for .B .include directives. .TP +.B \-\-gstabs +Generate stabs debugging information for each assembler line. This +may help debugging assembler code, if the debugger can handle it. +.TP .B \-K Issue warnings when difference tables altered for long displacements. .TP diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index 0d165d6..5ff1f76 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -199,7 +199,7 @@ Here is a brief summary of how to invoke @code{@value{AS}}. For details, @c to be limited to one line for the header. @smallexample @value{AS} [ -a[cdhlns][=file] ] [ -D ] [ --defsym @var{sym}=@var{val} ] - [ -f ] [ --help ] [ -I @var{dir} ] [ -J ] [ -K ] [ -L ] + [ -f ] [ --gstabs ] [ --help ] [ -I @var{dir} ] [ -J ] [ -K ] [ -L ] [ -o @var{objfile} ] [ -R ] [ --statistics ] [ -v ] [ -version ] [ --version ] [ -W ] [ -w ] [ -x ] [ -Z ] @ifset A29K @@ -293,6 +293,10 @@ indicates a hexadecimal value, and a leading @samp{0} indicates an octal value. ``fast''---skip whitespace and comment preprocessing (assume source is compiler output). +@item --gstabs +Generate stabs debugging information for each assembler line. This +may help debugging assembler code, if the debugger can handle it. + @item --help Print a summary of the command line options and exit. diff --git a/gas/ecoff.c b/gas/ecoff.c index ed5df5f..0821922 100644 --- a/gas/ecoff.c +++ b/gas/ecoff.c @@ -2215,11 +2215,14 @@ add_file (file_name, indx, fake) as_where (&file, (unsigned int *) NULL); file_name = (const char *) file; - if (! symbol_table_frozen) - generate_asm_lineno = 1; + /* Automatically generate ECOFF debugging information, since I + think that's what other ECOFF assemblers do. We don't do + this if we see a .file directive with a string, since that + implies that some sort of debugging information is being + provided. */ + if (! symbol_table_frozen && debug_type == DEBUG_NONE) + debug_type = DEBUG_ECOFF; } - else - generate_asm_lineno = 0; #ifndef NO_LISTING if (listing) @@ -2319,23 +2322,6 @@ add_file (file_name, indx, fake) fil_ptr->int_type = add_aux_sym_tir (&int_type_info, hash_yes, &cur_file_ptr->thash_head[0]); - /* gas used to have a bug that if the file does not have any - symbol, it either will abort or will not build the file, - the following is to get around that problem. ---kung*/ -#if 0 - if (generate_asm_lineno) - { - mark_stabs (0); - (void) add_ecoff_symbol (file_name, st_Nil, sc_Nil, - symbol_new ("L0\001", now_seg, - (valueT) frag_now_fix (), - frag_now), - (bfd_vma) 0, 0, ECOFF_MARK_STAB (N_SO)); - (void) add_ecoff_symbol ("void:t1=1", st_Nil, sc_Nil, - (symbolS *) NULL, (bfd_vma) 0, 0, - ECOFF_MARK_STAB (N_LSYM)); - } -#endif } } @@ -2350,7 +2336,11 @@ ecoff_new_file (name) if (cur_file_ptr != NULL && strcmp (cur_file_ptr->name, name) == 0) return; add_file (name, 0, 0); - generate_asm_lineno = 1; + + /* This is a hand coded assembler file, so automatically turn on + debugging information. */ + if (debug_type == DEBUG_NONE) + debug_type = DEBUG_ECOFF; } #ifdef ECOFF_DEBUG @@ -3058,25 +3048,11 @@ ecoff_directive_end (ignore) if (ent == (symbolS *) NULL) as_warn (".end directive names unknown symbol"); else - { - (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, - symbol_new ("L0\001", now_seg, - (valueT) frag_now_fix (), - frag_now), - (bfd_vma) 0, (symint_t) 0, (symint_t) 0); - - if (stabs_seen && generate_asm_lineno) - { - char *n; - - n = xmalloc (strlen (name) + 4); - strcpy (n, name); - strcat (n, ":F1"); - (void) add_ecoff_symbol ((const char *) n, stGlobal, scText, - ent, (bfd_vma) 0, 0, - ECOFF_MARK_STAB (N_FUN)); - } - } + (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, + symbol_new ("L0\001", now_seg, + (valueT) frag_now_fix (), + frag_now), + (bfd_vma) 0, (symint_t) 0, (symint_t) 0); cur_proc_ptr = (proc_t *) NULL; @@ -4297,6 +4273,11 @@ ecoff_build_symbols (backend, buf, bufend, offset) && local) sym_ptr->ecoff_sym.asym.index = isym - ifilesym - 1; sym_ptr->ecoff_sym.ifd = fil_ptr->file_index; + + /* Don't try to merge an FDR which has an + external symbol attached to it. */ + if (S_IS_EXTERNAL (as_sym) || S_IS_WEAK (as_sym)) + fil_ptr->fdr.fMerge = 0; } } } @@ -5353,18 +5334,9 @@ ecoff_generate_asm_lineno (filename, lineno) { lineno_list_t *list; - /* this potential can cause problem, when we start to see stab half the - way thru the file */ -/* - if (stabs_seen) - ecoff_generate_asm_line_stab(filename, lineno); -*/ - - if (current_stabs_filename == (char *)NULL || strcmp (current_stabs_filename, filename)) - { - add_file (filename, 0, 1); - generate_asm_lineno = 1; - } + if (current_stabs_filename == (char *)NULL + || strcmp (current_stabs_filename, filename)) + add_file (filename, 0, 1); list = allocate_lineno_list (); @@ -5398,29 +5370,4 @@ ecoff_generate_asm_lineno (filename, lineno) } } -static int line_label_cnt = 0; -void -ecoff_generate_asm_line_stab (filename, lineno) - char *filename; - int lineno; -{ - char *ll; - - if (strcmp (current_stabs_filename, filename)) - { - add_file (filename, 0, 1); - generate_asm_lineno = 1; - } - - line_label_cnt++; - /* generate local label $LMnn */ - ll = xmalloc(10); - sprintf(ll, "$LM%d", line_label_cnt); - colon (ll); - - /* generate stab for the line */ - generate_ecoff_stab ('n', ll, N_SLINE, 0, lineno); - -} - #endif /* ECOFF_DEBUGGING */ diff --git a/gas/ecoff.h b/gas/ecoff.h index 6042cb9..ed0be76 100644 --- a/gas/ecoff.h +++ b/gas/ecoff.h @@ -1,5 +1,5 @@ /* ecoff.h -- header file for ECOFF debugging support - Copyright (C) 1993 Free Software Foundation, Inc. + Copyright (C) 1993, 94, 95, 1996 Free Software Foundation, Inc. Contributed by Cygnus Support. Put together by Ian Lance Taylor . @@ -16,8 +16,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with GAS; see the file COPYING. If not, write to - the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ #ifdef ECOFF_DEBUGGING @@ -34,6 +35,10 @@ extern int ecoff_debugging_seen; obj_read_begin_hook. */ extern void ecoff_read_begin_hook PARAMS ((void)); +/* This function should be called when the assembler switches to a new + file. */ +extern void ecoff_new_file PARAMS ((const char *)); + /* This function should be called when a new symbol is created, by obj_symbol_new_hook. */ extern void ecoff_symbol_new_hook PARAMS ((struct symbol *)); @@ -59,6 +64,10 @@ extern void ecoff_directive_frame PARAMS ((int)); extern void ecoff_directive_loc PARAMS ((int)); extern void ecoff_directive_mask PARAMS ((int)); +/* Other ECOFF directives. */ +extern void ecoff_directive_extern PARAMS ((int)); +extern void ecoff_directive_weakext PARAMS ((int)); + /* Functions to handle the COFF debugging directives. */ extern void ecoff_directive_def PARAMS ((int)); extern void ecoff_directive_dim PARAMS ((int)); @@ -83,16 +92,16 @@ extern void ecoff_set_gp_prolog_size PARAMS ((int sz)); extern void obj_ecoff_set_ext PARAMS ((struct symbol *, EXTR *)); #endif -/* This function is called from read.c to peek at cur_file_ptr */ +/* This routine is used to patch up a line number directive when + instructions are moved around. */ +extern void ecoff_fix_loc PARAMS ((fragS *, unsigned long)); + +/* This function is called from read.c to peek at cur_file_ptr. */ extern int ecoff_no_current_file PARAMS ((void)); -/* This routine is called from read.c to generate line number for .s file -*/ +/* This routine is called from read.c to generate line number for .s + file. */ extern void ecoff_generate_asm_lineno PARAMS ((const char *, int)); -/* This routine is called from read.c to generate line number stabs for .s file -*/ -extern void ecoff_generate_asm_line_stab PARAMS ((char *, int)); - #endif /* ! GAS_ECOFF_H */ #endif /* ECOFF_DEBUGGING */ diff --git a/gas/read.c b/gas/read.c index 450046b..791ca88 100644 --- a/gas/read.c +++ b/gas/read.c @@ -63,8 +63,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA char *input_line_pointer; /*->next char of source file to parse. */ -int generate_asm_lineno = 0; /* flag to generate line stab for .s file */ - #if BITS_PER_CHAR != 8 /* The following table is indexed by[(char)] and will break if a char does not have exactly 256 states (hopefully 0:255!)! */ @@ -290,6 +288,7 @@ static const pseudo_typeS potable[] = {"endif", s_endif, 0}, /* endef */ {"equ", s_set, 0}, + {"equiv", s_set, 1}, {"err", s_err, 0}, {"exitm", s_mexit, 0}, /* extend */ @@ -363,6 +362,7 @@ static const pseudo_typeS potable[] = /* size */ {"space", s_space, 0}, {"skip", s_space, 0}, + {"sleb128", s_leb128, 1}, {"spc", s_ignore, 0}, {"stabd", s_stab, 'd'}, {"stabn", s_stab, 'n'}, @@ -385,6 +385,7 @@ static const pseudo_typeS potable[] = {"title", listing_title, 0}, /* Listing title */ {"ttl", listing_title, 0}, /* type */ + {"uleb128", s_leb128, 0}, /* use */ /* val */ {"xcom", s_comm, 0}, @@ -487,6 +488,7 @@ read_a_source_file (name) listing_file (name); listing_newline (""); + register_dependency (name); while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0) { /* We have another line to parse. */ @@ -782,20 +784,29 @@ read_a_source_file (name) c = *input_line_pointer; *input_line_pointer = '\0'; + if (debug_type == DEBUG_STABS) + stabs_generate_asm_lineno (); + #ifdef OBJ_GENERATE_ASM_LINENO - if (generate_asm_lineno == 0) +#ifdef ECOFF_DEBUGGING + /* ECOFF assemblers automatically generate + debugging information. FIXME: This should + probably be handled elsewhere. */ + if (debug_type == DEBUG_NONE) { - if (ecoff_no_current_file ()) - generate_asm_lineno = 1; + if (ecoff_no_current_file ()) + debug_type = DEBUG_ECOFF; } - if (generate_asm_lineno == 1) + + if (debug_type == DEBUG_ECOFF) { unsigned int lineno; char *s; as_where (&s, &lineno); OBJ_GENERATE_ASM_LINENO (s, lineno); - } + } +#endif #endif if (macro_defined) @@ -1109,8 +1120,21 @@ do_align (n, fill, len, max) if (fill == NULL) { - /* FIXME: Fix this right for BFD! */ + int maybe_text; + +#ifdef BFD_ASSEMBLER + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + maybe_text = 1; + else + maybe_text = 0; +#else if (now_seg != data_section && now_seg != bss_section) + maybe_text = 1; + else + maybe_text = 0; +#endif + + if (maybe_text) default_fill = NOP_OPCODE; else default_fill = 0; @@ -1313,7 +1337,7 @@ s_comm (ignore) *p = 0; symbolP = symbol_find_or_make (name); *p = c; - if (S_IS_DEFINED (symbolP)) + if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) { as_bad ("Ignoring attempt to re-define symbol `%s'.", S_GET_NAME (symbolP)); @@ -1412,17 +1436,12 @@ s_mri_common (small) align = get_absolute_expression (); } - if (S_IS_DEFINED (sym)) + if (S_IS_DEFINED (sym) && ! S_IS_COMMON (sym)) { -#if defined (S_IS_COMMON) || defined (BFD_ASSEMBLER) - if (! S_IS_COMMON (sym)) -#endif - { - as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym)); - mri_comment_end (stop, stopc); - ignore_rest_of_line (); - return; - } + as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym)); + mri_comment_end (stop, stopc); + ignore_rest_of_line (); + return; } S_SET_EXTERNAL (sym); @@ -1514,6 +1533,7 @@ s_app_file (appfile) if (listing) listing_source_file (s); #endif + register_dependency (s); } #ifdef obj_app_file obj_app_file (s); @@ -1647,7 +1667,9 @@ s_fill (ignore) if (temp_size && !need_pass_2) { - p = frag_var (rs_fill, (int) temp_size, (int) temp_size, (relax_substateT) 0, (symbolS *) 0, temp_repeat, (char *) 0); + p = frag_var (rs_fill, (int) temp_size, (int) temp_size, + (relax_substateT) 0, (symbolS *) 0, (offsetT) temp_repeat, + (char *) 0); memset (p, 0, (unsigned int) temp_size); /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX * flavoured AS. The following bizzare behaviour is to be @@ -1960,7 +1982,7 @@ s_lcomm (needs_align) symbolP->sy_frag = frag_now; pfrag = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, - temp, (char *)0); + (offsetT) temp, (char *) 0); *pfrag = 0; S_SET_SEGMENT (symbolP, bss_seg); @@ -2165,6 +2187,7 @@ void s_mexit (ignore) int ignore; { + cond_exit_macro (macro_nest); buffer_limit = input_scrub_next_buffer (&input_line_pointer); } @@ -2519,9 +2542,13 @@ s_rept (ignore) buffer_limit = input_scrub_next_buffer (&input_line_pointer); } +/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then + this is .equiv, and it is an error if the symbol is already + defined. */ + void -s_set (ignore) - int ignore; +s_set (equiv) + int equiv; { register char *name; register char delim; @@ -2580,6 +2607,12 @@ s_set (ignore) symbol_table_insert (symbolP); *end_name = delim; + + if (equiv + && S_IS_DEFINED (symbolP) + && S_GET_SEGMENT (symbolP) != reg_section) + as_bad ("symbol `%s' already defined", S_GET_NAME (symbolP)); + pseudo_set (symbolP); demand_empty_rest_of_line (); } /* s_set() */ @@ -2710,7 +2743,7 @@ s_space (mult) if (!need_pass_2) p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0, - repeat, (char *) 0); + (offsetT) repeat, (char *) 0); } else { @@ -2726,7 +2759,7 @@ s_space (mult) } if (!need_pass_2) p = frag_var (rs_space, 1, 1, (relax_substateT) 0, - make_expr_symbol (&exp), 0L, (char *) 0); + make_expr_symbol (&exp), (offsetT) 0, (char *) 0); } if (p) @@ -3844,6 +3877,306 @@ float_cons (float_type) demand_empty_rest_of_line (); } /* float_cons() */ +/* Return the size of a LEB128 value */ + +static inline int +sizeof_sleb128 (value) + offsetT value; +{ + register int size = 0; + register unsigned byte; + + do + { + byte = (value & 0x7f); + /* Sadly, we cannot rely on typical arithmetic right shift behaviour. + Fortunately, we can structure things so that the extra work reduces + to a noop on systems that do things "properly". */ + value = (value >> 7) | ~(-(offsetT)1 >> 7); + size += 1; + } + while (!(((value == 0) && ((byte & 0x40) == 0)) + || ((value == -1) && ((byte & 0x40) != 0)))); + + return size; +} + +static inline int +sizeof_uleb128 (value) + valueT value; +{ + register int size = 0; + register unsigned byte; + + do + { + byte = (value & 0x7f); + value >>= 7; + size += 1; + } + while (value != 0); + + return size; +} + +inline int +sizeof_leb128 (value, sign) + valueT value; + int sign; +{ + if (sign) + return sizeof_sleb128 ((offsetT) value); + else + return sizeof_uleb128 (value); +} + +/* Output a LEB128 value. */ + +static inline int +output_sleb128 (p, value) + char *p; + offsetT value; +{ + register char *orig = p; + register int more; + + do + { + unsigned byte = (value & 0x7f); + + /* Sadly, we cannot rely on typical arithmetic right shift behaviour. + Fortunately, we can structure things so that the extra work reduces + to a noop on systems that do things "properly". */ + value = (value >> 7) | ~(-(offsetT)1 >> 7); + + more = !((((value == 0) && ((byte & 0x40) == 0)) + || ((value == -1) && ((byte & 0x40) != 0)))); + if (more) + byte |= 0x80; + + *p++ = byte; + } + while (more); + + return p - orig; +} + +static inline int +output_uleb128 (p, value) + char *p; + valueT value; +{ + char *orig = p; + + do + { + unsigned byte = (value & 0x7f); + value >>= 7; + if (value != 0) + /* More bytes to follow. */ + byte |= 0x80; + + *p++ = byte; + } + while (value != 0); + + return p - orig; +} + +inline int +output_leb128 (p, value, sign) + char *p; + valueT value; + int sign; +{ + if (sign) + return output_sleb128 (p, (offsetT) value); + else + return output_uleb128 (p, value); +} + +/* Do the same for bignums. We combine sizeof with output here in that + we don't output for NULL values of P. It isn't really as critical as + for "normal" values that this be streamlined. */ + +static int +output_big_sleb128 (p, bignum, size) + char *p; + LITTLENUM_TYPE *bignum; + int size; +{ + char *orig = p; + valueT val; + int loaded = 0; + unsigned byte; + + /* Strip leading sign extensions off the bignum. */ + while (size > 0 && bignum[size-1] == (LITTLENUM_TYPE)-1) + size--; + + do + { + if (loaded < 7 && size > 0) + { + val |= (*bignum << loaded); + loaded += 8 * CHARS_PER_LITTLENUM; + size--; + bignum++; + } + + byte = val & 0x7f; + loaded -= 7; + val >>= 7; + + if (size == 0) + { + if ((val == 0 && (byte & 0x40) == 0) + || (~(val | ~(((valueT)1 << loaded) - 1)) == 0 + && (byte & 0x40) != 0)) + byte |= 0x80; + } + + if (orig) + *p = byte; + p++; + } + while (byte & 0x80); + + return p - orig; +} + +static int +output_big_uleb128 (p, bignum, size) + char *p; + LITTLENUM_TYPE *bignum; + int size; +{ + char *orig = p; + valueT val; + int loaded = 0; + unsigned byte; + + /* Strip leading zeros off the bignum. */ + /* XXX: Is this needed? */ + while (size > 0 && bignum[size-1] == 0) + size--; + + do + { + if (loaded < 7 && size > 0) + { + val |= (*bignum << loaded); + loaded += 8 * CHARS_PER_LITTLENUM; + size--; + bignum++; + } + + byte = val & 0x7f; + loaded -= 7; + val >>= 7; + + if (size > 0 || val) + byte |= 0x80; + + if (orig) + *p = byte; + p++; + } + while (byte & 0x80); + + return p - orig; +} + +static inline int +output_big_leb128 (p, bignum, size, sign) + char *p; + LITTLENUM_TYPE *bignum; + int size, sign; +{ + if (sign) + return output_big_sleb128 (p, bignum, size); + else + return output_big_uleb128 (p, bignum, size); +} + +/* Generate the appropriate fragments for a given expression to emit a + leb128 value. */ + +void +emit_leb128_expr(exp, sign) + expressionS *exp; + int sign; +{ + operatorT op = exp->X_op; + + if (op == O_absent || op == O_illegal) + { + as_warn ("zero assumed for missing expression"); + exp->X_add_number = 0; + op = O_constant; + } + else if (op == O_big && exp->X_add_number <= 0) + { + as_bad ("floating point number invalid; zero assumed"); + exp->X_add_number = 0; + op = O_constant; + } + else if (op == O_register) + { + as_warn ("register value used as expression"); + op = O_constant; + } + + if (op == O_constant) + { + /* If we've got a constant, emit the thing directly right now. */ + + valueT value = exp->X_add_number; + int size; + char *p; + + size = sizeof_leb128 (value, sign); + p = frag_more (size); + output_leb128 (p, value, sign); + } + else if (op == O_big) + { + /* O_big is a different sort of constant. */ + + int size; + char *p; + + size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign); + p = frag_more (size); + output_big_leb128 (p, generic_bignum, exp->X_add_number, sign); + } + else + { + /* Otherwise, we have to create a variable sized fragment and + resolve things later. */ + + frag_var (rs_leb128, sizeof_uleb128 (~(valueT)0), 0, sign, + make_expr_symbol (exp), 0, (char *) NULL); + } +} + +/* Parse the .sleb128 and .uleb128 pseudos. */ + +void +s_leb128 (sign) + int sign; +{ + expressionS exp; + + do { + expression (&exp); + emit_leb128_expr (&exp, sign); + } while (*input_line_pointer++ == ','); + + input_line_pointer--; + demand_empty_rest_of_line (); +} + /* * stringer() * @@ -4289,6 +4622,7 @@ s_include (arg) path = filename; gotit: /* malloc Storage leak when file is found on path. FIXME-SOMEDAY. */ + register_dependency (path); newbuf = input_scrub_include_file (path, input_line_pointer); buffer_limit = input_scrub_next_buffer (&input_line_pointer); } /* s_include() */ diff --git a/gas/read.h b/gas/read.h index e2f51ef..674d50f 100644 --- a/gas/read.h +++ b/gas/read.h @@ -1,6 +1,5 @@ /* read.h - of read.c - - Copyright (C) 1986, 1990, 1992 Free Software Foundation, Inc. + Copyright (C) 1986, 90, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -50,6 +49,8 @@ extern char *input_line_pointer;/* -> char we are parsing now. */ extern char lex_type[]; extern char is_end_of_line[]; +extern int is_it_end_of_statement PARAMS ((void)); + extern int target_big_endian; /* These are initialized by the CPU specific target files (tc-*.c). */ @@ -57,65 +58,94 @@ extern const char comment_chars[]; extern const char line_comment_chars[]; extern const char line_separator_chars[]; -/* This flag whether to generate line info for asm file */ -extern int generate_asm_lineno; - /* The offset in the absolute section. */ extern addressT abs_section_offset; -/* The MRI label on a line, used by some of the MRI pseudo-ops. */ -extern symbolS *mri_line_label; +/* The label on a line, used by some of the pseudo-ops. */ +extern symbolS *line_label; /* This is used to support MRI common sections. */ extern symbolS *mri_common_symbol; -unsigned int get_stab_string_offset PARAMS ((const char *string, - const char *stabstr_secname)); - -char *demand_copy_C_string PARAMS ((int *len_pointer)); -char get_absolute_expression_and_terminator PARAMS ((long *val_pointer)); -offsetT get_absolute_expression PARAMS ((void)); -unsigned int next_char_of_string PARAMS ((void)); -void add_include_dir PARAMS ((char *path)); -void cons PARAMS ((int nbytes)); -void demand_empty_rest_of_line PARAMS ((void)); -void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes)); -void equals PARAMS ((char *sym_name)); -void float_cons PARAMS ((int float_type)); -void ignore_rest_of_line PARAMS ((void)); -void pseudo_set PARAMS ((symbolS * symbolP)); -void read_a_source_file PARAMS ((char *name)); -void read_begin PARAMS ((void)); -void s_abort PARAMS ((int)); -void s_align_bytes PARAMS ((int arg)); -void s_align_ptwo PARAMS ((int)); -void s_app_file PARAMS ((int)); -void s_app_line PARAMS ((int)); -void s_comm PARAMS ((int)); -void s_data PARAMS ((int)); -void s_desc PARAMS ((int)); -void s_else PARAMS ((int arg)); -void s_end PARAMS ((int arg)); -void s_endif PARAMS ((int arg)); -void s_fail PARAMS ((int)); -void s_fill PARAMS ((int)); -void s_float_space PARAMS ((int mult)); -void s_globl PARAMS ((int arg)); -void s_if PARAMS ((int arg)); -void s_ifdef PARAMS ((int arg)); -void s_ifeqs PARAMS ((int arg)); -void s_ignore PARAMS ((int arg)); -void s_include PARAMS ((int arg)); -void s_lcomm PARAMS ((int needs_align)); -void s_lsym PARAMS ((int)); -void s_mri_common PARAMS ((int)); -void s_org PARAMS ((int)); -void s_set PARAMS ((int)); -void s_space PARAMS ((int mult)); -void s_stab PARAMS ((int what)); -void s_struct PARAMS ((int)); -void s_text PARAMS ((int)); -void stringer PARAMS ((int append_zero)); -void s_xstab PARAMS ((int what)); +/* Possible arguments to .linkonce. */ +enum linkonce_type +{ + LINKONCE_UNSET = 0, + LINKONCE_DISCARD, + LINKONCE_ONE_ONLY, + LINKONCE_SAME_SIZE, + LINKONCE_SAME_CONTENTS +}; + +extern void pop_insert PARAMS ((const pseudo_typeS *)); +extern unsigned int get_stab_string_offset + PARAMS ((const char *string, const char *stabstr_secname)); +extern char *demand_copy_C_string PARAMS ((int *len_pointer)); +extern char get_absolute_expression_and_terminator + PARAMS ((long *val_pointer)); +extern offsetT get_absolute_expression PARAMS ((void)); +extern unsigned int next_char_of_string PARAMS ((void)); +extern void s_mri_sect PARAMS ((char *)); +extern char *mri_comment_field PARAMS ((char *)); +extern void mri_comment_end PARAMS ((char *, int)); +extern void add_include_dir PARAMS ((char *path)); +extern void cons PARAMS ((int nbytes)); +extern void demand_empty_rest_of_line PARAMS ((void)); +extern void emit_expr PARAMS ((expressionS *exp, unsigned int nbytes)); +extern void emit_leb128_expr PARAMS ((expressionS *, int)); +extern void equals PARAMS ((char *sym_name, int reassign)); +extern void float_cons PARAMS ((int float_type)); +extern void ignore_rest_of_line PARAMS ((void)); +extern int output_leb128 PARAMS ((char *, valueT, int sign)); +extern void pseudo_set PARAMS ((symbolS * symbolP)); +extern void read_a_source_file PARAMS ((char *name)); +extern void read_begin PARAMS ((void)); +extern void read_print_statistics PARAMS ((FILE *)); +extern int sizeof_leb128 PARAMS ((valueT, int sign)); +extern void stabs_generate_asm_lineno PARAMS ((void)); + +extern void s_abort PARAMS ((int)); +extern void s_align_bytes PARAMS ((int arg)); +extern void s_align_ptwo PARAMS ((int)); +extern void s_app_file PARAMS ((int)); +extern void s_app_line PARAMS ((int)); +extern void s_comm PARAMS ((int)); +extern void s_data PARAMS ((int)); +extern void s_desc PARAMS ((int)); +extern void s_else PARAMS ((int arg)); +extern void s_end PARAMS ((int arg)); +extern void s_endif PARAMS ((int arg)); +extern void s_err PARAMS ((int)); +extern void s_fail PARAMS ((int)); +extern void s_fill PARAMS ((int)); +extern void s_float_space PARAMS ((int mult)); +extern void s_globl PARAMS ((int arg)); +extern void s_if PARAMS ((int arg)); +extern void s_ifc PARAMS ((int arg)); +extern void s_ifdef PARAMS ((int arg)); +extern void s_ifeqs PARAMS ((int arg)); +extern void s_ignore PARAMS ((int arg)); +extern void s_include PARAMS ((int arg)); +extern void s_irp PARAMS ((int arg)); +extern void s_lcomm PARAMS ((int needs_align)); +extern void s_leb128 PARAMS ((int sign)); +extern void s_linkonce PARAMS ((int)); +extern void s_lsym PARAMS ((int)); +extern void s_macro PARAMS ((int)); +extern void s_mexit PARAMS ((int)); +extern void s_mri PARAMS ((int)); +extern void s_mri_common PARAMS ((int)); +extern void s_org PARAMS ((int)); +extern void s_print PARAMS ((int)); +extern void s_purgem PARAMS ((int)); +extern void s_rept PARAMS ((int)); +extern void s_set PARAMS ((int)); +extern void s_space PARAMS ((int mult)); +extern void s_stab PARAMS ((int what)); +extern void s_struct PARAMS ((int)); +extern void s_text PARAMS ((int)); +extern void stringer PARAMS ((int append_zero)); +extern void s_xstab PARAMS ((int what)); +extern void s_rva PARAMS ((int)); /* end of read.h */ -- cgit v1.1