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

📄 function.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Expands front end tree to back end RTL for GNU C-Compiler   Copyright (C) 1987, 1988, 1989, 1991, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* This file handles the generation of rtl code from tree structure   at the level of the function as a whole.   It creates the rtl expressions for parameters and auto variables   and has full responsibility for allocating stack slots.   `expand_function_start' is called at the beginning of a function,   before the function body is parsed, and `expand_function_end' is   called after parsing the body.   Call `assign_stack_local' to allocate a stack slot for a local variable.   This is usually done during the RTL generation for the function body,   but it can also be done in the reload pass when a pseudo-register does   not get a hard register.   Call `put_var_into_stack' when you learn, belatedly, that a variable   previously given a pseudo-register must in fact go in the stack.   This function changes the DECL_RTL to be a stack slot instead of a reg   then scans all the RTL instructions so far generated to correct them.  */#include "config.h"#include <stdio.h>#include "rtl.h"#include "tree.h"#include "flags.h"#include "function.h"#include "insn-flags.h"#include "expr.h"#include "insn-codes.h"#include "regs.h"#include "hard-reg-set.h"#include "insn-config.h"#include "recog.h"#include "output.h"#include "basic-block.h"/* Round a value to the lowest integer less than it that is a multiple of   the required alignment.  Avoid using division in case the value is   negative.  Assume the alignment is a power of two.  */#define FLOOR_ROUND(VALUE,ALIGN) ((VALUE) & ~((ALIGN) - 1))/* Similar, but round to the next highest integer that meets the   alignment.  */#define CEIL_ROUND(VALUE,ALIGN)	(((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))/* NEED_SEPARATE_AP means that we cannot derive ap from the value of fp   during rtl generation.  If they are different register numbers, this is   always true.  It may also be true if   FIRST_PARM_OFFSET - STARTING_FRAME_OFFSET is not a constant during rtl   generation.  See fix_lexical_addr for details.  */#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM#define NEED_SEPARATE_AP#endif/* Number of bytes of args popped by function being compiled on its return.   Zero if no bytes are to be popped.   May affect compilation of return insn or of function epilogue.  */int current_function_pops_args;/* Nonzero if function being compiled needs to be given an address   where the value should be stored.  */int current_function_returns_struct;/* Nonzero if function being compiled needs to   return the address of where it has put a structure value.  */int current_function_returns_pcc_struct;/* Nonzero if function being compiled needs to be passed a static chain.  */int current_function_needs_context;/* Nonzero if function being compiled can call setjmp.  */int current_function_calls_setjmp;/* Nonzero if function being compiled can call longjmp.  */int current_function_calls_longjmp;/* Nonzero if function being compiled receives nonlocal gotos   from nested functions.  */int current_function_has_nonlocal_label;/* Nonzero if function being compiled contains nested functions.  */int current_function_contains_functions;/* Nonzero if function being compiled can call alloca,   either as a subroutine or builtin.  */int current_function_calls_alloca;/* Nonzero if the current function returns a pointer type */int current_function_returns_pointer;/* If some insns can be deferred to the delay slots of the epilogue, the   delay list for them is recorded here.  */rtx current_function_epilogue_delay_list;/* If function's args have a fixed size, this is that size, in bytes.   Otherwise, it is -1.   May affect compilation of return insn or of function epilogue.  */int current_function_args_size;/* # bytes the prologue should push and pretend that the caller pushed them.   The prologue must do this, but only if parms can be passed in registers.  */int current_function_pretend_args_size;/* # of bytes of outgoing arguments required to be pushed by the prologue.   If this is non-zero, it means that ACCUMULATE_OUTGOING_ARGS was defined   and no stack adjusts will be done on function calls.  */int current_function_outgoing_args_size;/* This is the offset from the arg pointer to the place where the first   anonymous arg can be found, if there is one.  */rtx current_function_arg_offset_rtx;/* Nonzero if current function uses varargs.h or equivalent.   Zero for functions that use stdarg.h.  */int current_function_varargs;/* Quantities of various kinds of registers   used for the current function's args.  */CUMULATIVE_ARGS current_function_args_info;/* Name of function now being compiled.  */char *current_function_name;/* If non-zero, an RTL expression for that location at which the current   function returns its result.  Always equal to   DECL_RTL (DECL_RESULT (current_function_decl)), but provided   independently of the tree structures.  */rtx current_function_return_rtx;/* Nonzero if the current function uses the constant pool.  */int current_function_uses_const_pool;/* Nonzero if the current function uses pic_offset_table_rtx.  */int current_function_uses_pic_offset_table;/* The arg pointer hard register, or the pseudo into which it was copied.  */rtx current_function_internal_arg_pointer;/* The FUNCTION_DECL for an inline function currently being expanded.  */tree inline_function_decl;/* Number of function calls seen so far in current function.  */int function_call_count;/* List (chain of TREE_LIST) of LABEL_DECLs for all nonlocal labels   (labels to which there can be nonlocal gotos from nested functions)   in this function.  */tree nonlocal_labels;/* RTX for stack slot that holds the current handler for nonlocal gotos.   Zero when function does not have nonlocal labels.  */rtx nonlocal_goto_handler_slot;/* RTX for stack slot that holds the stack pointer value to restore   for a nonlocal goto.   Zero when function does not have nonlocal labels.  */rtx nonlocal_goto_stack_level;/* Label that will go on parm cleanup code, if any.   Jumping to this label runs cleanup code for parameters, if   such code must be run.  Following this code is the logical return label.  */rtx cleanup_label;/* Label that will go on function epilogue.   Jumping to this label serves as a "return" instruction   on machines which require execution of the epilogue on all returns.  */rtx return_label;/* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.   So we can mark them all live at the end of the function, if nonopt.  */rtx save_expr_regs;/* List (chain of EXPR_LISTs) of all stack slots in this function.   Made for the sake of unshare_all_rtl.  */rtx stack_slot_list;/* Chain of all RTL_EXPRs that have insns in them.  */tree rtl_expr_chain;/* Label to jump back to for tail recursion, or 0 if we have   not yet needed one for this function.  */rtx tail_recursion_label;/* Place after which to insert the tail_recursion_label if we need one.  */rtx tail_recursion_reentry;/* Location at which to save the argument pointer if it will need to be   referenced.  There are two cases where this is done: if nonlocal gotos   exist, or if vars stored at an offset from the argument pointer will be   needed by inner routines.  */rtx arg_pointer_save_area;/* Offset to end of allocated area of stack frame.   If stack grows down, this is the address of the last stack slot allocated.   If stack grows up, this is the address for the next slot.  */int frame_offset;/* List (chain of TREE_LISTs) of static chains for containing functions.   Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx   in an RTL_EXPR in the TREE_VALUE.  */static tree context_display;/* List (chain of TREE_LISTs) of trampolines for nested functions.   The trampoline sets up the static chain and jumps to the function.   We supply the trampoline's address when the function's address is requested.   Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx   in an RTL_EXPR in the TREE_VALUE.  */static tree trampoline_list;/* Insn after which register parms and SAVE_EXPRs are born, if nonopt.  */static rtx parm_birth_insn;#if 0/* Nonzero if a stack slot has been generated whose address is not   actually valid.  It means that the generated rtl must all be scanned   to detect and correct the invalid addresses where they occur.  */static int invalid_stack_slot;#endif/* Last insn of those whose job was to put parms into their nominal homes.  */static rtx last_parm_insn;/* 1 + last pseudo register number used for loading a copy   of a parameter of this function.  */static int max_parm_reg;/* Vector indexed by REGNO, containing location on stack in which   to put the parm which is nominally in pseudo register REGNO,   if we discover that that parm must go in the stack.  */static rtx *parm_reg_stack_loc;#if 0  /* Turned off because 0 seems to work just as well.  *//* Cleanup lists are required for binding levels regardless of whether   that binding level has cleanups or not.  This node serves as the   cleanup list whenever an empty list is required.  */static tree empty_cleanup_list;#endif/* Nonzero once virtual register instantiation has been done.   assign_stack_local uses frame_pointer_rtx when this is nonzero.  */static int virtuals_instantiated;/* Nonzero if we need to distinguish between the return value of this function   and the return value of a function called by this function.  This helps   integrate.c  */extern int rtx_equal_function_value_matters;void fixup_gotos ();static tree round_down ();static rtx round_trampoline_addr ();static rtx fixup_stack_1 ();static void fixup_var_refs ();static void fixup_var_refs_insns ();static void fixup_var_refs_1 ();static void optimize_bit_field ();static void instantiate_decls ();static void instantiate_decls_1 ();static void instantiate_decl ();static int instantiate_virtual_regs_1 ();static rtx fixup_memory_subreg ();static rtx walk_fixup_memory_subreg ();/* In order to evaluate some expressions, such as function calls returning   structures in memory, we need to temporarily allocate stack locations.   We record each allocated temporary in the following structure.   Associated with each temporary slot is a nesting level.  When we pop up   one level, all temporaries associated with the previous level are freed.   Normally, all temporaries are freed after the execution of the statement   in which they were created.  However, if we are inside a ({...}) grouping,   the result may be in a temporary and hence must be preserved.  If the   result could be in a temporary, we preserve it if we can determine which   one it is in.  If we cannot determine which temporary may contain the   result, all temporaries are preserved.  A temporary is preserved by   pretending it was allocated at the previous nesting level.   Automatic variables are also assigned temporary slots, at the nesting   level where they are defined.  They are marked a "kept" so that   free_temp_slots will not free them.  */struct temp_slot{  /* Points to next temporary slot.  */  struct temp_slot *next;  /* The rtx to used to reference the slot. */  rtx slot;  /* The size, in units, of the slot.  */  int size;  /* Non-zero if this temporary is currently in use.  */  char in_use;  /* Nesting level at which this slot is being used.  */  int level;  /* Non-zero if this should survive a call to free_temp_slots.  */  int keep;};/* List of all temporaries allocated, both available and in use.  */struct temp_slot *temp_slots;/* Current nesting level for temporaries.  */int temp_slot_level;/* Pointer to chain of `struct function' for containing functions.  */struct function *outer_function_chain;/* Given a function decl for a containing function,   return the `struct function' for it.  */struct function *find_function_data (decl)     tree decl;{  struct function *p;  for (p = outer_function_chain; p; p = p->next)    if (p->decl == decl)      return p;  abort ();}/* Save the current context for compilation of a nested function.   This is called from language-specific code.   The caller is responsible for saving any language-specific status,   since this function knows only about language-independent variables.  */voidpush_function_context (){  struct function *p = (struct function *) xmalloc (sizeof (struct function));  p->next = outer_function_chain;  outer_function_chain = p;  p->name = current_function_name;  p->decl = current_function_decl;  p->pops_args = current_function_pops_args;  p->returns_struct = current_function_returns_struct;  p->returns_pcc_struct = current_function_returns_pcc_struct;  p->needs_context = current_function_needs_context;  p->calls_setjmp = current_function_calls_setjmp;  p->calls_longjmp = current_function_calls_longjmp;  p->calls_alloca = current_function_calls_alloca;  p->has_nonlocal_label = current_function_has_nonlocal_label;  p->args_size = current_function_args_size;  p->pretend_args_size = current_function_pretend_args_size;  p->arg_offset_rtx = current_function_arg_offset_rtx;  p->uses_const_pool = current_function_uses_const_pool;  p->uses_pic_offset_table = current_function_uses_pic_offset_table;  p->internal_arg_pointer = current_function_internal_arg_pointer;  p->max_parm_reg = max_parm_reg;  p->parm_reg_stack_loc = parm_reg_stack_loc;  p->outgoing_args_size = current_function_outgoing_args_size;  p->return_rtx = current_function_return_rtx;  p->nonlocal_goto_handler_slot = nonlocal_goto_handler_slot;  p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;  p->nonlocal_labels = nonlocal_labels;

⌨️ 快捷键说明

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