📄 trans-decl.c
字号:
/* Backend function setup Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Paul BrookThis file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING. If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA. *//* trans-decl.c -- Handling of backend function and variable decls, etc */#include "config.h"#include "system.h"#include "coretypes.h"#include "tree.h"#include "tree-dump.h"#include "tree-gimple.h"#include "ggc.h"#include "toplev.h"#include "tm.h"#include "target.h"#include "function.h"#include "flags.h"#include "cgraph.h"#include "gfortran.h"#include "trans.h"#include "trans-types.h"#include "trans-array.h"#include "trans-const.h"/* Only for gfc_trans_code. Shouldn't need to include this. */#include "trans-stmt.h"#define MAX_LABEL_VALUE 99999/* Holds the result of the function if no result variable specified. */static GTY(()) tree current_fake_result_decl;static GTY(()) tree current_function_return_label;/* Holds the variable DECLs for the current function. */static GTY(()) tree saved_function_decls = NULL_TREE;static GTY(()) tree saved_parent_function_decls = NULL_TREE;/* The namespace of the module we're currently generating. Only used while outputting decls for module variables. Do not rely on this being set. */static gfc_namespace *module_namespace;/* List of static constructor functions. */tree gfc_static_ctors;/* Function declarations for builtin library functions. */tree gfor_fndecl_internal_malloc;tree gfor_fndecl_internal_malloc64;tree gfor_fndecl_internal_realloc;tree gfor_fndecl_internal_realloc64;tree gfor_fndecl_internal_free;tree gfor_fndecl_allocate;tree gfor_fndecl_allocate64;tree gfor_fndecl_deallocate;tree gfor_fndecl_pause_numeric;tree gfor_fndecl_pause_string;tree gfor_fndecl_stop_numeric;tree gfor_fndecl_stop_string;tree gfor_fndecl_select_string;tree gfor_fndecl_runtime_error;tree gfor_fndecl_set_fpe;tree gfor_fndecl_set_std;tree gfor_fndecl_set_convert;tree gfor_fndecl_ctime;tree gfor_fndecl_fdate;tree gfor_fndecl_ttynam;tree gfor_fndecl_in_pack;tree gfor_fndecl_in_unpack;tree gfor_fndecl_associated;/* Math functions. Many other math functions are handled in trans-intrinsic.c. */gfc_powdecl_list gfor_fndecl_math_powi[4][3];tree gfor_fndecl_math_cpowf;tree gfor_fndecl_math_cpow;tree gfor_fndecl_math_cpowl10;tree gfor_fndecl_math_cpowl16;tree gfor_fndecl_math_ishftc4;tree gfor_fndecl_math_ishftc8;tree gfor_fndecl_math_ishftc16;tree gfor_fndecl_math_exponent4;tree gfor_fndecl_math_exponent8;tree gfor_fndecl_math_exponent10;tree gfor_fndecl_math_exponent16;/* String functions. */tree gfor_fndecl_copy_string;tree gfor_fndecl_compare_string;tree gfor_fndecl_concat_string;tree gfor_fndecl_string_len_trim;tree gfor_fndecl_string_index;tree gfor_fndecl_string_scan;tree gfor_fndecl_string_verify;tree gfor_fndecl_string_trim;tree gfor_fndecl_string_repeat;tree gfor_fndecl_adjustl;tree gfor_fndecl_adjustr;/* Other misc. runtime library functions. */tree gfor_fndecl_size0;tree gfor_fndecl_size1;tree gfor_fndecl_iargc;/* Intrinsic functions implemented in FORTRAN. */tree gfor_fndecl_si_kind;tree gfor_fndecl_sr_kind;static voidgfc_add_decl_to_parent_function (tree decl){ gcc_assert (decl); DECL_CONTEXT (decl) = DECL_CONTEXT (current_function_decl); DECL_NONLOCAL (decl) = 1; TREE_CHAIN (decl) = saved_parent_function_decls; saved_parent_function_decls = decl;}voidgfc_add_decl_to_function (tree decl){ gcc_assert (decl); TREE_USED (decl) = 1; DECL_CONTEXT (decl) = current_function_decl; TREE_CHAIN (decl) = saved_function_decls; saved_function_decls = decl;}/* Build a backend label declaration. Set TREE_USED for named labels. The context of the label is always the current_function_decl. All labels are marked artificial. */treegfc_build_label_decl (tree label_id){ /* 2^32 temporaries should be enough. */ static unsigned int tmp_num = 1; tree label_decl; char *label_name; if (label_id == NULL_TREE) { /* Build an internal label name. */ ASM_FORMAT_PRIVATE_NAME (label_name, "L", tmp_num++); label_id = get_identifier (label_name); } else label_name = NULL; /* Build the LABEL_DECL node. Labels have no type. */ label_decl = build_decl (LABEL_DECL, label_id, void_type_node); DECL_CONTEXT (label_decl) = current_function_decl; DECL_MODE (label_decl) = VOIDmode; /* We always define the label as used, even if the original source file never references the label. We don't want all kinds of spurious warnings for old-style Fortran code with too many labels. */ TREE_USED (label_decl) = 1; DECL_ARTIFICIAL (label_decl) = 1; return label_decl;}/* Returns the return label for the current function. */treegfc_get_return_label (void){ char name[GFC_MAX_SYMBOL_LEN + 10]; if (current_function_return_label) return current_function_return_label; sprintf (name, "__return_%s", IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); current_function_return_label = gfc_build_label_decl (get_identifier (name)); DECL_ARTIFICIAL (current_function_return_label) = 1; return current_function_return_label;}/* Set the backend source location of a decl. */voidgfc_set_decl_location (tree decl, locus * loc){#ifdef USE_MAPPED_LOCATION DECL_SOURCE_LOCATION (decl) = loc->lb->location;#else DECL_SOURCE_LINE (decl) = loc->lb->linenum; DECL_SOURCE_FILE (decl) = loc->lb->file->filename;#endif}/* Return the backend label declaration for a given label structure, or create it if it doesn't exist yet. */treegfc_get_label_decl (gfc_st_label * lp){ if (lp->backend_decl) return lp->backend_decl; else { char label_name[GFC_MAX_SYMBOL_LEN + 1]; tree label_decl; /* Validate the label declaration from the front end. */ gcc_assert (lp != NULL && lp->value <= MAX_LABEL_VALUE); /* Build a mangled name for the label. */ sprintf (label_name, "__label_%.6d", lp->value); /* Build the LABEL_DECL node. */ label_decl = gfc_build_label_decl (get_identifier (label_name)); /* Tell the debugger where the label came from. */ if (lp->value <= MAX_LABEL_VALUE) /* An internal label. */ gfc_set_decl_location (label_decl, &lp->where); else DECL_ARTIFICIAL (label_decl) = 1; /* Store the label in the label list and return the LABEL_DECL. */ lp->backend_decl = label_decl; return label_decl; }}/* Convert a gfc_symbol to an identifier of the same name. */static treegfc_sym_identifier (gfc_symbol * sym){ return (get_identifier (sym->name));}/* Construct mangled name from symbol name. */static treegfc_sym_mangled_identifier (gfc_symbol * sym){ char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1]; if (sym->module == NULL) return gfc_sym_identifier (sym); else { snprintf (name, sizeof name, "__%s__%s", sym->module, sym->name); return get_identifier (name); }}/* Construct mangled function name from symbol name. */static treegfc_sym_mangled_function_id (gfc_symbol * sym){ int has_underscore; char name[GFC_MAX_MANGLED_SYMBOL_LEN + 1]; if (sym->module == NULL || sym->attr.proc == PROC_EXTERNAL || (sym->module != NULL && sym->attr.if_source == IFSRC_IFBODY)) { if (strcmp (sym->name, "MAIN__") == 0 || sym->attr.proc == PROC_INTRINSIC) return get_identifier (sym->name); if (gfc_option.flag_underscoring) { has_underscore = strchr (sym->name, '_') != 0; if (gfc_option.flag_second_underscore && has_underscore) snprintf (name, sizeof name, "%s__", sym->name); else snprintf (name, sizeof name, "%s_", sym->name); return get_identifier (name); } else return get_identifier (sym->name); } else { snprintf (name, sizeof name, "__%s__%s", sym->module, sym->name); return get_identifier (name); }}/* Returns true if a variable of specified size should go on the stack. */intgfc_can_put_var_on_stack (tree size){ unsigned HOST_WIDE_INT low; if (!INTEGER_CST_P (size)) return 0; if (gfc_option.flag_max_stack_var_size < 0) return 1; if (TREE_INT_CST_HIGH (size) != 0) return 0; low = TREE_INT_CST_LOW (size); if (low > (unsigned HOST_WIDE_INT) gfc_option.flag_max_stack_var_size) return 0;/* TODO: Set a per-function stack size limit. */ return 1;}/* gfc_finish_cray_pointee sets DECL_VALUE_EXPR for a Cray pointee to an expression involving its corresponding pointer. There are 2 cases; one for variable size arrays, and one for everything else, because variable-sized arrays require one fewer level of indirection. */static voidgfc_finish_cray_pointee (tree decl, gfc_symbol *sym){ tree ptr_decl = gfc_get_symbol_decl (sym->cp_pointer); tree value; /* Parameters need to be dereferenced. */ if (sym->cp_pointer->attr.dummy) ptr_decl = gfc_build_indirect_ref (ptr_decl); /* Check to see if we're dealing with a variable-sized array. */ if (sym->attr.dimension && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE) { /* These decls will be dereferenced later, so we don't dereference them here. */ value = convert (TREE_TYPE (decl), ptr_decl); } else { ptr_decl = convert (build_pointer_type (TREE_TYPE (decl)), ptr_decl); value = gfc_build_indirect_ref (ptr_decl); } SET_DECL_VALUE_EXPR (decl, value); DECL_HAS_VALUE_EXPR_P (decl) = 1; /* This is a fake variable just for debugging purposes. */ TREE_ASM_WRITTEN (decl) = 1;}/* Finish processing of a declaration and install its initial value. */static voidgfc_finish_decl (tree decl, tree init){ if (TREE_CODE (decl) == PARM_DECL) gcc_assert (init == NULL_TREE); /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it overlaps DECL_ARG_TYPE. */ else if (init == NULL_TREE) gcc_assert (DECL_INITIAL (decl) == NULL_TREE); else gcc_assert (DECL_INITIAL (decl) == error_mark_node); if (init != NULL_TREE) { if (TREE_CODE (decl) != TYPE_DECL) DECL_INITIAL (decl) = init; else { /* typedef foo = bar; store the type of bar as the type of foo. */ TREE_TYPE (decl) = TREE_TYPE (init); DECL_INITIAL (decl) = init = 0; } } if (TREE_CODE (decl) == VAR_DECL) { if (DECL_SIZE (decl) == NULL_TREE && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE) layout_decl (decl, 0); /* A static variable with an incomplete type is an error if it is initialized. Also if it is not file scope. Otherwise, let it through, but if it is not `extern' then it may cause an error message later. */ /* An automatic variable with an incomplete type is an error. */ if (DECL_SIZE (decl) == NULL_TREE && (TREE_STATIC (decl) ? (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0) : !DECL_EXTERNAL (decl))) { gfc_fatal_error ("storage size not known"); } if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl)) && (DECL_SIZE (decl) != 0) && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)) { gfc_fatal_error ("storage size not constant"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -