varasm.c

来自「GCC编译器源代码」· C语言 代码 · 共 2,382 行 · 第 1/5 页

C
2,382
字号
/* Output variables, constants and external declarations, for GNU compiler.   Copyright (C) 1987, 88, 89, 92-6, 1997 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 2, 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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, 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 "config.h"#include <stdio.h>#include <setjmp.h>/* #include <stab.h> */#include "rtl.h"#include "tree.h"#include "flags.h"#include "except.h"#include "function.h"#include "expr.h"#include "output.h"#include "hard-reg-set.h"#include "regs.h"#include "defaults.h"#include "real.h"#include "bytecode.h"#include "obstack.h"#include "c-pragma.h"#ifdef XCOFF_DEBUGGING_INFO#include "xcoffout.h"#endif#include <ctype.h>#ifndef TRAMPOLINE_ALIGNMENT#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY#endif#ifndef ASM_STABS_OP#define ASM_STABS_OP ".stabs"#endif/* Define the prefix to use when check_memory_usage_flag is enable.  */#ifdef NO_DOLLAR_IN_LABEL#ifdef NO_DOT_IN_LABEL#define CHKR_PREFIX "chkr_prefix_"#else /* !NO_DOT_IN_LABEL */#define CHKR_PREFIX "chkr."#endif #else /* !NO_DOLLAR_IN_LABEL */#define CHKR_PREFIX "chkr$"#endif#define CHKR_PREFIX_SIZE (sizeof (CHKR_PREFIX) - 1)/* This macro gets just the user-specified name   out of the string in a SYMBOL_REF.  On most machines,   we discard the * if any and that's all.  */#ifndef STRIP_NAME_ENCODING#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \  (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))#endif/* File in which assembler code is being written.  */extern FILE *asm_out_file;/* The (assembler) name of the first globally-visible object output.  */char *first_global_object_name;extern struct obstack *current_obstack;extern struct obstack *saveable_obstack;extern struct obstack *rtl_obstack;extern struct obstack permanent_obstack;#define obstack_chunk_alloc 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;/* Carry information from ASM_DECLARE_OBJECT_NAME   to ASM_FINISH_DECLARE_OBJECT.  */int size_directive_output;/* The last decl for which assemble_variable was called,   if it did ASM_DECLARE_OBJECT_NAME.   If the last call to assemble_variable didn't do that,   this holds 0.  */tree last_assemble_variable_decl;#ifdef HANDLE_PRAGMA_WEAK/* Any weak symbol declarations waiting to be emitted.  */struct weak_syms{  struct weak_syms *next;  char *name;  char *value;};static struct weak_syms *weak_decls;#endif/* Nonzero if at least one function definition has been seen.  */static int function_defined;struct addr_const;struct constant_descriptor;struct rtx_const;struct pool_constant;static void bc_make_decl_rtl		PROTO((tree, char *, int));static char *strip_reg_name		PROTO((char *));static void bc_output_ascii		PROTO((FILE *, char *, int));static int contains_pointers_p		PROTO((tree));static void decode_addr_const		PROTO((tree, struct addr_const *));static int const_hash			PROTO((tree));static int compare_constant		PROTO((tree,					       struct constant_descriptor *));static char *compare_constant_1		PROTO((tree, char *));static struct constant_descriptor *record_constant PROTO((tree));static void record_constant_1		PROTO((tree));static tree copy_constant		PROTO((tree));static void output_constant_def_contents  PROTO((tree, int, int));static void decode_rtx_const		PROTO((enum machine_mode, rtx,					       struct rtx_const *));static int const_hash_rtx		PROTO((enum machine_mode, rtx));static int compare_constant_rtx		PROTO((enum machine_mode, rtx,					       struct constant_descriptor *));static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,							      rtx));static struct pool_constant *find_pool_constant PROTO((rtx));static void mark_constant_pool		PROTO((void));static void mark_constants		PROTO((rtx));static int output_addressed_constants	PROTO((tree));static void output_after_function_constants PROTO((void));static void bc_assemble_integer		PROTO((tree, int));static void output_constructor		PROTO((tree, int));static enum in_section { no_section, in_text, in_data, in_named#ifdef BSS_SECTION_ASM_OP  , in_bss#endif#ifdef EH_FRAME_SECTION_ASM_OP  , in_eh_frame#endif#ifdef EXTRA_SECTIONS  , EXTRA_SECTIONS#endif} in_section = no_section;/* Return a non-zero value if DECL has a section attribute.  */#define IN_NAMED_SECTION(DECL) \  ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \   && DECL_SECTION_NAME (DECL) != NULL_TREE)/* Text of section name when in_section == in_named.  */static char *in_named_name;/* 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)    {      if (output_bytecode)	bc_text ();      else	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 (output_bytecode)	bc_data ();      else	{	  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;    }}/* Tell assembler to switch to read-only data section.  This is normally   the text section.  */voidreadonly_data_section (){#ifdef READONLY_DATA_SECTION  READONLY_DATA_SECTION ();  /* Note this can call data_section.  */#else  text_section ();#endif}/* Determine if we're in the text section.  */intin_text_section (){  return in_section == in_text;}/* Determine if we're in the data section.  */intin_data_section (){  return in_section == in_data;}/* Tell assembler to change to section NAME for DECL.   If DECL is NULL, just switch to section NAME.   If NAME is NULL, get the name from DECL.   If RELOC is 1, the initializer for DECL contains relocs.  */voidnamed_section (decl, name, reloc)     tree decl;     char *name;     int reloc;{  if (decl != NULL_TREE      && TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')    abort ();  if (name == NULL)    name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));  if (in_section != in_named || strcmp (name, in_named_name))    {#ifdef ASM_OUTPUT_SECTION_NAME      ASM_OUTPUT_SECTION_NAME (asm_out_file, decl, name, reloc);#else      /* Section attributes are not supported if this macro isn't provided -	 some host formats don't support them at all.  The front-end should	 already have flagged this as an error.  */      abort ();#endif      in_named_name = obstack_alloc (&permanent_obstack, strlen (name) + 1);      strcpy (in_named_name, name);      in_section = in_named;    }}#ifdef ASM_OUTPUT_SECTION_NAME#ifndef UNIQUE_SECTION#define UNIQUE_SECTION(DECL,RELOC)				\do {								\  int len;							\  char *name, *string;						\								\  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL));	\  /* Strip off any encoding in name.  */			\  STRIP_NAME_ENCODING (name, name);				\								\  len = strlen (name) + 1;					\  string = alloca (len + 1);					\  sprintf (string, ".%s", name);				\								\  DECL_SECTION_NAME (DECL) = build_string (len, string);	\} while (0)#endif#ifndef UNIQUE_SECTION_P#define UNIQUE_SECTION_P(DECL) 0#endif#endif#ifdef BSS_SECTION_ASM_OP/* Tell the assembler to switch to the bss section.  */voidbss_section (){  if (in_section != in_bss)    {      if (output_bytecode)	bc_data ();      else	{#ifdef SHARED_BSS_SECTION_ASM_OP	  if (flag_shared_data)	    fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP);	  else#endif	    fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP);	}      in_section = in_bss;    }}#ifdef ASM_OUTPUT_BSS/* Utility function for ASM_OUTPUT_BSS for targets to use if   they don't support alignments in .bss.   ??? It is believed that this function will work in most cases so such   support is localized here.  */static voidasm_output_bss (file, decl, name, size, rounded)     FILE *file;     tree decl;     char *name;     int size, rounded;{  ASM_GLOBALIZE_LABEL (file, name);  bss_section ();#ifdef ASM_DECLARE_OBJECT_NAME  last_assemble_variable_decl = decl;  ASM_DECLARE_OBJECT_NAME (file, name, decl);#else  /* Standard thing is just output label for the object.  */  ASM_OUTPUT_LABEL (file, name);#endif /* ASM_DECLARE_OBJECT_NAME */  ASM_OUTPUT_SKIP (file, rounded);}#endif#ifdef ASM_OUTPUT_ALIGNED_BSS/* Utility function for targets to use in implementing   ASM_OUTPUT_ALIGNED_BSS.   ??? It is believed that this function will work in most cases so such   support is localized here.  */static voidasm_output_aligned_bss (file, decl, name, size, align)     FILE *file;     tree decl;     char *name;     int size, align;{  ASM_GLOBALIZE_LABEL (file, name);  bss_section ();  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));#ifdef ASM_DECLARE_OBJECT_NAME  last_assemble_variable_decl = decl;  ASM_DECLARE_OBJECT_NAME (file, name, decl);#else  /* Standard thing is just output label for the object.  */  ASM_OUTPUT_LABEL (file, name);#endif /* ASM_DECLARE_OBJECT_NAME */  ASM_OUTPUT_SKIP (file, size ? size : 1);}#endif#endif /* BSS_SECTION_ASM_OP */#ifdef EH_FRAME_SECTION_ASM_OPvoideh_frame_section (){  if (in_section != in_eh_frame)    {      fprintf (asm_out_file, "%s\n", EH_FRAME_SECTION_ASM_OP);      in_section = in_eh_frame;    }} #endif/* Switch to the section for function DECL.   If DECL is NULL_TREE, switch to the text section.   ??? It's not clear that we will ever be passed NULL_TREE, but it's   safer to handle it.  */voidfunction_section (decl)     tree decl;{  if (decl != NULL_TREE      && DECL_SECTION_NAME (decl) != NULL_TREE)    named_section (decl, (char *) 0, 0);  else    text_section ();}/* Switch to section for variable DECL.   RELOC is the `reloc' argument to SELECT_SECTION.  */voidvariable_section (decl, reloc)     tree decl;     int reloc;{  if (IN_NAMED_SECTION (decl))    named_section (decl, NULL, reloc);  else    {      /* C++ can have const variables that get initialized from constructors,	 and thus can not be in a readonly section.  We prevent this by	 verifying that the initial value is constant for objects put in a	 readonly section.	 error_mark_node is used by the C front end to indicate that the	 initializer has not been seen yet.  In this case, we assume that	 the initializer must be constant.	 C++ uses error_mark_node for variables that have complicated	 initializers, but these variables go in BSS so we won't be called	 for them.  */#ifdef SELECT_SECTION      SELECT_SECTION (decl, reloc);#else      if (DECL_READONLY_SECTION (decl, reloc))	readonly_data_section ();      else	data_section ();#endif    }}/* Tell assembler to switch to the section for the exception handling   table.  */voidexception_section ()

⌨️ 快捷键说明

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