📄 f95-lang.c
字号:
/* gfortran backend interface Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Paul Brook.This 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. *//* f95-lang.c-- GCC backend interface stuff *//* declare required prototypes: */#include "config.h"#include "system.h"#include "ansidecl.h"#include "system.h"#include "coretypes.h"#include "tree.h"#include "tree-gimple.h"#include "flags.h"#include "langhooks.h"#include "langhooks-def.h"#include "timevar.h"#include "tm.h"#include "function.h"#include "ggc.h"#include "toplev.h"#include "target.h"#include "debug.h"#include "diagnostic.h"#include "tree-dump.h"#include "cgraph.h"#include "gfortran.h"#include "trans.h"#include "trans-types.h"#include "trans-const.h"/* Language-dependent contents of an identifier. */struct lang_identifierGTY(()){ struct tree_identifier common;};/* The resulting tree type. */union lang_tree_nodeGTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)"))){ union tree_node GTY((tag ("0"), desc ("tree_node_structure (&%h)"))) generic; struct lang_identifier GTY((tag ("1"))) identifier;};/* Save and restore the variables in this file and elsewhere that keep track of the progress of compilation of the current function. Used for nested functions. */struct language_functionGTY(()){ /* struct gfc_language_function base; */ struct binding_level *binding_level;};/* We don't have a lex/yacc lexer/parser, but toplev expects these to exist anyway. */void yyerror (const char *str);int yylex (void);static void gfc_init_decl_processing (void);static void gfc_init_builtin_functions (void);/* Each front end provides its own. */static bool gfc_init (void);static void gfc_finish (void);static void gfc_print_identifier (FILE *, tree, int);static bool gfc_mark_addressable (tree);void do_function_end (void);int global_bindings_p (void);void insert_block (tree);static void gfc_clear_binding_stack (void);static void gfc_be_parse_file (int);static void gfc_expand_function (tree);#undef LANG_HOOKS_NAME#undef LANG_HOOKS_INIT#undef LANG_HOOKS_FINISH#undef LANG_HOOKS_INIT_OPTIONS#undef LANG_HOOKS_HANDLE_OPTION#undef LANG_HOOKS_POST_OPTIONS#undef LANG_HOOKS_PRINT_IDENTIFIER#undef LANG_HOOKS_PARSE_FILE#undef LANG_HOOKS_MARK_ADDRESSABLE#undef LANG_HOOKS_TYPE_FOR_MODE#undef LANG_HOOKS_TYPE_FOR_SIZE#undef LANG_HOOKS_UNSIGNED_TYPE#undef LANG_HOOKS_SIGNED_TYPE#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION#undef LANG_HOOKS_CLEAR_BINDING_STACK/* Define lang hooks. */#define LANG_HOOKS_NAME "GNU F95"#define LANG_HOOKS_INIT gfc_init#define LANG_HOOKS_FINISH gfc_finish#define LANG_HOOKS_INIT_OPTIONS gfc_init_options#define LANG_HOOKS_HANDLE_OPTION gfc_handle_option#define LANG_HOOKS_POST_OPTIONS gfc_post_options#define LANG_HOOKS_PRINT_IDENTIFIER gfc_print_identifier#define LANG_HOOKS_PARSE_FILE gfc_be_parse_file#define LANG_HOOKS_MARK_ADDRESSABLE gfc_mark_addressable#define LANG_HOOKS_TYPE_FOR_MODE gfc_type_for_mode#define LANG_HOOKS_TYPE_FOR_SIZE gfc_type_for_size#define LANG_HOOKS_UNSIGNED_TYPE gfc_unsigned_type#define LANG_HOOKS_SIGNED_TYPE gfc_signed_type#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE gfc_signed_or_unsigned_type#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION gfc_expand_function#define LANG_HOOKS_CLEAR_BINDING_STACK gfc_clear_binding_stackconst struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function that have names. Here so we can clear out their names' definitions at the end of the function. *//* Tree code classes. */#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,const enum tree_code_class tree_code_type[] = {#include "tree.def"};#undef DEFTREECODE/* Table indexed by tree code giving number of expression operands beyond the fixed part of the node structure. Not used for types or decls. */#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,const unsigned char tree_code_length[] = {#include "tree.def"};#undef DEFTREECODE/* Names of tree components. Used for printing out the tree and error messages. */#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,const char *const tree_code_name[] = {#include "tree.def"};#undef DEFTREECODE#define NULL_BINDING_LEVEL (struct binding_level *) NULL/* A chain of binding_level structures awaiting reuse. */static GTY(()) struct binding_level *free_binding_level;/* The elements of `ridpointers' are identifier nodes for the reserved type names and storage classes. It is indexed by a RID_... value. */tree *ridpointers = NULL;/* language-specific flags. */static voidgfc_expand_function (tree fndecl){ tree t; if (DECL_INITIAL (fndecl) && BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))) { /* Local static equivalenced variables are never seen by check_global_declarations, so we need to output debug info by hand. */ t = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)); for (t = BLOCK_VARS (t); t; t = TREE_CHAIN (t)) if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t) && TREE_STATIC (t)) { tree expr = DECL_VALUE_EXPR (t); if (TREE_CODE (expr) == COMPONENT_REF && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == UNION_TYPE && cgraph_varpool_node (TREE_OPERAND (expr, 0))->needed && errorcount == 0 && sorrycount == 0) { timevar_push (TV_SYMOUT); (*debug_hooks->global_decl) (t); timevar_pop (TV_SYMOUT); } } } tree_rest_of_compilation (fndecl);}/* Prepare expr to be an argument of a TRUTH_NOT_EXPR, or validate its data type for an `if' or `while' statement or ?..: exp. This preparation consists of taking the ordinary representation of an expression expr and producing a valid tree boolean expression describing whether expr is nonzero. We could simply always do build_binary_op (NE_EXPR, expr, boolean_false_node, 1), but we optimize comparisons, &&, ||, and !. The resulting type should always be `boolean_type_node'. This is much simpler than the corresponding C version because we have a distinct boolean type. */treegfc_truthvalue_conversion (tree expr){ switch (TREE_CODE (TREE_TYPE (expr))) { case BOOLEAN_TYPE: if (TREE_TYPE (expr) == boolean_type_node) return expr; else if (COMPARISON_CLASS_P (expr)) { TREE_TYPE (expr) = boolean_type_node; return expr; } else if (TREE_CODE (expr) == NOP_EXPR) return build1 (NOP_EXPR, boolean_type_node, TREE_OPERAND (expr, 0)); else return build1 (NOP_EXPR, boolean_type_node, expr); case INTEGER_TYPE: if (TREE_CODE (expr) == INTEGER_CST) return integer_zerop (expr) ? boolean_false_node : boolean_true_node; else return build2 (NE_EXPR, boolean_type_node, expr, integer_zero_node); default: internal_error ("Unexpected type in truthvalue_conversion"); }}static voidgfc_create_decls (void){ /* GCC builtins. */ gfc_init_builtin_functions (); /* Runtime/IO library functions. */ gfc_build_builtin_function_decls (); gfc_init_constants ();}static voidgfc_be_parse_file (int set_yydebug ATTRIBUTE_UNUSED){ int errors; int warnings; gfc_create_decls (); gfc_parse_file (); gfc_generate_constructors (); cgraph_finalize_compilation_unit (); cgraph_optimize (); /* Tell the frontent about any errors. */ gfc_get_errors (&warnings, &errors); errorcount += errors; warningcount += warnings;}/* Initialize everything. */static boolgfc_init (void){#ifdef USE_MAPPED_LOCATION linemap_add (&line_table, LC_ENTER, false, gfc_source_file, 1); linemap_add (&line_table, LC_RENAME, false, "<built-in>", 0);#endif /* First initialize the backend. */ gfc_init_decl_processing (); gfc_static_ctors = NULL_TREE; /* Then the frontend. */ gfc_init_1 (); if (gfc_new_file () != SUCCESS) fatal_error ("can't open input file: %s", gfc_source_file); return true;}static voidgfc_finish (void){ gfc_done_1 (); gfc_release_include_path (); return;}static voidgfc_print_identifier (FILE * file ATTRIBUTE_UNUSED, tree node ATTRIBUTE_UNUSED, int indent ATTRIBUTE_UNUSED){ return;}/* These functions and variables deal with binding contours. We only need these functions for the list of PARM_DECLs, but we leave the functions more general; these are a simplified version of the functions from GNAT. *//* For each binding contour we allocate a binding_level structure which records the entities defined or declared in that contour. Contours include: the global one one for each subprogram definition one for each compound statement (declare block) Binding contours are used to create GCC tree BLOCK nodes. */struct binding_levelGTY(()){ /* A chain of ..._DECL nodes for all variables, constants, functions, parameters and type declarations. These ..._DECL nodes are chained through the TREE_CHAIN field. Note that these ..._DECL nodes are stored in the reverse of the order supplied to be compatible with the back-end. */ tree names; /* For each level (except the global one), a chain of BLOCK nodes for all the levels that were entered and exited one level down from this one. */ tree blocks; /* The binding level containing this one (the enclosing binding level). */ struct binding_level *level_chain;};/* The binding level currently in effect. */static GTY(()) struct binding_level *current_binding_level = NULL;/* The outermost binding level. This binding level is created when the compiler is started and it will exist through the entire compilation. */static GTY(()) struct binding_level *global_binding_level;/* Binding level structures are initialized by copying this one. */static struct binding_level clear_binding_level = { NULL, NULL, NULL };/* Return nonzero if we are currently in the global binding level. */intglobal_bindings_p (void){ return current_binding_level == global_binding_level ? -1 : 0;}treegetdecls (void){ return current_binding_level->names;}/* Enter a new binding level. The input parameter is ignored, but has to be specified for back-end compatibility. */voidpushlevel (int ignore ATTRIBUTE_UNUSED){ struct binding_level *newlevel = (struct binding_level *) ggc_alloc (sizeof (struct binding_level)); *newlevel = clear_binding_level; /* Add this level to the front of the chain (stack) of levels that are active. */ newlevel->level_chain = current_binding_level; current_binding_level = newlevel;}/* Exit a binding level. Pop the level off, and restore the state of the identifier-decl mappings that were in effect when this level was entered. If KEEP is nonzero, this level had explicit declarations, so and create a "block" (a BLOCK node) for the level to record its declarations and subblocks for symbol table output. If FUNCTIONBODY is nonzero, this level is the body of a function, so create a block as if KEEP were set and also clear out all label names. If REVERSE is nonzero, reverse the order of decls before putting them into the BLOCK. */treepoplevel (int keep, int reverse, int functionbody){ /* Points to a BLOCK tree node. This is the BLOCK node constructed for the binding level that we are about to exit and which is returned by this routine. */ tree block_node = NULL_TREE; tree decl_chain; tree subblock_chain = current_binding_level->blocks; tree subblock_node; /* Reverse the list of XXXX_DECL nodes if desired. Note that the ..._DECL nodes chained through the `names' field of current_binding_level are in reverse order except for PARM_DECL node, which are explicitly stored in the right order. */ decl_chain = (reverse) ? nreverse (current_binding_level->names) : current_binding_level->names; /* If there were any declarations in the current binding level, or if this binding level is a function body, or if there are any nested blocks then create a BLOCK node to record them for the life of this function. */ if (keep || functionbody) block_node = build_block (keep ? decl_chain : 0, subblock_chain, 0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -