⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 varasm.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* Output variables, constants and external declarations, for GNU compiler.   Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* This file handles generation of all the assembler code   *except* the instructions of a function.   This includes declarations of variables and their initial values.   We also output the assembler code for constants stored in memory   and are responsible for combining constants with the same value.  */#include <stdio.h>#include <setjmp.h>/* #include <stab.h> */#include "config.h"#include "rtl.h"#include "tree.h"#include "flags.h"#include "expr.h"#include "hard-reg-set.h"#include "obstack.h"#define MIN(a, b) ((a) < (b) ? (a) : (b))/* File in which assembler code is being written.  */extern FILE *asm_out_file;extern struct obstack *current_obstack;extern struct obstack *saveable_obstack;extern struct obstack permanent_obstack;#define obstack_chunk_alloc xmallocextern int xmalloc ();/* Number for making the label on the next   constant that is stored in memory.  */int const_labelno;/* Number for making the label on the next   static variable internal to a function.  */int var_labelno;/* Nonzero if at least one function definition has been seen.  */static int function_defined;extern FILE *asm_out_file;static char *compare_constant_1 ();static void record_constant_1 ();void assemble_name ();void output_addressed_constants ();void output_constant ();void output_constructor ();#ifdef EXTRA_SECTIONSstatic enum in_section {no_section, in_text, in_data, EXTRA_SECTIONS} in_section  = no_section;#elsestatic enum in_section {no_section, in_text, in_data} in_section  = no_section;#endif/* Define functions like text_section for any extra sections.  */#ifdef EXTRA_SECTION_FUNCTIONSEXTRA_SECTION_FUNCTIONS#endif/* Tell assembler to switch to text section.  */voidtext_section (){  if (in_section != in_text)    {      fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);      in_section = in_text;    }}/* Tell assembler to switch to data section.  */voiddata_section (){  if (in_section != in_data)    {      if (flag_shared_data)	{#ifdef SHARED_SECTION_ASM_OP	  fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);#else	  fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);#endif	}      else	fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);      in_section = in_data;    }}/* Determine if we're in the text section. */intin_text_section (){  return in_section == in_text;}/* Create the rtl to represent a function, for a function definition.   DECL is a FUNCTION_DECL node which describes which function.   The rtl is stored into DECL.  */voidmake_function_rtl (decl)     tree decl;{  if (DECL_RTL (decl) == 0)    DECL_RTL (decl)      = gen_rtx (MEM, DECL_MODE (decl),		 gen_rtx (SYMBOL_REF, Pmode, DECL_ASSEMBLER_NAME (decl)));  /* Record at least one function has been defined.  */  function_defined = 1;}/* Decode an `asm' spec for a declaration as a register name.   Return the register number, or -1 if nothing specified,   or -2 if the name is not a register.  */intdecode_reg_name (asmspec)     char *asmspec;{  if (asmspec != 0)    {      int i;      extern char *reg_names[];      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)	if (!strcmp (asmspec, reg_names[i]))	  break;      if (i < FIRST_PSEUDO_REGISTER)	return i;      else	return -2;    }  return -1;}/* Create the DECL_RTL for a declaration for a static or external variable   or static or external function.   ASMSPEC, if not 0, is the string which the user specified   as the assembler symbol name.   TOP_LEVEL is nonzero if this is a file-scope variable.   This is never called for PARM_DECL nodes.  */voidmake_decl_rtl (decl, asmspec, top_level)     tree decl;     char *asmspec;     int top_level;{  register char *name = DECL_ASSEMBLER_NAME (decl);  int reg_number = decode_reg_name (asmspec);  if (reg_number == -2)    {      name = (char *) obstack_alloc (saveable_obstack,				     strlen (asmspec) + 2);      name[0] = '*';      strcpy (&name[1], asmspec);    }  /* For a duplicate declaration, we can be called twice on the     same DECL node.  Don't alter the RTL already made     unless the old mode is wrong (which can happen when     the previous rtl was made when the type was incomplete).  */  if (DECL_RTL (decl) == 0      || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))    {      DECL_RTL (decl) = 0;      /* First detect errors in declaring global registers.  */      if (TREE_REGDECL (decl) && reg_number == -1)	error_with_decl (decl,			 "register name not specified for `%s'");      else if (TREE_REGDECL (decl) && reg_number == -2)	error_with_decl (decl,			 "invalid register name for `%s'");      else if (reg_number >= 0 && ! TREE_REGDECL (decl))	error_with_decl (decl,			 "register name given for non-register variable `%s'");      else if (TREE_REGDECL (decl) && TREE_CODE (decl) == FUNCTION_DECL)	error ("function declared `register'");      else if (TREE_REGDECL (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)	error_with_decl (decl, "data type of `%s' isn't suitable for a register");      /* Now handle properly declared static register variables.  */      else if (TREE_REGDECL (decl))	{	  int nregs;	  if (pedantic)	    warning ("ANSI C forbids explicit register variables");	  if (DECL_INITIAL (decl) != 0 && top_level)	    {	      DECL_INITIAL (decl) = 0;	      error ("global register variable has initial value");	    }	  if (fixed_regs[reg_number] == 0	      && function_defined && top_level)	    error ("global register variable follows a function definition");	  DECL_RTL (decl) = gen_rtx (REG, DECL_MODE (decl), reg_number);	  if (top_level)	    {	      /* Make this register fixed, so not usable for anything else.  */	      nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl));	      while (nregs > 0)		global_regs[reg_number + --nregs] = 1;	      init_reg_sets_1 ();	    }	}      /* Now handle ordinary static variables and functions (in memory).	 Also handle vars declared register invalidly.  */      if (DECL_RTL (decl) == 0)	{	  /* Can't use just the variable's own name for a variable	     whose scope is less than the whole file.	     Concatenate a distinguishing number.  */	  if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0)	    {	      char *label;	      ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);	      name = obstack_copy0 (saveable_obstack, label, strlen (label));	      var_labelno++;	    }	  DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),				     gen_rtx (SYMBOL_REF, Pmode, name));	  if (TREE_EXTERNAL (decl) && TREE_PUBLIC (decl))	    EXTERNAL_SYMBOL_P (XEXP (DECL_RTL (decl), 0)) = 1; 	  if (TREE_VOLATILE (decl))	    MEM_VOLATILE_P (DECL_RTL (decl)) = 1;	  if (TREE_READONLY (decl))	    RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;	  MEM_IN_STRUCT_P (DECL_RTL (decl))	    = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE	       || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE	       || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);	}    }}/* Output a string of literal assembler code   for an `asm' keyword used between functions.  */voidassemble_asm (string)     tree string;{  app_enable ();  fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));}/* Output assembler code associated with defining the name of a function   as described by DECL.  */voidassemble_function (decl)     tree decl;{  rtx x, n;  char *fnname;  int align;  /* Get the function's name, as described by its RTL.     This may be different from the DECL_NAME name used in the source file.  */  x = DECL_RTL (decl);  if (GET_CODE (x) != MEM)    abort ();  n = XEXP (x, 0);  if (GET_CODE (n) != SYMBOL_REF)    abort ();  fnname = XSTR (n, 0);  /* The following code does not need preprocessing in the assembler.  */  app_disable ();  text_section ();#ifdef SDB_DEBUGGING_INFO  /* Make sure types are defined for debugger before fcn name is defined.  */  if (write_symbols == SDB_DEBUG)    sdbout_tags (gettags ());#endif  /* Tell assembler to move to target machine's alignment for functions.  */  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);  if (align > 0)    ASM_OUTPUT_ALIGN (asm_out_file, align);#ifdef SDB_DEBUGGING_INFO  /* Output SDB definition of the function.  */  if (write_symbols == SDB_DEBUG)    sdbout_mark_begin_function ();#endif  /* Make function name accessible from other files, if appropriate.  */  if (TREE_PUBLIC (decl))    ASM_GLOBALIZE_LABEL (asm_out_file, fnname);  /* Do any machine/system dependent processing of the function name */#ifdef ASM_DECLARE_FUNCTION_NAME  ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);#else  /* Standard thing is just output label for the function.  */  ASM_OUTPUT_LABEL (asm_out_file, fnname);#endif /* ASM_DECLARE_FUNCTION_NAME */}/* Assemble " .int 0\n" or whatever this assembler wants.  */voidassemble_integer_zero (){  ASM_OUTPUT_INT (asm_out_file, const0_rtx);}/* Assemble a string constant with the specified C string as contents.  */voidassemble_string (p, size)     unsigned char *p;     int size;{  register int i;  int excess = 0;  int pos = 0;  int maximum = 2000;  /* If the string is very long, split it up.  */  while (pos < size)    {      int thissize = size - pos;      if (thissize > maximum)	thissize = maximum;#ifdef ASM_OUTPUT_ASCII      ASM_OUTPUT_ASCII (asm_out_file, p, thissize);#else      fprintf (asm_out_file, "\t.ascii \"");      for (i = 0; i < thissize; i++)	{	  register int c = p[i];	  if (c == '\"' || c == '\\')	    putc ('\\', asm_out_file);	  if (c >= ' ' && c < 0177)	    putc (c, asm_out_file);	  else	    {	      fprintf (asm_out_file, "\\%o", c);	      /* After an octal-escape, if a digit follows,		 terminate one string constant and start another.		 The Vax assembler fails to stop reading the escape		 after three digits, so this is the only way we		 can get it to parse the data properly.  */	      if (i < thissize - 1		  && p[i + 1] >= '0' && p[i + 1] <= '9')		fprintf (asm_out_file, "\"\n\t.ascii \"");	    }	}      fprintf (asm_out_file, "\"\n");#endif /* no ASM_OUTPUT_ASCII */      pos += thissize;      p += thissize;    }}/* Assemble everything that is needed for a variable or function declaration.   Not used for automatic variables, and not used for function definitions.   Should not be called for variables of incomplete structure type.   TOP_LEVEL is nonzero if this variable has file scope.   WRITE_SYMBOLS is DBX_DEBUG if writing dbx symbol output.   The dbx data for a file-scope variable is written here.   AT_END is nonzero if this is the special handling, at end of compilation,   to define things that have had only tentative definitions.  */voidassemble_variable (decl, top_level, write_symbols, at_end)     tree decl;     int top_level;     enum debugger write_symbols;     int at_end;{  register char *name;  register int i;  /* Do nothing for global register variables.  */  if (GET_CODE (DECL_RTL (decl)) == REG)    return;  /* Normally no need to say anything for external references,     since assembler considers all undefined symbols external.  */  if (TREE_EXTERNAL (decl))    return;  /* Output no assembler code for a function declaration.     Only definitions of functions output anything.  */  if (TREE_CODE (decl) == FUNCTION_DECL)    return;  /* If type was incomplete when the variable was declared,     see if it is complete now.  */  if (DECL_SIZE (decl) == 0)    layout_decl (decl, 0);  /* Still incomplete => don't allocate it; treat the tentative defn     (which is what it must have been) as an `extern' reference.  */  if (DECL_SIZE (decl) == 0)    {      error_with_file_and_line (DECL_SOURCE_FILE (decl),				DECL_SOURCE_LINE (decl),				"storage size of static var `%s' isn't known",				IDENTIFIER_POINTER (DECL_NAME (decl)));      return;    }  /* The first declaration of a variable that comes through this function     decides whether it is global (in C, has external linkage)     or local (in C, has internal linkage).  So do nothing more     if this function has already run.  */  if (TREE_ASM_WRITTEN (decl))    return;  TREE_ASM_WRITTEN (decl) = 1;#ifdef DBX_DEBUGGING_INFO  /* File-scope global variables are output here.  */  if (write_symbols == DBX_DEBUG && top_level)    dbxout_symbol (decl, 0);#endif#ifdef SDB_DEBUGGING_INFO  if (write_symbols == SDB_DEBUG && top_level)    sdbout_symbol (decl, 0);#endif  if (write_symbols == GDB_DEBUG)    /* Make sure the file is known to GDB even if it has no functions.  */    set_current_gdbfile (DECL_SOURCE_FILE (decl));  /* If storage size is erroneously variable, just continue.     Error message was already made.  */  if (! TREE_LITERAL (DECL_SIZE (decl)))    return;  app_disable ();  name = XSTR (XEXP (DECL_RTL (decl), 0), 0);  /* Handle uninitialized definitions.  */  if (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)    {      int size, rounded;      if (DECL_SIZE_UNIT (decl) % BITS_PER_UNIT == 0)	size = (TREE_INT_CST_LOW (DECL_SIZE (decl))		* (DECL_SIZE_UNIT (decl) / BITS_PER_UNIT));      else	size = (TREE_INT_CST_LOW (DECL_SIZE (decl))		* DECL_SIZE_UNIT (decl)		/ BITS_PER_UNIT);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -