* tree-gimple.c: Rename from tree-simple.c.
* tree-gimple.h: Rename from tree-simple.h.
* c-gimplify.c: Rename from c-simplify.c
* Makefile.in, c-decl.c, gimple-low.c, gimplify.c,
langhooks.c, tree-alias-ander.c, tree-alias-common.c,
tree-complex.c, tree-dfa.c, tree-flow.h, tree-inline.c,
tree-into-ssa.c, tree-iterator.c, tree-mudflap.c,
tree-nested.c, tree-nomudflap.c, tree-outof-ssa.c, tree-sra.c,
tree-ssa-alias.c, tree-ssa-ccp.c, tree-ssa-copyrename.c,
tree-ssa-dce.c, tree-ssa-live.c, tree-ssa-pre.c, tree-ssa.c:
Update.
cp/ChangeLog
* cp-gimplify.c: Rename from cp-simplify.c.
* Make-lang.in, optimize.c: Update.
fortran/ChangeLog
* Make-lang.in, f95-lang.c, trans-array.c, trans-decl.c,
trans-expr.c, trans-intrinsic.c, trans-io.c, trans-stmt.c,
trans.c: Rename tree-simple.[ch] to tree-gimple.[ch].
java/ChangeLog
* Make-lang.in, expr.c, java-gimplify.c: Rename
tree-simple.[ch] to tree-gimple.[ch].
From-SVN: r81829
+2004-05-13 Diego Novillo <dnovillo@redhat.com>
+
+ * tree-gimple.c: Rename from tree-simple.c.
+ * tree-gimple.h: Rename from tree-simple.h.
+ * c-gimplify.c: Rename from c-simplify.c
+ * Makefile.in, c-decl.c, gimple-low.c, gimplify.c,
+ langhooks.c, tree-alias-ander.c, tree-alias-common.c,
+ tree-complex.c, tree-dfa.c, tree-flow.h, tree-inline.c,
+ tree-into-ssa.c, tree-iterator.c, tree-mudflap.c,
+ tree-nested.c, tree-nomudflap.c, tree-outof-ssa.c, tree-sra.c,
+ tree-ssa-alias.c, tree-ssa-ccp.c, tree-ssa-copyrename.c,
+ tree-ssa-dce.c, tree-ssa-live.c, tree-ssa-pre.c, tree-ssa.c:
+ Update.
+
2004-05-14 Ranjit Mathew <rmathew@hotmail.com>
* doc/sourcebuild.texi: Mention libbanshee and libmudflap.
PREDICT_H = predict.h predict.def
CPPLIB_H = cpplib.h line-map.h
TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H)
-TREE_SIMPLE_H = tree-simple.h tree-iterator.h
+TREE_GIMPLE_H = tree-gimple.h tree-iterator.h
TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \
- bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h $(TREE_SIMPLE_H) \
+ bitmap.h $(BASIC_BLOCK_H) hard-reg-set.h $(TREE_GIMPLE_H) \
$(HASHTAB_H)
PRETTY_PRINT_H = pretty-print.h input.h $(OBSTACK_H)
DIAGNOSTIC_H = diagnostic.h diagnostic.def $(PRETTY_PRINT_H)
c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \
c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
c-objc-common.o c-dump.o c-pch.o $(C_TARGET_OBJS) \
- c-simplify.o tree-mudflap.o c-mudflap.o c-pretty-print.o
+ c-gimplify.o tree-mudflap.o c-mudflap.o c-pretty-print.o
# Language-specific object files for C.
C_OBJS = c-parse.o c-lang.o stub-objc.o $(C_AND_OBJC_OBJS)
# Language-independent object files.
OBJS-common = \
- tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-simple.o \
+ tree-cfg.o tree-dfa.o tree-eh.o tree-ssa.o tree-optimize.o tree-gimple.o \
tree-alias-type.o gimplify.o tree-pretty-print.o tree-into-ssa.o \
tree-outof-ssa.o tree-alias-common.o tree-ssa-ccp.o \
@ANDER@ tree-ssa-dce.o tree-ssa-copy.o tree-nrv.o tree-ssa-copyrename.o \
$(TREE_H) $(RTL_H) $(EXPR_H) flags.h $(PARAMS_H) input.h insn-config.h \
$(INTEGRATE_H) $(VARRAY_H) $(HASHTAB_H) $(SPLAY_TREE_H) toplev.h \
langhooks.h $(C_COMMON_H) tree-inline.h cgraph.h intl.h function.h \
- $(TREE_SIMPLE_H)
+ $(TREE_GIMPLE_H)
print-tree.o : print-tree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(GGC_H) langhooks.h real.h
stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(TREE_DUMP_H) diagnostic.h except.h tree-pass.h flags.h langhooks.h
tree-nested.o: tree-nested.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \
$(RTL_H) $(TM_P_H) function.h tree-dump.h tree-inline.h tree-iterator.h \
- tree-simple.h cgraph.h $(EXPR_H) langhooks.h $(GGC_H) gt-tree-nested.h
+ tree-gimple.h cgraph.h $(EXPR_H) langhooks.h $(GGC_H) gt-tree-nested.h
tree-iterator.o : tree-iterator.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) \
- coretypes.h $(GGC_H) tree-iterator.h tree-simple.h gt-tree-iterator.h
+ coretypes.h $(GGC_H) tree-iterator.h tree-gimple.h gt-tree-iterator.h
tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
errors.h tree-inline.h $(HASHTAB_H) flags.h function.h $(TIMEVAR_H) \
$(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) toplev.h function.h \
langhooks.h flags.h cgraph.h tree-inline.h tree-mudflap.h $(GGC_H) \
cgraph.h tree-pass.h
-c-simplify.o : c-simplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
- $(C_TREE_H) $(C_COMMON_H) diagnostic.h $(TREE_SIMPLE_H) varray.h flags.h \
+c-gimplify.o : c-gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
+ $(C_TREE_H) $(C_COMMON_H) diagnostic.h $(TREE_GIMPLE_H) varray.h flags.h \
langhooks.h toplev.h rtl.h $(TREE_FLOW_H) langhooks-def.h \
$(TM_H) coretypes.h $(C_PRETTY_PRINT_H) cgraph.h
gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
- diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
+ diagnostic.h $(TREE_GIMPLE_H) tree-inline.h varray.h langhooks.h \
langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
flags.h $(RTL_H) function.h $(EXPR_H) output.h $(GGC_H) gt-gimplify.h
gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
- diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
+ diagnostic.h $(TREE_GIMPLE_H) tree-inline.h varray.h langhooks.h \
langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
flags.h $(RTL_H) function.h tree-pass.h
tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
$(TM_H) coretypes.h
-tree-simple.o : tree-simple.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(EXPR_H) \
- $(RTL_H) $(TREE_SIMPLE_H) $(TM_H) coretypes.h bitmap.h $(GGC_H)
+tree-gimple.o : tree-gimple.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(EXPR_H) \
+ $(RTL_H) $(TREE_GIMPLE_H) $(TM_H) coretypes.h bitmap.h $(GGC_H)
tree-mudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
- $(C_TREE_H) $(C_COMMON_H) $(TREE_SIMPLE_H) diagnostic.h $(HASHTAB_H) \
+ $(C_TREE_H) $(C_COMMON_H) $(TREE_GIMPLE_H) diagnostic.h $(HASHTAB_H) \
output.h varray.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h \
$(TREE_DUMP_H) tree-pass.h
c-mudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
- $(C_TREE_H) $(C_COMMON_H) $(TREE_SIMPLE_H) diagnostic.h $(HASHTAB_H) \
+ $(C_TREE_H) $(C_COMMON_H) $(TREE_GIMPLE_H) diagnostic.h $(HASHTAB_H) \
output.h varray.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h
tree-nomudflap.o : $(CONFIG_H) errors.h $(SYSTEM_H) $(TREE_H) tree-inline.h \
- $(C_TREE_H) $(C_COMMON_H) $(TREE_SIMPLE_H) diagnostic.h $(HASHTAB_H) \
+ $(C_TREE_H) $(C_COMMON_H) $(TREE_GIMPLE_H) diagnostic.h $(HASHTAB_H) \
output.h varray.h langhooks.h tree-mudflap.h $(TM_H) coretypes.h
tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
errors.h $(TREE_H) diagnostic.h real.h $(HASHTAB_H) $(TREE_FLOW_H) \
coretypes.h $(TREE_DUMP_H) tree-pass.h flags.h
tree-ssa-ccp.o : tree-ssa-ccp.c $(CONFIG_H) system.h errors.h $(TREE_H) \
$(RTL_H) $(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
- $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SIMPLE_H) \
+ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \
$(EXPR_H) tree-pass.h flags.h langhooks.h
tree-sra.o : tree-sra.c $(CONFIG_H) system.h errors.h $(TREE_H) $(RTL_H) \
$(TM_P_H) $(TREE_FLOW_H) diagnostic.h tree-inline.h \
- $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_SIMPLE_H) \
+ $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \
langhooks.h tree-pass.h flags.h
tree-complex.o : tree-complex.c $(CONFIG_H) system.h $(TREE_H) \
- $(TM_H) $(TREE_FLOW_H) $(TREE_SIMPLE_H) tree-iterator.h tree-pass.h \
+ $(TM_H) $(TREE_FLOW_H) $(TREE_GIMPLE_H) tree-iterator.h tree-pass.h \
flags.h
df.o : df.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
insn-config.h $(RECOG_H) function.h $(REGS_H) alloc-pool.h hard-reg-set.h \
#include "c-pragma.h"
#include "langhooks.h"
#include "tree-mudflap.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "diagnostic.h"
#include "tree-dump.h"
#include "cgraph.h"
--- /dev/null
+/* Tree lowering pass. This pass gimplifies the tree representation built
+ by the C-based front ends. The structure of gimplified, or
+ language-independent, trees is dictated by the grammar described in this
+ file.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
+ Re-written to support lowering of whole function trees, documentation
+ and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "errors.h"
+#include "varray.h"
+#include "c-tree.h"
+#include "c-common.h"
+#include "tree-gimple.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "tree-flow.h"
+#include "tree-inline.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "flags.h"
+#include "rtl.h"
+#include "toplev.h"
+#include "tree-dump.h"
+#include "c-pretty-print.h"
+#include "cgraph.h"
+
+
+/* The gimplification pass converts the language-dependent trees
+ (ld-trees) emitted by the parser into language-independent trees
+ (li-trees) that are the target of SSA analysis and transformations.
+
+ Language-independent trees are based on the SIMPLE intermediate
+ representation used in the McCAT compiler framework:
+
+ "Designing the McCAT Compiler Based on a Family of Structured
+ Intermediate Representations,"
+ L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
+ Proceedings of the 5th International Workshop on Languages and
+ Compilers for Parallel Computing, no. 757 in Lecture Notes in
+ Computer Science, New Haven, Connecticut, pp. 406-420,
+ Springer-Verlag, August 3-5, 1992.
+
+ http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
+
+ Basically, we walk down gimplifying the nodes that we encounter. As we
+ walk back up, we check that they fit our constraints, and copy them
+ into temporaries if not. */
+
+/* Local declarations. */
+
+static enum gimplify_status gimplify_expr_stmt (tree *);
+static enum gimplify_status gimplify_decl_stmt (tree *);
+static enum gimplify_status gimplify_for_stmt (tree *, tree *);
+static enum gimplify_status gimplify_while_stmt (tree *);
+static enum gimplify_status gimplify_do_stmt (tree *);
+static enum gimplify_status gimplify_if_stmt (tree *);
+static enum gimplify_status gimplify_switch_stmt (tree *);
+static enum gimplify_status gimplify_return_stmt (tree *);
+static enum gimplify_status gimplify_stmt_expr (tree *);
+static enum gimplify_status gimplify_compound_literal_expr (tree *);
+#if defined ENABLE_CHECKING
+static int is_last_stmt_of_scope (tree);
+#endif
+static enum gimplify_status gimplify_block (tree *, tree *);
+static enum gimplify_status gimplify_cleanup (tree *, tree *);
+static tree gimplify_c_loop (tree, tree, tree, bool);
+static void push_context (void);
+static void pop_context (void);
+static tree c_build_bind_expr (tree, tree);
+static void add_block_to_enclosing (tree);
+static void gimplify_condition (tree *);
+
+enum bc_t { bc_break = 0, bc_continue = 1 };
+static tree begin_bc_block (enum bc_t);
+static tree finish_bc_block (tree, tree);
+static tree build_bc_goto (enum bc_t);
+
+static struct c_gimplify_ctx
+{
+ /* For handling break and continue. */
+ tree current_bc_label;
+ tree bc_id[2];
+} *ctxp;
+
+static void
+push_context (void)
+{
+ if (ctxp)
+ abort ();
+ ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
+ ctxp->bc_id[bc_continue] = get_identifier ("continue");
+ ctxp->bc_id[bc_break] = get_identifier ("break");
+}
+
+static void
+pop_context (void)
+{
+ if (!ctxp || ctxp->current_bc_label)
+ abort ();
+ free (ctxp);
+ ctxp = NULL;
+}
+
+/* Gimplification of statement trees. */
+
+/* Convert the tree representation of FNDECL from C frontend trees to
+ GENERIC. */
+
+void
+c_genericize (tree fndecl)
+{
+ FILE *dump_file;
+ int local_dump_flags;
+ struct cgraph_node *cgn;
+
+ /* Dump the C-specific tree IR. */
+ dump_file = dump_begin (TDI_original, &local_dump_flags);
+ if (dump_file)
+ {
+ fprintf (dump_file, "\n;; Function %s",
+ (*lang_hooks.decl_printable_name) (fndecl, 2));
+ fprintf (dump_file, " (%s)\n",
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+ fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
+ fprintf (dump_file, "\n");
+
+ if (local_dump_flags & TDF_RAW)
+ dump_node (DECL_SAVED_TREE (fndecl),
+ TDF_SLIM | local_dump_flags, dump_file);
+ else
+ print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
+ fprintf (dump_file, "\n");
+
+ dump_end (TDI_original, dump_file);
+ }
+
+ /* Go ahead and gimplify for now. */
+ push_context ();
+ gimplify_function_tree (fndecl);
+ pop_context ();
+
+ /* Dump the genericized tree IR. */
+ dump_function (TDI_generic, fndecl);
+
+ /* Genericize all nested functions now. We do things in this order so
+ that items like VLA sizes are expanded properly in the context of
+ the correct function. */
+ cgn = cgraph_node (fndecl);
+ for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
+ c_genericize (cgn->decl);
+}
+
+/* Entry point for the tree lowering pass. Recursively scan
+ *STMT_P and convert it to a GIMPLE tree. */
+
+int
+c_gimplify_stmt (tree *stmt_p)
+{
+ tree stmt, next;
+ tree outer_pre = NULL_TREE;
+
+ /* PRE and POST are tree chains that contain the side-effects of the
+ gimplified tree. For instance, given the expression tree:
+
+ c = ++a * 3 + b++;
+
+ After gimplification, the tree will be re-written as:
+
+ a = a + 1;
+ t1 = a * 3; <-- PRE
+ c = t1 + b;
+ b = b + 1; <-- POST */
+
+ for (stmt = *stmt_p; stmt && stmt != error_mark_node; stmt = next)
+ {
+ tree pre, post;
+ int saved_stmts_are_full_exprs_p;
+ location_t stmt_locus;
+ enum gimplify_status ret;
+
+ /* Set up context appropriately for handling this statement. */
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
+ prep_stmt (stmt);
+ stmt_locus = input_location;
+
+ pre = NULL_TREE;
+ post = NULL_TREE;
+
+ next = TREE_CHAIN (stmt);
+
+ switch (TREE_CODE (stmt))
+ {
+ case COMPOUND_STMT:
+ stmt = COMPOUND_BODY (stmt);
+ ret = GS_OK;
+ break;
+
+ case SCOPE_STMT:
+ ret = gimplify_block (&stmt, &next);
+ break;
+
+ case FOR_STMT:
+ ret = gimplify_for_stmt (&stmt, &next);
+ break;
+
+ case WHILE_STMT:
+ ret = gimplify_while_stmt (&stmt);
+ break;
+
+ case DO_STMT:
+ ret = gimplify_do_stmt (&stmt);
+ break;
+
+ case IF_STMT:
+ ret = gimplify_if_stmt (&stmt);
+ break;
+
+ case SWITCH_STMT:
+ ret = gimplify_switch_stmt (&stmt);
+ break;
+
+ case EXPR_STMT:
+ ret = gimplify_expr_stmt (&stmt);
+ break;
+
+ case RETURN_STMT:
+ ret = gimplify_return_stmt (&stmt);
+ break;
+
+ case DECL_STMT:
+ ret = gimplify_decl_stmt (&stmt);
+ break;
+
+ case LABEL_STMT:
+ stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
+ ret = GS_OK;
+ break;
+
+ case GOTO_STMT:
+ stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
+ ret = GS_OK;
+ break;
+
+ case CASE_LABEL:
+ {
+ tree label = create_artificial_label ();
+ stmt = build (CASE_LABEL_EXPR, void_type_node,
+ CASE_LOW (stmt), CASE_HIGH (stmt), label);
+ ret = GS_OK;
+ }
+ break;
+
+ case CONTINUE_STMT:
+ stmt = build_bc_goto (bc_continue);
+ ret = GS_OK;
+ break;
+
+ case BREAK_STMT:
+ stmt = build_bc_goto (bc_break);
+ ret = GS_OK;
+ break;
+
+ case CLEANUP_STMT:
+ ret = gimplify_cleanup (&stmt, &next);
+ break;
+
+ case ASM_STMT:
+ {
+ tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
+ ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
+ ASM_CLOBBERS (stmt));
+ ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
+ ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
+ stmt = new_stmt;
+ ret = GS_OK;
+ }
+ break;
+
+ default:
+ if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next))
+ {
+ ret = GS_OK;
+ break;
+ }
+
+ fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
+ debug_tree (stmt);
+ abort ();
+ break;
+ }
+
+ switch (ret)
+ {
+ case GS_ERROR:
+ goto cont;
+ case GS_OK:
+ gimplify_stmt (&stmt);
+ break;
+ case GS_ALL_DONE:
+ break;
+ default:
+ abort ();
+ }
+
+ /* PRE and POST now contain a list of statements for all the
+ side-effects in STMT. */
+
+ append_to_statement_list (stmt, &pre);
+ append_to_statement_list (post, &pre);
+ annotate_all_with_locus (&pre, stmt_locus);
+
+ append_to_statement_list (pre, &outer_pre);
+ cont:
+ /* Restore saved state. */
+ current_stmt_tree ()->stmts_are_full_exprs_p
+ = saved_stmts_are_full_exprs_p;
+ }
+ append_to_statement_list (stmt, &outer_pre);
+ *stmt_p = outer_pre;
+
+ return GS_ALL_DONE;
+}
+
+static void
+add_block_to_enclosing (tree block)
+{
+ tree enclosing;
+
+ for (enclosing = gimple_current_bind_expr ();
+ enclosing; enclosing = TREE_CHAIN (enclosing))
+ if (BIND_EXPR_BLOCK (enclosing))
+ break;
+
+ enclosing = BIND_EXPR_BLOCK (enclosing);
+ BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
+}
+
+/* Genericize a scope by creating a new BIND_EXPR.
+ BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
+ In the latter case, we need to create a new BLOCK and add it to the
+ BLOCK_SUBBLOCKS of the enclosing block.
+ BODY is a chain of C _STMT nodes for the contents of the scope, to be
+ genericized. */
+
+static tree
+c_build_bind_expr (tree block, tree body)
+{
+ tree decls, bind;
+
+ if (block == NULL_TREE)
+ decls = NULL_TREE;
+ else if (TREE_CODE (block) == BLOCK)
+ decls = BLOCK_VARS (block);
+ else
+ {
+ decls = block;
+ if (DECL_ARTIFICIAL (decls))
+ block = NULL_TREE;
+ else
+ {
+ block = make_node (BLOCK);
+ BLOCK_VARS (block) = decls;
+ add_block_to_enclosing (block);
+ }
+ }
+
+ if (!body)
+ body = build_empty_stmt ();
+
+ bind = build (BIND_EXPR, void_type_node, decls, body, block);
+ TREE_SIDE_EFFECTS (bind) = 1;
+
+ return bind;
+}
+
+/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and
+ wrapping the intervening code in a BIND_EXPR. This function assumes
+ that matching SCOPE_STMTs will always appear in the same statement
+ sequence. */
+
+static enum gimplify_status
+gimplify_block (tree *stmt_p, tree *next_p)
+{
+ tree *p;
+ tree block;
+ tree bind;
+ int depth;
+ location_t stmt_locus;
+
+ if (!SCOPE_BEGIN_P (*stmt_p))
+ {
+ /* Can wind up mismatched with syntax errors. */
+ if (!errorcount && !sorrycount)
+ abort ();
+ *stmt_p = NULL;
+ return GS_ERROR;
+ }
+
+ block = SCOPE_STMT_BLOCK (*stmt_p);
+
+ /* Find the matching ending SCOPE_STMT. */
+ depth = 1;
+ for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
+ {
+ if (*p == NULL)
+ break;
+ if (TREE_CODE (*p) == SCOPE_STMT)
+ {
+ if (SCOPE_BEGIN_P (*p))
+ ++depth;
+ else if (--depth == 0)
+ break;
+ }
+ }
+
+ stmt_locus = input_location;
+ if (*p)
+ {
+ if (SCOPE_STMT_BLOCK (*p) != block)
+ abort ();
+ if (EXPR_LOCUS (*p))
+ stmt_locus = *EXPR_LOCUS (*p);
+ *next_p = TREE_CHAIN (*p);
+ *p = NULL_TREE;
+ }
+ else
+ {
+ /* Can wind up mismatched with syntax errors. */
+ if (!errorcount && !sorrycount)
+ abort ();
+ }
+
+ bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p));
+ *stmt_p = bind;
+ input_location = stmt_locus;
+
+ return GS_OK;
+}
+
+/* Genericize a CLEANUP_STMT. Just wrap everything from here to the end of
+ the block in a TRY_FINALLY_EXPR. Or a TRY_CATCH_EXPR, if it's an
+ EH-only cleanup. */
+
+static enum gimplify_status
+gimplify_cleanup (tree *stmt_p, tree *next_p)
+{
+ tree stmt = *stmt_p;
+ tree body = TREE_CHAIN (stmt);
+ tree cleanup = CLEANUP_EXPR (stmt);
+ enum tree_code code
+ = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
+
+ if (!body)
+ body = build_empty_stmt ();
+ if (!cleanup)
+ cleanup = build_empty_stmt ();
+
+ *stmt_p = build (code, void_type_node, body, cleanup);
+ *next_p = NULL_TREE;
+
+ return GS_OK;
+}
+
+/* Gimplify an EXPR_STMT node.
+
+ STMT is the statement node.
+
+ PRE_P points to the list where side effects that must happen before
+ STMT should be stored.
+
+ POST_P points to the list where side effects that must happen after
+ STMT should be stored. */
+
+static enum gimplify_status
+gimplify_expr_stmt (tree *stmt_p)
+{
+ tree stmt = EXPR_STMT_EXPR (*stmt_p);
+
+ if (stmt == error_mark_node)
+ stmt = NULL;
+
+ /* Gimplification of a statement expression will nullify the
+ statement if all its side effects are moved to *PRE_P and *POST_P.
+
+ In this case we will not want to emit the gimplified statement.
+ However, we may still want to emit a warning, so we do that before
+ gimplification. */
+ if (stmt && (extra_warnings || warn_unused_value))
+ {
+ if (!TREE_SIDE_EFFECTS (stmt))
+ {
+ if (!IS_EMPTY_STMT (stmt)
+ && !VOID_TYPE_P (TREE_TYPE (stmt))
+ && !TREE_NO_WARNING (stmt))
+ warning ("statement with no effect");
+ }
+ else if (warn_unused_value)
+ {
+ /* Kludge for 20020220-2.c. warn_if_unused_value shouldn't use
+ the stmt file location info. */
+ set_file_and_line_for_stmt (input_location);
+ warn_if_unused_value (stmt);
+ }
+ }
+
+ if (stmt == NULL_TREE)
+ stmt = build_empty_stmt ();
+ else if (stmts_are_full_exprs_p ())
+ stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
+
+ *stmt_p = stmt;
+
+ return GS_OK;
+}
+
+/* If the condition for a loop (or the like) is a decl, it will be a
+ TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
+ a use of the decl. Turn such a thing into a COMPOUND_EXPR. */
+
+static void
+gimplify_condition (tree *cond_p)
+{
+ tree cond = *cond_p;
+ if (cond && TREE_CODE (cond) == TREE_LIST)
+ {
+ tree decl = TREE_PURPOSE (cond);
+ tree value = TREE_VALUE (cond);
+ c_gimplify_stmt (&decl);
+ *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
+ }
+}
+
+/* Begin a scope which can be exited by a break or continue statement. BC
+ indicates which.
+
+ Just creates a label and pushes it into the current context. */
+
+static tree
+begin_bc_block (enum bc_t bc)
+{
+ tree label = create_artificial_label ();
+ DECL_NAME (label) = ctxp->bc_id[bc];
+ TREE_CHAIN (label) = ctxp->current_bc_label;
+ ctxp->current_bc_label = label;
+ return label;
+}
+
+/* Finish a scope which can be exited by a break or continue statement.
+ LABEL was returned from the most recent call to begin_bc_block. BODY is
+ an expression for the contents of the scope.
+
+ If we saw a break (or continue) in the scope, append a LABEL_EXPR to
+ body. Otherwise, just forget the label. */
+
+static tree
+finish_bc_block (tree label, tree body)
+{
+ if (label != ctxp->current_bc_label)
+ abort ();
+
+ if (TREE_USED (label))
+ {
+ tree t, sl = NULL;
+
+ /* Clear the name so flow can delete the label. */
+ DECL_NAME (label) = NULL_TREE;
+ t = build1 (LABEL_EXPR, void_type_node, label);
+
+ append_to_statement_list (body, &sl);
+ append_to_statement_list (t, &sl);
+ body = sl;
+ }
+
+ ctxp->current_bc_label = TREE_CHAIN (label);
+ TREE_CHAIN (label) = NULL_TREE;
+ return body;
+}
+
+/* Build a GOTO_EXPR to represent a break or continue statement. BC
+ indicates which. */
+
+static tree
+build_bc_goto (enum bc_t bc)
+{
+ tree label;
+ tree target_name = ctxp->bc_id[bc];
+
+ /* Look for the appropriate type of label. */
+ for (label = ctxp->current_bc_label;
+ label;
+ label = TREE_CHAIN (label))
+ if (DECL_NAME (label) == target_name)
+ break;
+
+ if (label == NULL_TREE)
+ {
+ if (bc == bc_break)
+ error ("break statement not within loop or switch");
+ else
+ error ("continue statement not within loop or switch");
+
+ return NULL_TREE;
+ }
+
+ /* Mark the label used for finish_bc_block. */
+ TREE_USED (label) = 1;
+ return build1 (GOTO_EXPR, void_type_node, label);
+}
+
+/* Build a generic representation of one of the C loop forms. COND is the
+ loop condition or NULL_TREE. BODY is the (possibly compound) statement
+ controlled by the loop. INCR is the increment expression of a for-loop,
+ or NULL_TREE. COND_IS_FIRST indicates whether the condition is
+ evaluated before the loop body as in while and for loops, or after the
+ loop body as in do-while loops. */
+
+static tree
+gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
+{
+ tree top, entry, exit, cont_block, break_block, stmt_list, t;
+ location_t stmt_locus;
+
+ stmt_locus = input_location;
+
+ /* Detect do { ... } while (0) and don't generate loop construct. */
+ if (!cond_is_first && cond && integer_zerop (cond))
+ top = cond = NULL;
+ else
+ {
+ /* If we use a LOOP_EXPR here, we have to feed the whole thing
+ back through the main gimplifier to lower it. Given that we
+ have to gimplify the loop body NOW so that we can resolve
+ break/continue stmts, seems easier to just expand to gotos. */
+ top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+ }
+
+ break_block = begin_bc_block (bc_break);
+
+ if (top)
+ {
+ /* If we have an exit condition, then we build an IF with gotos either
+ out of the loop, or to the top of it. If there's no exit condition,
+ then we just build a jump back to the top. */
+ exit = build_and_jump (&LABEL_EXPR_LABEL (top));
+ if (cond)
+ {
+ gimplify_condition (&cond);
+ t = build_bc_goto (bc_break);
+ exit = build (COND_EXPR, void_type_node, cond, exit, t);
+ exit = fold (exit);
+ gimplify_stmt (&exit);
+ }
+ }
+ else
+ exit = NULL_TREE;
+
+ cont_block = begin_bc_block (bc_continue);
+
+ gimplify_stmt (&body);
+ if (incr && stmts_are_full_exprs_p ())
+ incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
+ gimplify_stmt (&incr);
+
+ body = finish_bc_block (cont_block, body);
+
+ stmt_list = NULL;
+
+ if (cond_is_first && cond)
+ {
+ entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
+ t = build_and_jump (&LABEL_EXPR_LABEL (entry));
+ append_to_statement_list (t, &stmt_list);
+ }
+ else
+ entry = NULL_TREE;
+
+ append_to_statement_list (top, &stmt_list);
+ append_to_statement_list (body, &stmt_list);
+ append_to_statement_list (incr, &stmt_list);
+ append_to_statement_list (entry, &stmt_list);
+ append_to_statement_list (exit, &stmt_list);
+
+ annotate_all_with_locus (&stmt_list, stmt_locus);
+
+ return finish_bc_block (break_block, stmt_list);
+}
+
+/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
+ prequeue and hand off to gimplify_c_loop. */
+
+static enum gimplify_status
+gimplify_for_stmt (tree *stmt_p, tree *next_p)
+{
+ tree stmt = *stmt_p;
+ tree init = FOR_INIT_STMT (stmt);
+
+ if (init)
+ {
+ /* Reorganize the statements so that we do the right thing with a
+ CLEANUP_STMT. We want the FOR_STMT and nothing else to be in the
+ scope of the cleanup, so play with pointers to accomplish that. */
+ FOR_INIT_STMT (stmt) = NULL_TREE;
+ chainon (init, stmt);
+ *stmt_p = init;
+ *next_p = TREE_CHAIN (stmt);
+ TREE_CHAIN (stmt) = NULL_TREE;
+ c_gimplify_stmt (stmt_p);
+ }
+ else
+ *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
+ FOR_EXPR (stmt), 1);
+
+ return GS_ALL_DONE;
+}
+
+/* Gimplify a WHILE_STMT node. */
+
+static enum gimplify_status
+gimplify_while_stmt (tree *stmt_p)
+{
+ tree stmt = *stmt_p;
+ *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
+ NULL_TREE, 1);
+ return GS_ALL_DONE;
+}
+
+/* Gimplify a DO_STMT node. */
+
+static enum gimplify_status
+gimplify_do_stmt (tree *stmt_p)
+{
+ tree stmt = *stmt_p;
+ *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
+ NULL_TREE, 0);
+ return GS_ALL_DONE;
+}
+
+/* Genericize an IF_STMT by turning it into a COND_EXPR. */
+
+static enum gimplify_status
+gimplify_if_stmt (tree *stmt_p)
+{
+ tree stmt, then_, else_;
+
+ stmt = *stmt_p;
+ restart:
+ then_ = THEN_CLAUSE (stmt);
+ else_ = ELSE_CLAUSE (stmt);
+
+ if (!then_)
+ then_ = build_empty_stmt ();
+ if (!else_)
+ else_ = build_empty_stmt ();
+
+ stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
+ gimplify_condition (& TREE_OPERAND (stmt, 0));
+ *stmt_p = stmt;
+
+ /* Handle properly nested if-else chains via iteration instead of
+ mutual recursion between gimplify.c and c-simplify.c. */
+ annotate_with_locus (stmt, input_location);
+ if (TREE_CODE (else_) == IF_STMT && !TREE_CHAIN (else_))
+ {
+ stmt_p = &COND_EXPR_ELSE (stmt);
+ stmt = else_;
+ prep_stmt (stmt);
+ goto restart;
+ }
+
+ return GS_OK;
+}
+
+/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
+
+static enum gimplify_status
+gimplify_switch_stmt (tree *stmt_p)
+{
+ tree stmt = *stmt_p;
+ tree break_block, body;
+ location_t stmt_locus = input_location;
+
+ break_block = begin_bc_block (bc_break);
+
+ gimplify_condition (&SWITCH_COND (stmt));
+
+ body = SWITCH_BODY (stmt);
+ if (!body)
+ body = build_empty_stmt ();
+
+ *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
+ body, NULL_TREE);
+ annotate_with_locus (*stmt_p, stmt_locus);
+ gimplify_stmt (stmt_p);
+
+ *stmt_p = finish_bc_block (break_block, *stmt_p);
+ return GS_ALL_DONE;
+}
+
+/* Genericize a RETURN_STMT by turning it into a RETURN_EXPR. */
+
+static enum gimplify_status
+gimplify_return_stmt (tree *stmt_p)
+{
+ tree expr = RETURN_STMT_EXPR (*stmt_p);
+ expr = build1 (RETURN_EXPR, void_type_node, expr);
+ if (stmts_are_full_exprs_p ())
+ expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
+ *stmt_p = expr;
+ return GS_OK;
+}
+
+/* Gimplifies a DECL_STMT node T.
+
+ If a declaration V has an initial value I, create an expression 'V = I'
+ and insert it after the DECL_STMT.
+
+ PRE_P is a queue for effects that should happen before the DECL_STMT.
+
+ MID_P is a queue for effects that should happen after the DECL_STMT,
+ but before uses of the initialized decl.
+
+ POST_P is a queue for effects that should happen after uses of the
+ initialized decl.
+
+ Usually these last two will be the same, but they may need to be
+ different if the DECL_STMT is somehow embedded in an expression. */
+
+static enum gimplify_status
+gimplify_decl_stmt (tree *stmt_p)
+{
+ tree stmt = *stmt_p;
+ tree decl = DECL_STMT_DECL (stmt);
+ tree pre = NULL_TREE;
+ tree post = NULL_TREE;
+
+ if (TREE_TYPE (decl) == error_mark_node)
+ {
+ *stmt_p = NULL;
+ return GS_ERROR;
+ }
+
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ tree type = TREE_TYPE (decl);
+ if (TYPE_SIZE_UNIT (type)
+ && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
+ {
+ /* This is a variable-sized array type. Simplify its size. */
+ tree temp = TYPE_SIZE_UNIT (type);
+ gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
+ }
+ }
+
+ if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+ {
+ tree init = DECL_INITIAL (decl);
+
+ if (!TREE_CONSTANT (DECL_SIZE (decl)))
+ {
+ tree pt_type = build_pointer_type (TREE_TYPE (decl));
+ tree alloc, size;
+
+ /* This is a variable-sized decl. Simplify its size and mark it
+ for deferred expansion. Note that mudflap depends on the format
+ of the emitted code: see mx_register_decls(). */
+
+ size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
+ DECL_DEFER_OUTPUT (decl) = 1;
+ alloc = build_function_call_expr
+ (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
+ tree_cons (NULL_TREE,
+ build1 (ADDR_EXPR, pt_type, decl),
+ tree_cons (NULL_TREE, size, NULL_TREE)));
+ append_to_compound_expr (alloc, &pre);
+ }
+
+ if (init && init != error_mark_node)
+ {
+ if (!TREE_STATIC (decl))
+ {
+ /* Do not warn about int x = x; as it is a GCC extension
+ to turn off this warning but only if warn_init_self
+ is zero. */
+ if (init == decl && !warn_init_self)
+ TREE_NO_WARNING (decl) = 1;
+
+ DECL_INITIAL (decl) = NULL_TREE;
+ init = build (MODIFY_EXPR, void_type_node, decl, init);
+ if (stmts_are_full_exprs_p ())
+ init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
+ append_to_compound_expr (init, &pre);
+ }
+ else
+ {
+ /* We must still examine initializers for static variables
+ as they may contain a label address. */
+ walk_tree (&init, force_labels_r, NULL, NULL);
+ }
+ }
+
+ /* This decl isn't mentioned in the enclosing block, so add it to the
+ list of temps. FIXME it seems a bit of a kludge to say that
+ anonymous artificial vars aren't pushed, but everything else is. */
+ if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
+ gimple_add_tmp_var (decl);
+ }
+
+ append_to_compound_expr (post, &pre);
+ *stmt_p = pre;
+ return GS_OK;
+}
+
+/* Gimplification of expression trees. */
+
+/* Gimplify a C99 compound literal expression. This just means adding the
+ DECL_STMT before the current EXPR_STMT and using its anonymous decl
+ instead. */
+
+static enum gimplify_status
+gimplify_compound_literal_expr (tree *expr_p)
+{
+ tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
+ tree decl = DECL_STMT_DECL (decl_s);
+
+ /* This decl isn't mentioned in the enclosing block, so add it to the
+ list of temps. FIXME it seems a bit of a kludge to say that
+ anonymous artificial vars aren't pushed, but everything else is. */
+ if (DECL_NAME (decl) == NULL_TREE)
+ gimple_add_tmp_var (decl);
+
+ gimplify_decl_stmt (&decl_s);
+ *expr_p = decl_s ? decl_s : decl;
+ return GS_OK;
+}
+
+/* Do C-specific gimplification. Args are as for gimplify_expr. */
+
+int
+c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
+ tree *post_p ATTRIBUTE_UNUSED)
+{
+ enum tree_code code = TREE_CODE (*expr_p);
+
+ if (STATEMENT_CODE_P (code))
+ return c_gimplify_stmt (expr_p);
+
+ switch (code)
+ {
+ case COMPOUND_LITERAL_EXPR:
+ return gimplify_compound_literal_expr (expr_p);
+
+ case STMT_EXPR:
+ return gimplify_stmt_expr (expr_p);
+
+ default:
+ return GS_UNHANDLED;
+ }
+}
+
+/* Returns the final EXPR_STMT which represents the return value of a
+ STMT_EXPR, or NULL_TREE if none. */
+
+tree
+stmt_expr_last_stmt (tree stmt_expr)
+{
+ tree body = STMT_EXPR_STMT (stmt_expr);
+ tree last_stmt, substmt;
+
+ /* Splice the last expression out of the STMT chain. */
+ last_stmt = NULL_TREE;
+ for (substmt = COMPOUND_BODY (body); substmt;
+ substmt = TREE_CHAIN (substmt))
+ if (TREE_CODE (substmt) != SCOPE_STMT)
+ last_stmt = substmt;
+
+ if (last_stmt == NULL_TREE
+ || TREE_CODE (last_stmt) != EXPR_STMT
+ || (TREE_TYPE (last_stmt)
+ && VOID_TYPE_P (TREE_TYPE (last_stmt))))
+ {
+ location_t loc;
+ if (last_stmt && EXPR_LOCUS (last_stmt))
+ loc = *EXPR_LOCUS (last_stmt);
+ else if (EXPR_LOCUS (stmt_expr))
+ loc = *EXPR_LOCUS (stmt_expr);
+ else
+ loc = input_location;
+ warning ("%Hstatement-expressions should end with a "
+ "non-void expression", &loc);
+ last_stmt = NULL_TREE;
+ }
+
+#if defined ENABLE_CHECKING
+ if (last_stmt && !is_last_stmt_of_scope (last_stmt))
+ abort ();
+#endif
+
+ return last_stmt;
+}
+
+/* Gimplify a STMT_EXPR. EXPR_P points to the expression to gimplify.
+ After gimplification, if the STMT_EXPR returns a value, EXPR_P will
+ point to a new temporary that holds that value; otherwise it will be
+ null.
+
+ PRE_P points to the list where side effects that must happen before
+ *EXPR_P should be stored. */
+
+static enum gimplify_status
+gimplify_stmt_expr (tree *expr_p)
+{
+ tree body = STMT_EXPR_STMT (*expr_p);
+
+ if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
+ {
+ *expr_p = body;
+ return c_gimplify_stmt (expr_p);
+ }
+ else
+ {
+ tree last_stmt = stmt_expr_last_stmt (*expr_p);
+ tree last_expr = NULL_TREE;
+
+ if (last_stmt)
+ {
+ last_expr = EXPR_STMT_EXPR (last_stmt);
+
+ if (stmts_are_full_exprs_p ())
+ last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr),
+ last_expr);
+ EXPR_STMT_EXPR (last_stmt) = NULL_TREE;
+ }
+
+ /* Genericize the block. */
+ c_gimplify_stmt (&body);
+
+ /* Now retrofit that last expression into the BIND_EXPR. */
+ if (last_expr)
+ {
+ tree *sub_p;
+
+ if (!STMT_EXPR_NO_SCOPE (*expr_p))
+ {
+ /* Our BIND_EXPR will always be hidden within
+ a STATEMENT_LIST. Discard that. */
+ body = expr_first (body);
+ sub_p = &BIND_EXPR_BODY (body);
+
+ /* Append the last expression to the end of the BIND_EXPR.
+ We'll now re-process this, and let voidify_wrapper_expr
+ do its job. */
+ append_to_statement_list_force (last_expr, sub_p);
+ TREE_TYPE (body) = TREE_TYPE (last_expr);
+ }
+ else
+ append_to_compound_expr (last_expr, &body);
+ }
+
+ *expr_p = body;
+ return GS_OK;
+ }
+}
+
+/* Code generation. */
+
+/* Miscellaneous helpers. */
+
+#if defined ENABLE_CHECKING
+/* Return nonzero if STMT is the last statement of its scope. */
+
+static int
+is_last_stmt_of_scope (tree stmt)
+{
+ return (TREE_CHAIN (stmt) == NULL_TREE
+ || (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
+ && SCOPE_END_P (TREE_CHAIN (stmt))));
+}
+#endif
+++ /dev/null
-/* Tree lowering pass. This pass gimplifies the tree representation built
- by the C-based front ends. The structure of gimplified, or
- language-independent, trees is dictated by the grammar described in this
- file.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
- Re-written to support lowering of whole function trees, documentation
- and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "errors.h"
-#include "varray.h"
-#include "c-tree.h"
-#include "c-common.h"
-#include "tree-simple.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "tree-flow.h"
-#include "tree-inline.h"
-#include "diagnostic.h"
-#include "langhooks.h"
-#include "langhooks-def.h"
-#include "flags.h"
-#include "rtl.h"
-#include "toplev.h"
-#include "tree-dump.h"
-#include "c-pretty-print.h"
-#include "cgraph.h"
-
-
-/* The gimplification pass converts the language-dependent trees
- (ld-trees) emitted by the parser into language-independent trees
- (li-trees) that are the target of SSA analysis and transformations.
-
- Language-independent trees are based on the SIMPLE intermediate
- representation used in the McCAT compiler framework:
-
- "Designing the McCAT Compiler Based on a Family of Structured
- Intermediate Representations,"
- L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
- Proceedings of the 5th International Workshop on Languages and
- Compilers for Parallel Computing, no. 757 in Lecture Notes in
- Computer Science, New Haven, Connecticut, pp. 406-420,
- Springer-Verlag, August 3-5, 1992.
-
- http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
-
- Basically, we walk down gimplifying the nodes that we encounter. As we
- walk back up, we check that they fit our constraints, and copy them
- into temporaries if not. */
-
-/* Local declarations. */
-
-static enum gimplify_status gimplify_expr_stmt (tree *);
-static enum gimplify_status gimplify_decl_stmt (tree *);
-static enum gimplify_status gimplify_for_stmt (tree *, tree *);
-static enum gimplify_status gimplify_while_stmt (tree *);
-static enum gimplify_status gimplify_do_stmt (tree *);
-static enum gimplify_status gimplify_if_stmt (tree *);
-static enum gimplify_status gimplify_switch_stmt (tree *);
-static enum gimplify_status gimplify_return_stmt (tree *);
-static enum gimplify_status gimplify_stmt_expr (tree *);
-static enum gimplify_status gimplify_compound_literal_expr (tree *);
-#if defined ENABLE_CHECKING
-static int is_last_stmt_of_scope (tree);
-#endif
-static enum gimplify_status gimplify_block (tree *, tree *);
-static enum gimplify_status gimplify_cleanup (tree *, tree *);
-static tree gimplify_c_loop (tree, tree, tree, bool);
-static void push_context (void);
-static void pop_context (void);
-static tree c_build_bind_expr (tree, tree);
-static void add_block_to_enclosing (tree);
-static void gimplify_condition (tree *);
-
-enum bc_t { bc_break = 0, bc_continue = 1 };
-static tree begin_bc_block (enum bc_t);
-static tree finish_bc_block (tree, tree);
-static tree build_bc_goto (enum bc_t);
-
-static struct c_gimplify_ctx
-{
- /* For handling break and continue. */
- tree current_bc_label;
- tree bc_id[2];
-} *ctxp;
-
-static void
-push_context (void)
-{
- if (ctxp)
- abort ();
- ctxp = (struct c_gimplify_ctx *) xcalloc (1, sizeof (struct c_gimplify_ctx));
- ctxp->bc_id[bc_continue] = get_identifier ("continue");
- ctxp->bc_id[bc_break] = get_identifier ("break");
-}
-
-static void
-pop_context (void)
-{
- if (!ctxp || ctxp->current_bc_label)
- abort ();
- free (ctxp);
- ctxp = NULL;
-}
-
-/* Gimplification of statement trees. */
-
-/* Convert the tree representation of FNDECL from C frontend trees to
- GENERIC. */
-
-void
-c_genericize (tree fndecl)
-{
- FILE *dump_file;
- int local_dump_flags;
- struct cgraph_node *cgn;
-
- /* Dump the C-specific tree IR. */
- dump_file = dump_begin (TDI_original, &local_dump_flags);
- if (dump_file)
- {
- fprintf (dump_file, "\n;; Function %s",
- (*lang_hooks.decl_printable_name) (fndecl, 2));
- fprintf (dump_file, " (%s)\n",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
- fprintf (dump_file, ";; enabled by -%s\n", dump_flag_name (TDI_original));
- fprintf (dump_file, "\n");
-
- if (local_dump_flags & TDF_RAW)
- dump_node (DECL_SAVED_TREE (fndecl),
- TDF_SLIM | local_dump_flags, dump_file);
- else
- print_c_tree (dump_file, DECL_SAVED_TREE (fndecl));
- fprintf (dump_file, "\n");
-
- dump_end (TDI_original, dump_file);
- }
-
- /* Go ahead and gimplify for now. */
- push_context ();
- gimplify_function_tree (fndecl);
- pop_context ();
-
- /* Dump the genericized tree IR. */
- dump_function (TDI_generic, fndecl);
-
- /* Genericize all nested functions now. We do things in this order so
- that items like VLA sizes are expanded properly in the context of
- the correct function. */
- cgn = cgraph_node (fndecl);
- for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- c_genericize (cgn->decl);
-}
-
-/* Entry point for the tree lowering pass. Recursively scan
- *STMT_P and convert it to a GIMPLE tree. */
-
-int
-c_gimplify_stmt (tree *stmt_p)
-{
- tree stmt, next;
- tree outer_pre = NULL_TREE;
-
- /* PRE and POST are tree chains that contain the side-effects of the
- gimplified tree. For instance, given the expression tree:
-
- c = ++a * 3 + b++;
-
- After gimplification, the tree will be re-written as:
-
- a = a + 1;
- t1 = a * 3; <-- PRE
- c = t1 + b;
- b = b + 1; <-- POST */
-
- for (stmt = *stmt_p; stmt && stmt != error_mark_node; stmt = next)
- {
- tree pre, post;
- int saved_stmts_are_full_exprs_p;
- location_t stmt_locus;
- enum gimplify_status ret;
-
- /* Set up context appropriately for handling this statement. */
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
- prep_stmt (stmt);
- stmt_locus = input_location;
-
- pre = NULL_TREE;
- post = NULL_TREE;
-
- next = TREE_CHAIN (stmt);
-
- switch (TREE_CODE (stmt))
- {
- case COMPOUND_STMT:
- stmt = COMPOUND_BODY (stmt);
- ret = GS_OK;
- break;
-
- case SCOPE_STMT:
- ret = gimplify_block (&stmt, &next);
- break;
-
- case FOR_STMT:
- ret = gimplify_for_stmt (&stmt, &next);
- break;
-
- case WHILE_STMT:
- ret = gimplify_while_stmt (&stmt);
- break;
-
- case DO_STMT:
- ret = gimplify_do_stmt (&stmt);
- break;
-
- case IF_STMT:
- ret = gimplify_if_stmt (&stmt);
- break;
-
- case SWITCH_STMT:
- ret = gimplify_switch_stmt (&stmt);
- break;
-
- case EXPR_STMT:
- ret = gimplify_expr_stmt (&stmt);
- break;
-
- case RETURN_STMT:
- ret = gimplify_return_stmt (&stmt);
- break;
-
- case DECL_STMT:
- ret = gimplify_decl_stmt (&stmt);
- break;
-
- case LABEL_STMT:
- stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
- ret = GS_OK;
- break;
-
- case GOTO_STMT:
- stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
- ret = GS_OK;
- break;
-
- case CASE_LABEL:
- {
- tree label = create_artificial_label ();
- stmt = build (CASE_LABEL_EXPR, void_type_node,
- CASE_LOW (stmt), CASE_HIGH (stmt), label);
- ret = GS_OK;
- }
- break;
-
- case CONTINUE_STMT:
- stmt = build_bc_goto (bc_continue);
- ret = GS_OK;
- break;
-
- case BREAK_STMT:
- stmt = build_bc_goto (bc_break);
- ret = GS_OK;
- break;
-
- case CLEANUP_STMT:
- ret = gimplify_cleanup (&stmt, &next);
- break;
-
- case ASM_STMT:
- {
- tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
- ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
- ASM_CLOBBERS (stmt));
- ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
- ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
- stmt = new_stmt;
- ret = GS_OK;
- }
- break;
-
- default:
- if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next))
- {
- ret = GS_OK;
- break;
- }
-
- fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
- debug_tree (stmt);
- abort ();
- break;
- }
-
- switch (ret)
- {
- case GS_ERROR:
- goto cont;
- case GS_OK:
- gimplify_stmt (&stmt);
- break;
- case GS_ALL_DONE:
- break;
- default:
- abort ();
- }
-
- /* PRE and POST now contain a list of statements for all the
- side-effects in STMT. */
-
- append_to_statement_list (stmt, &pre);
- append_to_statement_list (post, &pre);
- annotate_all_with_locus (&pre, stmt_locus);
-
- append_to_statement_list (pre, &outer_pre);
- cont:
- /* Restore saved state. */
- current_stmt_tree ()->stmts_are_full_exprs_p
- = saved_stmts_are_full_exprs_p;
- }
- append_to_statement_list (stmt, &outer_pre);
- *stmt_p = outer_pre;
-
- return GS_ALL_DONE;
-}
-
-static void
-add_block_to_enclosing (tree block)
-{
- tree enclosing;
-
- for (enclosing = gimple_current_bind_expr ();
- enclosing; enclosing = TREE_CHAIN (enclosing))
- if (BIND_EXPR_BLOCK (enclosing))
- break;
-
- enclosing = BIND_EXPR_BLOCK (enclosing);
- BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
-}
-
-/* Genericize a scope by creating a new BIND_EXPR.
- BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
- In the latter case, we need to create a new BLOCK and add it to the
- BLOCK_SUBBLOCKS of the enclosing block.
- BODY is a chain of C _STMT nodes for the contents of the scope, to be
- genericized. */
-
-static tree
-c_build_bind_expr (tree block, tree body)
-{
- tree decls, bind;
-
- if (block == NULL_TREE)
- decls = NULL_TREE;
- else if (TREE_CODE (block) == BLOCK)
- decls = BLOCK_VARS (block);
- else
- {
- decls = block;
- if (DECL_ARTIFICIAL (decls))
- block = NULL_TREE;
- else
- {
- block = make_node (BLOCK);
- BLOCK_VARS (block) = decls;
- add_block_to_enclosing (block);
- }
- }
-
- if (!body)
- body = build_empty_stmt ();
-
- bind = build (BIND_EXPR, void_type_node, decls, body, block);
- TREE_SIDE_EFFECTS (bind) = 1;
-
- return bind;
-}
-
-/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and
- wrapping the intervening code in a BIND_EXPR. This function assumes
- that matching SCOPE_STMTs will always appear in the same statement
- sequence. */
-
-static enum gimplify_status
-gimplify_block (tree *stmt_p, tree *next_p)
-{
- tree *p;
- tree block;
- tree bind;
- int depth;
- location_t stmt_locus;
-
- if (!SCOPE_BEGIN_P (*stmt_p))
- {
- /* Can wind up mismatched with syntax errors. */
- if (!errorcount && !sorrycount)
- abort ();
- *stmt_p = NULL;
- return GS_ERROR;
- }
-
- block = SCOPE_STMT_BLOCK (*stmt_p);
-
- /* Find the matching ending SCOPE_STMT. */
- depth = 1;
- for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
- {
- if (*p == NULL)
- break;
- if (TREE_CODE (*p) == SCOPE_STMT)
- {
- if (SCOPE_BEGIN_P (*p))
- ++depth;
- else if (--depth == 0)
- break;
- }
- }
-
- stmt_locus = input_location;
- if (*p)
- {
- if (SCOPE_STMT_BLOCK (*p) != block)
- abort ();
- if (EXPR_LOCUS (*p))
- stmt_locus = *EXPR_LOCUS (*p);
- *next_p = TREE_CHAIN (*p);
- *p = NULL_TREE;
- }
- else
- {
- /* Can wind up mismatched with syntax errors. */
- if (!errorcount && !sorrycount)
- abort ();
- }
-
- bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p));
- *stmt_p = bind;
- input_location = stmt_locus;
-
- return GS_OK;
-}
-
-/* Genericize a CLEANUP_STMT. Just wrap everything from here to the end of
- the block in a TRY_FINALLY_EXPR. Or a TRY_CATCH_EXPR, if it's an
- EH-only cleanup. */
-
-static enum gimplify_status
-gimplify_cleanup (tree *stmt_p, tree *next_p)
-{
- tree stmt = *stmt_p;
- tree body = TREE_CHAIN (stmt);
- tree cleanup = CLEANUP_EXPR (stmt);
- enum tree_code code
- = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
-
- if (!body)
- body = build_empty_stmt ();
- if (!cleanup)
- cleanup = build_empty_stmt ();
-
- *stmt_p = build (code, void_type_node, body, cleanup);
- *next_p = NULL_TREE;
-
- return GS_OK;
-}
-
-/* Gimplify an EXPR_STMT node.
-
- STMT is the statement node.
-
- PRE_P points to the list where side effects that must happen before
- STMT should be stored.
-
- POST_P points to the list where side effects that must happen after
- STMT should be stored. */
-
-static enum gimplify_status
-gimplify_expr_stmt (tree *stmt_p)
-{
- tree stmt = EXPR_STMT_EXPR (*stmt_p);
-
- if (stmt == error_mark_node)
- stmt = NULL;
-
- /* Gimplification of a statement expression will nullify the
- statement if all its side effects are moved to *PRE_P and *POST_P.
-
- In this case we will not want to emit the gimplified statement.
- However, we may still want to emit a warning, so we do that before
- gimplification. */
- if (stmt && (extra_warnings || warn_unused_value))
- {
- if (!TREE_SIDE_EFFECTS (stmt))
- {
- if (!IS_EMPTY_STMT (stmt)
- && !VOID_TYPE_P (TREE_TYPE (stmt))
- && !TREE_NO_WARNING (stmt))
- warning ("statement with no effect");
- }
- else if (warn_unused_value)
- {
- /* Kludge for 20020220-2.c. warn_if_unused_value shouldn't use
- the stmt file location info. */
- set_file_and_line_for_stmt (input_location);
- warn_if_unused_value (stmt);
- }
- }
-
- if (stmt == NULL_TREE)
- stmt = build_empty_stmt ();
- else if (stmts_are_full_exprs_p ())
- stmt = build1 (CLEANUP_POINT_EXPR, void_type_node, stmt);
-
- *stmt_p = stmt;
-
- return GS_OK;
-}
-
-/* If the condition for a loop (or the like) is a decl, it will be a
- TREE_LIST where the TREE_PURPOSE is a DECL_STMT and the TREE_VALUE is
- a use of the decl. Turn such a thing into a COMPOUND_EXPR. */
-
-static void
-gimplify_condition (tree *cond_p)
-{
- tree cond = *cond_p;
- if (cond && TREE_CODE (cond) == TREE_LIST)
- {
- tree decl = TREE_PURPOSE (cond);
- tree value = TREE_VALUE (cond);
- c_gimplify_stmt (&decl);
- *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
- }
-}
-
-/* Begin a scope which can be exited by a break or continue statement. BC
- indicates which.
-
- Just creates a label and pushes it into the current context. */
-
-static tree
-begin_bc_block (enum bc_t bc)
-{
- tree label = create_artificial_label ();
- DECL_NAME (label) = ctxp->bc_id[bc];
- TREE_CHAIN (label) = ctxp->current_bc_label;
- ctxp->current_bc_label = label;
- return label;
-}
-
-/* Finish a scope which can be exited by a break or continue statement.
- LABEL was returned from the most recent call to begin_bc_block. BODY is
- an expression for the contents of the scope.
-
- If we saw a break (or continue) in the scope, append a LABEL_EXPR to
- body. Otherwise, just forget the label. */
-
-static tree
-finish_bc_block (tree label, tree body)
-{
- if (label != ctxp->current_bc_label)
- abort ();
-
- if (TREE_USED (label))
- {
- tree t, sl = NULL;
-
- /* Clear the name so flow can delete the label. */
- DECL_NAME (label) = NULL_TREE;
- t = build1 (LABEL_EXPR, void_type_node, label);
-
- append_to_statement_list (body, &sl);
- append_to_statement_list (t, &sl);
- body = sl;
- }
-
- ctxp->current_bc_label = TREE_CHAIN (label);
- TREE_CHAIN (label) = NULL_TREE;
- return body;
-}
-
-/* Build a GOTO_EXPR to represent a break or continue statement. BC
- indicates which. */
-
-static tree
-build_bc_goto (enum bc_t bc)
-{
- tree label;
- tree target_name = ctxp->bc_id[bc];
-
- /* Look for the appropriate type of label. */
- for (label = ctxp->current_bc_label;
- label;
- label = TREE_CHAIN (label))
- if (DECL_NAME (label) == target_name)
- break;
-
- if (label == NULL_TREE)
- {
- if (bc == bc_break)
- error ("break statement not within loop or switch");
- else
- error ("continue statement not within loop or switch");
-
- return NULL_TREE;
- }
-
- /* Mark the label used for finish_bc_block. */
- TREE_USED (label) = 1;
- return build1 (GOTO_EXPR, void_type_node, label);
-}
-
-/* Build a generic representation of one of the C loop forms. COND is the
- loop condition or NULL_TREE. BODY is the (possibly compound) statement
- controlled by the loop. INCR is the increment expression of a for-loop,
- or NULL_TREE. COND_IS_FIRST indicates whether the condition is
- evaluated before the loop body as in while and for loops, or after the
- loop body as in do-while loops. */
-
-static tree
-gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
-{
- tree top, entry, exit, cont_block, break_block, stmt_list, t;
- location_t stmt_locus;
-
- stmt_locus = input_location;
-
- /* Detect do { ... } while (0) and don't generate loop construct. */
- if (!cond_is_first && cond && integer_zerop (cond))
- top = cond = NULL;
- else
- {
- /* If we use a LOOP_EXPR here, we have to feed the whole thing
- back through the main gimplifier to lower it. Given that we
- have to gimplify the loop body NOW so that we can resolve
- break/continue stmts, seems easier to just expand to gotos. */
- top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
- }
-
- break_block = begin_bc_block (bc_break);
-
- if (top)
- {
- /* If we have an exit condition, then we build an IF with gotos either
- out of the loop, or to the top of it. If there's no exit condition,
- then we just build a jump back to the top. */
- exit = build_and_jump (&LABEL_EXPR_LABEL (top));
- if (cond)
- {
- gimplify_condition (&cond);
- t = build_bc_goto (bc_break);
- exit = build (COND_EXPR, void_type_node, cond, exit, t);
- exit = fold (exit);
- gimplify_stmt (&exit);
- }
- }
- else
- exit = NULL_TREE;
-
- cont_block = begin_bc_block (bc_continue);
-
- gimplify_stmt (&body);
- if (incr && stmts_are_full_exprs_p ())
- incr = fold (build1 (CLEANUP_POINT_EXPR, void_type_node, incr));
- gimplify_stmt (&incr);
-
- body = finish_bc_block (cont_block, body);
-
- stmt_list = NULL;
-
- if (cond_is_first && cond)
- {
- entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
- t = build_and_jump (&LABEL_EXPR_LABEL (entry));
- append_to_statement_list (t, &stmt_list);
- }
- else
- entry = NULL_TREE;
-
- append_to_statement_list (top, &stmt_list);
- append_to_statement_list (body, &stmt_list);
- append_to_statement_list (incr, &stmt_list);
- append_to_statement_list (entry, &stmt_list);
- append_to_statement_list (exit, &stmt_list);
-
- annotate_all_with_locus (&stmt_list, stmt_locus);
-
- return finish_bc_block (break_block, stmt_list);
-}
-
-/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
- prequeue and hand off to gimplify_c_loop. */
-
-static enum gimplify_status
-gimplify_for_stmt (tree *stmt_p, tree *next_p)
-{
- tree stmt = *stmt_p;
- tree init = FOR_INIT_STMT (stmt);
-
- if (init)
- {
- /* Reorganize the statements so that we do the right thing with a
- CLEANUP_STMT. We want the FOR_STMT and nothing else to be in the
- scope of the cleanup, so play with pointers to accomplish that. */
- FOR_INIT_STMT (stmt) = NULL_TREE;
- chainon (init, stmt);
- *stmt_p = init;
- *next_p = TREE_CHAIN (stmt);
- TREE_CHAIN (stmt) = NULL_TREE;
- c_gimplify_stmt (stmt_p);
- }
- else
- *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
- FOR_EXPR (stmt), 1);
-
- return GS_ALL_DONE;
-}
-
-/* Gimplify a WHILE_STMT node. */
-
-static enum gimplify_status
-gimplify_while_stmt (tree *stmt_p)
-{
- tree stmt = *stmt_p;
- *stmt_p = gimplify_c_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
- NULL_TREE, 1);
- return GS_ALL_DONE;
-}
-
-/* Gimplify a DO_STMT node. */
-
-static enum gimplify_status
-gimplify_do_stmt (tree *stmt_p)
-{
- tree stmt = *stmt_p;
- *stmt_p = gimplify_c_loop (DO_COND (stmt), DO_BODY (stmt),
- NULL_TREE, 0);
- return GS_ALL_DONE;
-}
-
-/* Genericize an IF_STMT by turning it into a COND_EXPR. */
-
-static enum gimplify_status
-gimplify_if_stmt (tree *stmt_p)
-{
- tree stmt, then_, else_;
-
- stmt = *stmt_p;
- restart:
- then_ = THEN_CLAUSE (stmt);
- else_ = ELSE_CLAUSE (stmt);
-
- if (!then_)
- then_ = build_empty_stmt ();
- if (!else_)
- else_ = build_empty_stmt ();
-
- stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
- gimplify_condition (& TREE_OPERAND (stmt, 0));
- *stmt_p = stmt;
-
- /* Handle properly nested if-else chains via iteration instead of
- mutual recursion between gimplify.c and c-simplify.c. */
- annotate_with_locus (stmt, input_location);
- if (TREE_CODE (else_) == IF_STMT && !TREE_CHAIN (else_))
- {
- stmt_p = &COND_EXPR_ELSE (stmt);
- stmt = else_;
- prep_stmt (stmt);
- goto restart;
- }
-
- return GS_OK;
-}
-
-/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
-
-static enum gimplify_status
-gimplify_switch_stmt (tree *stmt_p)
-{
- tree stmt = *stmt_p;
- tree break_block, body;
- location_t stmt_locus = input_location;
-
- break_block = begin_bc_block (bc_break);
-
- gimplify_condition (&SWITCH_COND (stmt));
-
- body = SWITCH_BODY (stmt);
- if (!body)
- body = build_empty_stmt ();
-
- *stmt_p = build (SWITCH_EXPR, SWITCH_TYPE (stmt), SWITCH_COND (stmt),
- body, NULL_TREE);
- annotate_with_locus (*stmt_p, stmt_locus);
- gimplify_stmt (stmt_p);
-
- *stmt_p = finish_bc_block (break_block, *stmt_p);
- return GS_ALL_DONE;
-}
-
-/* Genericize a RETURN_STMT by turning it into a RETURN_EXPR. */
-
-static enum gimplify_status
-gimplify_return_stmt (tree *stmt_p)
-{
- tree expr = RETURN_STMT_EXPR (*stmt_p);
- expr = build1 (RETURN_EXPR, void_type_node, expr);
- if (stmts_are_full_exprs_p ())
- expr = build1 (CLEANUP_POINT_EXPR, void_type_node, expr);
- *stmt_p = expr;
- return GS_OK;
-}
-
-/* Gimplifies a DECL_STMT node T.
-
- If a declaration V has an initial value I, create an expression 'V = I'
- and insert it after the DECL_STMT.
-
- PRE_P is a queue for effects that should happen before the DECL_STMT.
-
- MID_P is a queue for effects that should happen after the DECL_STMT,
- but before uses of the initialized decl.
-
- POST_P is a queue for effects that should happen after uses of the
- initialized decl.
-
- Usually these last two will be the same, but they may need to be
- different if the DECL_STMT is somehow embedded in an expression. */
-
-static enum gimplify_status
-gimplify_decl_stmt (tree *stmt_p)
-{
- tree stmt = *stmt_p;
- tree decl = DECL_STMT_DECL (stmt);
- tree pre = NULL_TREE;
- tree post = NULL_TREE;
-
- if (TREE_TYPE (decl) == error_mark_node)
- {
- *stmt_p = NULL;
- return GS_ERROR;
- }
-
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- tree type = TREE_TYPE (decl);
- if (TYPE_SIZE_UNIT (type)
- && !TREE_CONSTANT (TYPE_SIZE_UNIT (type)))
- {
- /* This is a variable-sized array type. Simplify its size. */
- tree temp = TYPE_SIZE_UNIT (type);
- gimplify_expr (&temp, &pre, &post, is_gimple_val, fb_rvalue);
- }
- }
-
- if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
- {
- tree init = DECL_INITIAL (decl);
-
- if (!TREE_CONSTANT (DECL_SIZE (decl)))
- {
- tree pt_type = build_pointer_type (TREE_TYPE (decl));
- tree alloc, size;
-
- /* This is a variable-sized decl. Simplify its size and mark it
- for deferred expansion. Note that mudflap depends on the format
- of the emitted code: see mx_register_decls(). */
-
- size = get_initialized_tmp_var (DECL_SIZE_UNIT (decl), &pre, &post);
- DECL_DEFER_OUTPUT (decl) = 1;
- alloc = build_function_call_expr
- (implicit_built_in_decls[BUILT_IN_STACK_ALLOC],
- tree_cons (NULL_TREE,
- build1 (ADDR_EXPR, pt_type, decl),
- tree_cons (NULL_TREE, size, NULL_TREE)));
- append_to_compound_expr (alloc, &pre);
- }
-
- if (init && init != error_mark_node)
- {
- if (!TREE_STATIC (decl))
- {
- /* Do not warn about int x = x; as it is a GCC extension
- to turn off this warning but only if warn_init_self
- is zero. */
- if (init == decl && !warn_init_self)
- TREE_NO_WARNING (decl) = 1;
-
- DECL_INITIAL (decl) = NULL_TREE;
- init = build (MODIFY_EXPR, void_type_node, decl, init);
- if (stmts_are_full_exprs_p ())
- init = build1 (CLEANUP_POINT_EXPR, void_type_node, init);
- append_to_compound_expr (init, &pre);
- }
- else
- {
- /* We must still examine initializers for static variables
- as they may contain a label address. */
- walk_tree (&init, force_labels_r, NULL, NULL);
- }
- }
-
- /* This decl isn't mentioned in the enclosing block, so add it to the
- list of temps. FIXME it seems a bit of a kludge to say that
- anonymous artificial vars aren't pushed, but everything else is. */
- if (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
- gimple_add_tmp_var (decl);
- }
-
- append_to_compound_expr (post, &pre);
- *stmt_p = pre;
- return GS_OK;
-}
-
-/* Gimplification of expression trees. */
-
-/* Gimplify a C99 compound literal expression. This just means adding the
- DECL_STMT before the current EXPR_STMT and using its anonymous decl
- instead. */
-
-static enum gimplify_status
-gimplify_compound_literal_expr (tree *expr_p)
-{
- tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
- tree decl = DECL_STMT_DECL (decl_s);
-
- /* This decl isn't mentioned in the enclosing block, so add it to the
- list of temps. FIXME it seems a bit of a kludge to say that
- anonymous artificial vars aren't pushed, but everything else is. */
- if (DECL_NAME (decl) == NULL_TREE)
- gimple_add_tmp_var (decl);
-
- gimplify_decl_stmt (&decl_s);
- *expr_p = decl_s ? decl_s : decl;
- return GS_OK;
-}
-
-/* Do C-specific gimplification. Args are as for gimplify_expr. */
-
-int
-c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
- tree *post_p ATTRIBUTE_UNUSED)
-{
- enum tree_code code = TREE_CODE (*expr_p);
-
- if (STATEMENT_CODE_P (code))
- return c_gimplify_stmt (expr_p);
-
- switch (code)
- {
- case COMPOUND_LITERAL_EXPR:
- return gimplify_compound_literal_expr (expr_p);
-
- case STMT_EXPR:
- return gimplify_stmt_expr (expr_p);
-
- default:
- return GS_UNHANDLED;
- }
-}
-
-/* Returns the final EXPR_STMT which represents the return value of a
- STMT_EXPR, or NULL_TREE if none. */
-
-tree
-stmt_expr_last_stmt (tree stmt_expr)
-{
- tree body = STMT_EXPR_STMT (stmt_expr);
- tree last_stmt, substmt;
-
- /* Splice the last expression out of the STMT chain. */
- last_stmt = NULL_TREE;
- for (substmt = COMPOUND_BODY (body); substmt;
- substmt = TREE_CHAIN (substmt))
- if (TREE_CODE (substmt) != SCOPE_STMT)
- last_stmt = substmt;
-
- if (last_stmt == NULL_TREE
- || TREE_CODE (last_stmt) != EXPR_STMT
- || (TREE_TYPE (last_stmt)
- && VOID_TYPE_P (TREE_TYPE (last_stmt))))
- {
- location_t loc;
- if (last_stmt && EXPR_LOCUS (last_stmt))
- loc = *EXPR_LOCUS (last_stmt);
- else if (EXPR_LOCUS (stmt_expr))
- loc = *EXPR_LOCUS (stmt_expr);
- else
- loc = input_location;
- warning ("%Hstatement-expressions should end with a "
- "non-void expression", &loc);
- last_stmt = NULL_TREE;
- }
-
-#if defined ENABLE_CHECKING
- if (last_stmt && !is_last_stmt_of_scope (last_stmt))
- abort ();
-#endif
-
- return last_stmt;
-}
-
-/* Gimplify a STMT_EXPR. EXPR_P points to the expression to gimplify.
- After gimplification, if the STMT_EXPR returns a value, EXPR_P will
- point to a new temporary that holds that value; otherwise it will be
- null.
-
- PRE_P points to the list where side effects that must happen before
- *EXPR_P should be stored. */
-
-static enum gimplify_status
-gimplify_stmt_expr (tree *expr_p)
-{
- tree body = STMT_EXPR_STMT (*expr_p);
-
- if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
- {
- *expr_p = body;
- return c_gimplify_stmt (expr_p);
- }
- else
- {
- tree last_stmt = stmt_expr_last_stmt (*expr_p);
- tree last_expr = NULL_TREE;
-
- if (last_stmt)
- {
- last_expr = EXPR_STMT_EXPR (last_stmt);
-
- if (stmts_are_full_exprs_p ())
- last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr),
- last_expr);
- EXPR_STMT_EXPR (last_stmt) = NULL_TREE;
- }
-
- /* Genericize the block. */
- c_gimplify_stmt (&body);
-
- /* Now retrofit that last expression into the BIND_EXPR. */
- if (last_expr)
- {
- tree *sub_p;
-
- if (!STMT_EXPR_NO_SCOPE (*expr_p))
- {
- /* Our BIND_EXPR will always be hidden within
- a STATEMENT_LIST. Discard that. */
- body = expr_first (body);
- sub_p = &BIND_EXPR_BODY (body);
-
- /* Append the last expression to the end of the BIND_EXPR.
- We'll now re-process this, and let voidify_wrapper_expr
- do its job. */
- append_to_statement_list_force (last_expr, sub_p);
- TREE_TYPE (body) = TREE_TYPE (last_expr);
- }
- else
- append_to_compound_expr (last_expr, &body);
- }
-
- *expr_p = body;
- return GS_OK;
- }
-}
-
-/* Code generation. */
-
-/* Miscellaneous helpers. */
-
-#if defined ENABLE_CHECKING
-/* Return nonzero if STMT is the last statement of its scope. */
-
-static int
-is_last_stmt_of_scope (tree stmt)
-{
- return (TREE_CHAIN (stmt) == NULL_TREE
- || (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
- && SCOPE_END_P (TREE_CHAIN (stmt))));
-}
-#endif
+2004-05-13 Diego Novillo <dnovillo@redhat.com>
+
+ * cp-gimplify.c: Rename from cp-simplify.c.
+ * Make-lang.in, optimize.c: Update.
+
2004-05-13 Diego Novillo <dnovillo@redhat.com>
Merge from tree-ssa-20020619-branch. See
CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \
c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \
c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \
- c-simplify.o tree-inline.o
+ c-gimplify.o tree-inline.o
# Language-specific object files.
CXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
cp/mangle.o cp/cp-lang.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-simplify.o tree-mudflap.o cp/cp-mudflap.o
+ cp/cp-gimplify.o tree-mudflap.o cp/cp-mudflap.o
# Use strict warnings for this front end.
cp-warn = $(STRICT_WARN) $(WERROR)
tree-inline.h cgraph.h
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
- input.h $(PARAMS_H) debug.h tree-inline.h tree-simple.h
+ input.h $(PARAMS_H) debug.h tree-inline.h tree-gimple.h
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \
$(TARGET_H) $(TM_P_H)
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) diagnostic.h gt-cp-parser.h \
output.h
-cp/cp-simplify.o: cp/cp-simplify.c $(CXX_TREE_H) toplev.h c-common.h \
+cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) toplev.h c-common.h \
$(TM_H) coretypes.h
cp/cp-mudflap.o: cp/cp-mudflap.c $(CXX_TREE_H) toplev.h c-common.h \
$(TM_H) coretypes.h
--- /dev/null
+/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
+
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Jason Merrill <jason@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "cp-tree.h"
+#include "c-common.h"
+#include "toplev.h"
+#include "tree-gimple.h"
+
+static void genericize_try_block (tree *);
+static void genericize_catch_block (tree *);
+static void genericize_eh_spec_block (tree *);
+static void gimplify_must_not_throw_expr (tree *, tree *);
+static void cp_gimplify_init_expr (tree *, tree *, tree *);
+
+/* Genericize a C++ _STMT. Called from c_gimplify_stmt. */
+
+int
+cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
+{
+ tree stmt = *stmt_p;
+ switch (TREE_CODE (stmt))
+ {
+ case TRY_BLOCK:
+ genericize_try_block (stmt_p);
+ return 1;
+
+ case HANDLER:
+ genericize_catch_block (stmt_p);
+ return 1;
+
+ case EH_SPEC_BLOCK:
+ genericize_eh_spec_block (stmt_p);
+ return 1;
+
+ case USING_STMT:
+ /* Just ignore for now. Eventually we will want to pass this on to
+ the debugger. */
+ *stmt_p = build_empty_stmt ();
+ return 1;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+/* Genericize a TRY_BLOCK. */
+
+static void
+genericize_try_block (tree *stmt_p)
+{
+ tree body = TRY_STMTS (*stmt_p);
+ tree cleanup = TRY_HANDLERS (*stmt_p);
+
+ c_gimplify_stmt (&body);
+
+ if (CLEANUP_P (*stmt_p))
+ /* A cleanup is an expression, so it doesn't need to be genericized. */;
+ else
+ c_gimplify_stmt (&cleanup);
+
+ *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
+}
+
+/* Genericize a HANDLER by converting to a CATCH_EXPR. */
+
+static void
+genericize_catch_block (tree *stmt_p)
+{
+ tree type = HANDLER_TYPE (*stmt_p);
+ tree body = HANDLER_BODY (*stmt_p);
+
+ c_gimplify_stmt (&body);
+
+ /* FIXME should the caught type go in TREE_TYPE? */
+ *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
+}
+
+/* Genericize an EH_SPEC_BLOCK by converting it to a
+ TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
+
+static void
+genericize_eh_spec_block (tree *stmt_p)
+{
+ tree body = EH_SPEC_STMTS (*stmt_p);
+ tree allowed = EH_SPEC_RAISES (*stmt_p);
+ tree failure = build_call (call_unexpected_node,
+ tree_cons (NULL_TREE, build_exc_ptr (),
+ NULL_TREE));
+ c_gimplify_stmt (&body);
+
+ *stmt_p = gimple_build_eh_filter (body, allowed, failure);
+}
+
+/* Do C++-specific gimplification. Args are as for gimplify_expr. */
+
+int
+cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
+{
+ switch (TREE_CODE (*expr_p))
+ {
+ case PTRMEM_CST:
+ *expr_p = cplus_expand_constant (*expr_p);
+ return GS_OK;
+
+ case AGGR_INIT_EXPR:
+ simplify_aggr_init_expr (expr_p);
+ return GS_OK;
+
+ case THROW_EXPR:
+ /* FIXME communicate throw type to backend, probably by moving
+ THROW_EXPR into ../tree.def. */
+ *expr_p = TREE_OPERAND (*expr_p, 0);
+ return GS_OK;
+
+ case MUST_NOT_THROW_EXPR:
+ gimplify_must_not_throw_expr (expr_p, pre_p);
+ return GS_OK;
+
+ case INIT_EXPR:
+ case MODIFY_EXPR:
+ cp_gimplify_init_expr (expr_p, pre_p, post_p);
+ return GS_OK;
+
+ case EMPTY_CLASS_EXPR:
+ {
+ /* Yes, an INTEGER_CST with RECORD_TYPE. */
+ tree i = build_int_2 (0, 0);
+ TREE_TYPE (i) = TREE_TYPE (*expr_p);
+ *expr_p = i;
+ }
+ return GS_OK;
+
+ case BASELINK:
+ *expr_p = BASELINK_FUNCTIONS (*expr_p);
+ return GS_OK;
+
+ default:
+ return c_gimplify_expr (expr_p, pre_p, post_p);
+ }
+}
+
+/* Gimplify initialization from an AGGR_INIT_EXPR. */
+
+static void
+cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
+{
+ tree from = TREE_OPERAND (*expr_p, 1);
+ tree to = TREE_OPERAND (*expr_p, 0);
+ tree sub;
+
+ /* If we are initializing something from a TARGET_EXPR, strip the
+ TARGET_EXPR and initialize it directly. */
+ /* What about code that pulls out the temp and uses it elsewhere? I
+ think that such code never uses the TARGET_EXPR as an initializer. If
+ I'm wrong, we'll abort because the temp won't have any RTL. In that
+ case, I guess we'll need to replace references somehow. */
+ if (TREE_CODE (from) == TARGET_EXPR)
+ from = TARGET_EXPR_INITIAL (from);
+
+ sub = from;
+
+ /* If we are initializing from a STMT_EXPR, extract the returned
+ expression. */
+ if (TREE_CODE (from) == STMT_EXPR)
+ sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
+
+ /* Look through any COMPOUND_EXPRs. */
+ while (TREE_CODE (sub) == COMPOUND_EXPR)
+ sub = TREE_OPERAND (sub, 1);
+
+ /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
+ replace the slot operand with our target.
+
+ Should we add a target parm to gimplify_expr instead? No, as in this
+ case we want to replace the INIT_EXPR. */
+ if (TREE_CODE (sub) == AGGR_INIT_EXPR)
+ {
+ gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
+ TREE_OPERAND (sub, 2) = to;
+ *expr_p = from;
+
+ /* The initialization is now a side-effect, so the container can
+ become void. This is important for a STMT_EXPR, so we don't try
+ to voidify it later by creating a temporary. */
+ if (from != sub)
+ TREE_TYPE (from) = void_type_node;
+ }
+}
+
+/* Gimplify a MUST_NOT_THROW_EXPR. */
+
+static void
+gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
+{
+ tree stmt = *expr_p;
+ tree temp = voidify_wrapper_expr (stmt);
+ tree body = TREE_OPERAND (stmt, 0);
+
+ gimplify_stmt (&body);
+
+ stmt = gimple_build_eh_filter (body, NULL_TREE,
+ build_call (terminate_node, NULL_TREE));
+
+ if (temp)
+ {
+ append_to_statement_list (stmt, pre_p);
+ *expr_p = temp;
+ }
+ else
+ *expr_p = stmt;
+}
+++ /dev/null
-/* C++-specific tree lowering bits; see also c-simplify.c and tree-simple.c.
-
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- Contributed by Jason Merrill <jason@redhat.com>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "cp-tree.h"
-#include "c-common.h"
-#include "toplev.h"
-#include "tree-simple.h"
-
-static void genericize_try_block (tree *);
-static void genericize_catch_block (tree *);
-static void genericize_eh_spec_block (tree *);
-static void gimplify_must_not_throw_expr (tree *, tree *);
-static void cp_gimplify_init_expr (tree *, tree *, tree *);
-
-/* Genericize a C++ _STMT. Called from c_gimplify_stmt. */
-
-int
-cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
-{
- tree stmt = *stmt_p;
- switch (TREE_CODE (stmt))
- {
- case TRY_BLOCK:
- genericize_try_block (stmt_p);
- return 1;
-
- case HANDLER:
- genericize_catch_block (stmt_p);
- return 1;
-
- case EH_SPEC_BLOCK:
- genericize_eh_spec_block (stmt_p);
- return 1;
-
- case USING_STMT:
- /* Just ignore for now. Eventually we will want to pass this on to
- the debugger. */
- *stmt_p = build_empty_stmt ();
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Genericize a TRY_BLOCK. */
-
-static void
-genericize_try_block (tree *stmt_p)
-{
- tree body = TRY_STMTS (*stmt_p);
- tree cleanup = TRY_HANDLERS (*stmt_p);
-
- c_gimplify_stmt (&body);
-
- if (CLEANUP_P (*stmt_p))
- /* A cleanup is an expression, so it doesn't need to be genericized. */;
- else
- c_gimplify_stmt (&cleanup);
-
- *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
-}
-
-/* Genericize a HANDLER by converting to a CATCH_EXPR. */
-
-static void
-genericize_catch_block (tree *stmt_p)
-{
- tree type = HANDLER_TYPE (*stmt_p);
- tree body = HANDLER_BODY (*stmt_p);
-
- c_gimplify_stmt (&body);
-
- /* FIXME should the caught type go in TREE_TYPE? */
- *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
-}
-
-/* Genericize an EH_SPEC_BLOCK by converting it to a
- TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
-
-static void
-genericize_eh_spec_block (tree *stmt_p)
-{
- tree body = EH_SPEC_STMTS (*stmt_p);
- tree allowed = EH_SPEC_RAISES (*stmt_p);
- tree failure = build_call (call_unexpected_node,
- tree_cons (NULL_TREE, build_exc_ptr (),
- NULL_TREE));
- c_gimplify_stmt (&body);
-
- *stmt_p = gimple_build_eh_filter (body, allowed, failure);
-}
-
-/* Do C++-specific gimplification. Args are as for gimplify_expr. */
-
-int
-cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
-{
- switch (TREE_CODE (*expr_p))
- {
- case PTRMEM_CST:
- *expr_p = cplus_expand_constant (*expr_p);
- return GS_OK;
-
- case AGGR_INIT_EXPR:
- simplify_aggr_init_expr (expr_p);
- return GS_OK;
-
- case THROW_EXPR:
- /* FIXME communicate throw type to backend, probably by moving
- THROW_EXPR into ../tree.def. */
- *expr_p = TREE_OPERAND (*expr_p, 0);
- return GS_OK;
-
- case MUST_NOT_THROW_EXPR:
- gimplify_must_not_throw_expr (expr_p, pre_p);
- return GS_OK;
-
- case INIT_EXPR:
- case MODIFY_EXPR:
- cp_gimplify_init_expr (expr_p, pre_p, post_p);
- return GS_OK;
-
- case EMPTY_CLASS_EXPR:
- {
- /* Yes, an INTEGER_CST with RECORD_TYPE. */
- tree i = build_int_2 (0, 0);
- TREE_TYPE (i) = TREE_TYPE (*expr_p);
- *expr_p = i;
- }
- return GS_OK;
-
- case BASELINK:
- *expr_p = BASELINK_FUNCTIONS (*expr_p);
- return GS_OK;
-
- default:
- return c_gimplify_expr (expr_p, pre_p, post_p);
- }
-}
-
-/* Gimplify initialization from an AGGR_INIT_EXPR. */
-
-static void
-cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
-{
- tree from = TREE_OPERAND (*expr_p, 1);
- tree to = TREE_OPERAND (*expr_p, 0);
- tree sub;
-
- /* If we are initializing something from a TARGET_EXPR, strip the
- TARGET_EXPR and initialize it directly. */
- /* What about code that pulls out the temp and uses it elsewhere? I
- think that such code never uses the TARGET_EXPR as an initializer. If
- I'm wrong, we'll abort because the temp won't have any RTL. In that
- case, I guess we'll need to replace references somehow. */
- if (TREE_CODE (from) == TARGET_EXPR)
- from = TARGET_EXPR_INITIAL (from);
-
- sub = from;
-
- /* If we are initializing from a STMT_EXPR, extract the returned
- expression. */
- if (TREE_CODE (from) == STMT_EXPR)
- sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
-
- /* Look through any COMPOUND_EXPRs. */
- while (TREE_CODE (sub) == COMPOUND_EXPR)
- sub = TREE_OPERAND (sub, 1);
-
- /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
- replace the slot operand with our target.
-
- Should we add a target parm to gimplify_expr instead? No, as in this
- case we want to replace the INIT_EXPR. */
- if (TREE_CODE (sub) == AGGR_INIT_EXPR)
- {
- gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
- TREE_OPERAND (sub, 2) = to;
- *expr_p = from;
-
- /* The initialization is now a side-effect, so the container can
- become void. This is important for a STMT_EXPR, so we don't try
- to voidify it later by creating a temporary. */
- if (from != sub)
- TREE_TYPE (from) = void_type_node;
- }
-}
-
-/* Gimplify a MUST_NOT_THROW_EXPR. */
-
-static void
-gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
-{
- tree stmt = *expr_p;
- tree temp = voidify_wrapper_expr (stmt);
- tree body = TREE_OPERAND (stmt, 0);
-
- gimplify_stmt (&body);
-
- stmt = gimple_build_eh_filter (body, NULL_TREE,
- build_call (terminate_node, NULL_TREE));
-
- if (temp)
- {
- append_to_statement_list (stmt, pre_p);
- *expr_p = temp;
- }
- else
- *expr_p = stmt;
-}
#include "langhooks.h"
#include "diagnostic.h"
#include "tree-dump.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
/* Prototypes. */
+2004-05-13 Diego Novillo <dnovillo@redhat.com>
+
+ * Make-lang.in, f95-lang.c, trans-array.c, trans-decl.c,
+ trans-expr.c, trans-intrinsic.c, trans-io.c, trans-stmt.c,
+ trans.c: Rename tree-simple.[ch] to tree-gimple.[ch].
+
2004-05-13 Victor Leikehman <lei@haifasphere.co.il>
PR fortran/15314
# We rely on c-semantics to expand from GIMPLE to RTL.
# This should go away once a real GIMPLE expander is available.
F95_ADDITIONAL_OBJS = \
- tree-cfg.o tree-dfa.o tree-optimize.o tree-simple.o \
+ tree-cfg.o tree-dfa.o tree-optimize.o tree-gimple.o \
tree-ssa.o tree-ssa-ccp.o tree-ssa-dce.o \
tree-alias-common.o tree-alias-type.o gimplify.o stor-layout.o
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "flags.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include <stdio.h>
#include "ggc.h"
#include "toplev.h"
#include "coretypes.h"
#include "tree.h"
#include "tree-dump.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "ggc.h"
#include "toplev.h"
#include "tm.h"
#include "ggc.h"
#include "toplev.h"
#include "real.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "flags.h"
#include <gmp.h>
#include <assert.h>
/* TRUTH_NOT_EXPR is not a "true" unary operator in GCC.
We must convert it to a compare to 0 (e.g. EQ_EXPR (op1, 0)).
- All other unary operators have an equivalent SIMPLE unary operator */
+ All other unary operators have an equivalent GIMPLE unary operator */
if (code == TRUTH_NOT_EXPR)
se->expr = build (EQ_EXPR, type, operand.expr, integer_zero_node);
else
break;
/* EQV and NEQV only work on logicals, but since we represent them
- as integers, we can use EQ_EXPR and NE_EXPR for them in SIMPLE. */
+ as integers, we can use EQ_EXPR and NE_EXPR for them in GIMPLE. */
case INTRINSIC_EQ:
case INTRINSIC_EQV:
code = EQ_EXPR;
#include "ggc.h"
#include "toplev.h"
#include "real.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "flags.h"
#include <gmp.h>
#include <assert.h>
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include <stdio.h>
#include "ggc.h"
#include "toplev.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include <stdio.h>
#include "ggc.h"
#include "toplev.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include <stdio.h>
#include "ggc.h"
#include "toplev.h"
gfc_start_block (&block);
- /* Translate statements one by one to SIMPLE trees until we reach
+ /* Translate statements one by one to GIMPLE trees until we reach
the end of this gfc_code branch. */
for (; code; code = code->next)
{
#include "rtl.h"
#include "errors.h"
#include "varray.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "rtl.h"
#include "errors.h"
#include "varray.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "langhooks.h"
GIMPLE_TEST_F points to a function that takes a tree T and
returns nonzero if T is in the GIMPLE form requested by the
- caller. The GIMPLE predicates are in tree-simple.c.
+ caller. The GIMPLE predicates are in tree-gimple.c.
This test is used twice. Before gimplification, the test is
invoked to determine whether *EXPR_P is already gimple enough. If
+2004-05-13 Diego Novillo <dnovillo@redhat.com>
+
+ * Make-lang.in, expr.c, java-gimplify.c: Rename
+ tree-simple.[ch] to tree-gimple.[ch].
+
2004-05-14 Ranjit Mathew <rmathew@hotmail.com>
* java-gimplify.c (java_gimplify_expr): Correct minor typos.
java/zextract.o: java/zextract.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
java/zipfile.h
java/java-gimplify.o: java/java-gimplify.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(JAVA_TREE_H) tree-simple.h toplev.h
+ coretypes.h $(TM_H) $(JAVA_TREE_H) tree-gimple.h toplev.h
java/parse-scan.o: java/parse-scan.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) toplev.h $(JAVA_LEX_C) java/parse.h java/lex.h input.h
#include "toplev.h"
#include "except.h"
#include "ggc.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "target.h"
static void flush_quick_stack (void);
#include "tree.h"
#include "java-tree.h"
#include "tree-dump.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "toplev.h"
static tree java_gimplify_case_expr (tree);
#include "toplev.h"
#include "tree.h"
#include "tree-inline.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "rtl.h"
#include "insn-config.h"
#include "integrate.h"
#include "tree-flow.h"
#include "tree-inline.h"
#include "varray.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "splay-tree.h"
#include "engine/util.h"
#include "libcompat/regions.h"
#include "tree-inline.h"
#include "varray.h"
#include "c-tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "hashtab.h"
#include "function.h"
#include "cgraph.h"
#include "tree.h"
#include "tm.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-iterator.h"
#include "tree-pass.h"
#include "flags.h"
#include "function.h"
#include "diagnostic.h"
#include "tree-dump.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-flow.h"
#include "tree-inline.h"
#include "tree-alias-common.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "hashtab.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-ssa-operands.h"
/* Forward declare structures for the garbage collector GTY markers. */
--- /dev/null
+/* Functions to analyze and validate GIMPLE trees.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Diego Novillo <dnovillo@redhat.com>
+ Rewritten by Jason Merrill <jason@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "ggc.h"
+#include "tm.h"
+#include "tree.h"
+#include "tree-gimple.h"
+#include "output.h"
+#include "rtl.h"
+#include "expr.h"
+#include "bitmap.h"
+
+/* GCC GIMPLE structure
+
+ Inspired by the SIMPLE C grammar at
+
+ http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
+
+ function:
+ FUNCTION_DECL
+ DECL_SAVED_TREE -> block
+ block:
+ BIND_EXPR
+ BIND_EXPR_VARS -> DECL chain
+ BIND_EXPR_BLOCK -> BLOCK
+ BIND_EXPR_BODY -> compound-stmt
+ compound-stmt:
+ COMPOUND_EXPR
+ op0 -> non-compound-stmt
+ op1 -> stmt
+ | EXPR_VEC
+ (or other alternate solution)
+ stmt: compound-stmt | non-compound-stmt
+ non-compound-stmt:
+ block
+ | if-stmt
+ | switch-stmt
+ | jump-stmt
+ | label-stmt
+ | try-stmt
+ | modify-stmt
+ | call-stmt
+ if-stmt:
+ COND_EXPR
+ op0 -> condition
+ op1 -> stmt
+ op2 -> stmt
+ switch-stmt:
+ SWITCH_EXPR
+ op0 -> val
+ op1 -> stmt
+ op2 -> array of case labels (as LABEL_DECLs?)
+ FIXME: add case value info
+ jump-stmt:
+ GOTO_EXPR
+ op0 -> LABEL_DECL | '*' ID
+ | RETURN_EXPR
+ op0 -> modify-stmt | NULL_TREE
+ (maybe -> RESULT_DECL | NULL_TREE? seems like some of expand_return
+ depends on getting a MODIFY_EXPR.)
+ | THROW_EXPR? do we need/want such a thing for opts, perhaps
+ to generate an ERT_THROW region? I think so.
+ Hmm...this would only work at the GIMPLE level, where we know that
+ the call args don't have any EH impact. Perhaps
+ annotation of the CALL_EXPR would work better.
+ | RESX_EXPR
+ label-stmt:
+ LABEL_EXPR
+ op0 -> LABEL_DECL
+ | CASE_LABEL_EXPR
+ CASE_LOW -> val | NULL_TREE
+ CASE_HIGH -> val | NULL_TREE
+ CASE_LABEL -> LABEL_DECL FIXME
+ try-stmt:
+ TRY_CATCH_EXPR
+ op0 -> stmt
+ op1 -> handler
+ | TRY_FINALLY_EXPR
+ op0 -> stmt
+ op1 -> stmt
+ handler:
+ catch-seq
+ | EH_FILTER_EXPR
+ | stmt
+ modify-stmt:
+ MODIFY_EXPR
+ op0 -> lhs
+ op1 -> rhs
+ call-stmt: CALL_EXPR
+ op0 -> ID | '&' ID
+ op1 -> arglist
+
+ addr-expr-arg : compref | ID
+ lhs: addr-expr-arg | '*' ID | bitfieldref
+ min-lval: ID | '*' ID
+ bitfieldref :
+ BIT_FIELD_REF
+ op0 -> compref | min-lval
+ op1 -> CONST
+ op2 -> CONST
+ compref :
+ COMPONENT_REF
+ op0 -> compref | min-lval
+ | ARRAY_REF
+ op0 -> compref | min-lval
+ op1 -> val
+ | REALPART_EXPR
+ | IMAGPART_EXPR
+
+ condition : val | val relop val
+ val : ID | CONST
+
+ rhs : varname | CONST
+ | '*' ID
+ | '&' addr-expr-arg
+ | call_expr
+ | unop val
+ | val binop val
+ | '(' cast ')' val
+
+ (cast here stands for all valid C typecasts)
+
+ unop
+ : '+'
+ | '-'
+ | '!'
+ | '~'
+
+ binop
+ : relop | '-'
+ | '+'
+ | '/'
+ | '*'
+ | '%'
+ | '&'
+ | '|'
+ | '<<'
+ | '>>'
+ | '^'
+
+ relop
+ : '<'
+ | '<='
+ | '>'
+ | '>='
+ | '=='
+ | '!='
+
+*/
+
+static inline bool is_gimple_id (tree);
+
+/* Validation of GIMPLE expressions. */
+
+/* Return nonzero if T is a GIMPLE RHS:
+
+ rhs : varname | CONST
+ | '*' ID
+ | '&' varname_or_temp
+ | call_expr
+ | unop val
+ | val binop val
+ | '(' cast ')' val
+ | <CONSTRUCTOR <gimple_val ...>>
+
+ The last option is only valid GIMPLE for vector and complex types;
+ aggregate types should have their constructors decomposed. */
+
+bool
+is_gimple_rhs (tree t)
+{
+ enum tree_code code = TREE_CODE (t);
+
+ switch (TREE_CODE_CLASS (code))
+ {
+ case '1':
+ case '2':
+ case '<':
+ return 1;
+
+ default:
+ break;
+ }
+
+ switch (code)
+ {
+ case TRUTH_NOT_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ case ADDR_EXPR:
+ case CALL_EXPR:
+ case CONSTRUCTOR:
+ case COMPLEX_EXPR:
+ /* FIXME lower VA_ARG_EXPR. */
+ case VA_ARG_EXPR:
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ return 1;
+
+ default:
+ break;
+ }
+
+ if (is_gimple_lvalue (t) || is_gimple_val (t))
+ return 1;
+
+ return 0;
+}
+
+/* Returns nonzero if T is a valid CONSTRUCTOR component in GIMPLE, either
+ a val or another CONSTRUCTOR. */
+
+bool
+is_gimple_constructor_elt (tree t)
+{
+ return (is_gimple_val (t)
+ || TREE_CODE (t) == CONSTRUCTOR);
+}
+
+/* Return nonzero if T is a valid LHS for a GIMPLE assignment expression. */
+
+bool
+is_gimple_lvalue (tree t)
+{
+ return (is_gimple_addr_expr_arg (t)
+ || TREE_CODE (t) == INDIRECT_REF
+ /* These are complex lvalues, but don't have addresses, so they
+ go here. */
+ || TREE_CODE (t) == BIT_FIELD_REF);
+}
+
+
+/* Return nonzero if T is a GIMPLE condition:
+
+ condexpr
+ : val
+ | val relop val */
+
+bool
+is_gimple_condexpr (tree t)
+{
+ return (is_gimple_val (t)
+ || TREE_CODE_CLASS (TREE_CODE (t)) == '<');
+}
+
+
+/* Return nonzero if T is a valid operand for '&':
+
+ varname
+ : arrayref
+ | compref
+ | ID */
+
+bool
+is_gimple_addr_expr_arg (tree t)
+{
+ return (is_gimple_id (t)
+ || TREE_CODE (t) == ARRAY_REF
+ || TREE_CODE (t) == COMPONENT_REF
+ || TREE_CODE (t) == REALPART_EXPR
+ || TREE_CODE (t) == IMAGPART_EXPR);
+}
+
+/* Return nonzero if T is function invariant. Or rather a restricted
+ form of function invariant. */
+
+bool
+is_gimple_min_invariant (tree t)
+{
+ switch (TREE_CODE (t))
+ {
+ case ADDR_EXPR:
+ return TREE_INVARIANT (t);
+
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case COMPLEX_CST:
+ case VECTOR_CST:
+ return !TREE_OVERFLOW (t);
+
+ default:
+ return false;
+ }
+}
+
+/* Return nonzero if T looks like a valid GIMPLE statement. */
+
+bool
+is_gimple_stmt (tree t)
+{
+ enum tree_code code = TREE_CODE (t);
+
+ if (IS_EMPTY_STMT (t))
+ return 1;
+
+ switch (code)
+ {
+ case BIND_EXPR:
+ case COND_EXPR:
+ /* These are only valid if they're void. */
+ return VOID_TYPE_P (TREE_TYPE (t));
+
+ case SWITCH_EXPR:
+ case GOTO_EXPR:
+ case RETURN_EXPR:
+ case LABEL_EXPR:
+ case CASE_LABEL_EXPR:
+ case TRY_CATCH_EXPR:
+ case TRY_FINALLY_EXPR:
+ case EH_FILTER_EXPR:
+ case CATCH_EXPR:
+ case ASM_EXPR:
+ case RESX_EXPR:
+ case PHI_NODE:
+ case STATEMENT_LIST:
+ /* These are always void. */
+ return 1;
+
+ case VA_ARG_EXPR:
+ /* FIXME this should be lowered. */
+ return 1;
+
+ case COMPOUND_EXPR:
+ /* FIXME should we work harder to make COMPOUND_EXPRs void? */
+ case CALL_EXPR:
+ case MODIFY_EXPR:
+ /* These are valid regardless of their type. */
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Return nonzero if T is a variable. */
+
+bool
+is_gimple_variable (tree t)
+{
+ return (TREE_CODE (t) == VAR_DECL
+ || TREE_CODE (t) == PARM_DECL
+ || TREE_CODE (t) == RESULT_DECL
+ || TREE_CODE (t) == SSA_NAME);
+}
+
+/* Return nonzero if T is a GIMPLE identifier (something with an address). */
+
+static inline bool
+is_gimple_id (tree t)
+{
+ return (is_gimple_variable (t)
+ || TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == LABEL_DECL
+ /* Allow string constants, since they are addressable. */
+ || TREE_CODE (t) == STRING_CST);
+}
+
+/* Return nonzero if TYPE is a suitable type for a scalar register
+ variable. */
+
+bool
+is_gimple_reg_type (tree type)
+{
+ return (!AGGREGATE_TYPE_P (type)
+ && TREE_CODE (type) != COMPLEX_TYPE);
+}
+
+
+/* Return nonzero if T is a scalar register variable. */
+
+bool
+is_gimple_reg (tree t)
+{
+ if (TREE_CODE (t) == SSA_NAME)
+ t = SSA_NAME_VAR (t);
+
+ return (is_gimple_variable (t)
+ && is_gimple_reg_type (TREE_TYPE (t))
+ /* A volatile decl is not acceptable because we can't reuse it as
+ needed. We need to copy it into a temp first. */
+ && ! TREE_THIS_VOLATILE (t)
+ && ! TREE_ADDRESSABLE (t)
+ && ! needs_to_live_in_memory (t));
+}
+
+/* Return nonzero if T is a GIMPLE variable whose address is not needed. */
+
+bool
+is_gimple_non_addressable (tree t)
+{
+ if (TREE_CODE (t) == SSA_NAME)
+ t = SSA_NAME_VAR (t);
+
+ return (is_gimple_variable (t)
+ && ! TREE_ADDRESSABLE (t)
+ && ! needs_to_live_in_memory (t));
+}
+
+/* Return nonzero if T is a GIMPLE rvalue, i.e. an identifier or a
+ constant. */
+
+bool
+is_gimple_val (tree t)
+{
+ /* Make loads from volatiles and memory vars explicit. */
+ if (is_gimple_variable (t)
+ && is_gimple_reg_type (TREE_TYPE (t))
+ && !is_gimple_reg (t))
+ return 0;
+
+ /* FIXME make these decls. That can happen only when we expose the
+ entire landing-pad construct at the tree level. */
+ if (TREE_CODE (t) == EXC_PTR_EXPR || TREE_CODE (t) == FILTER_EXPR)
+ return 1;
+
+ return (is_gimple_variable (t) || is_gimple_min_invariant (t));
+}
+
+
+/* Return true if T is a GIMPLE minimal lvalue, of the form
+
+ min_lval: ID | '(' '*' ID ')'
+
+ This never actually appears in the original SIMPLE grammar, but is
+ repeated in several places. */
+
+bool
+is_gimple_min_lval (tree t)
+{
+ return (is_gimple_id (t)
+ || TREE_CODE (t) == INDIRECT_REF);
+}
+
+/* Return nonzero if T is a typecast operation of the form
+ '(' cast ')' val. */
+
+bool
+is_gimple_cast (tree t)
+{
+ return (TREE_CODE (t) == NOP_EXPR
+ || TREE_CODE (t) == CONVERT_EXPR
+ || TREE_CODE (t) == FIX_TRUNC_EXPR
+ || TREE_CODE (t) == FIX_CEIL_EXPR
+ || TREE_CODE (t) == FIX_FLOOR_EXPR
+ || TREE_CODE (t) == FIX_ROUND_EXPR);
+}
+
+
+/* If T makes a function call, return the corresponding CALL_EXPR operand.
+ Otherwise, return NULL_TREE. */
+
+tree
+get_call_expr_in (tree t)
+{
+ if (TREE_CODE (t) == CALL_EXPR)
+ return t;
+ else if (TREE_CODE (t) == MODIFY_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
+ return TREE_OPERAND (t, 1);
+ else if (TREE_CODE (t) == RETURN_EXPR
+ && TREE_OPERAND (t, 0)
+ && TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
+ && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == CALL_EXPR)
+ return TREE_OPERAND (TREE_OPERAND (t, 0), 1);
+
+ return NULL_TREE;
+}
+
+
+/* Given an _EXPR TOP, reorganize all of the nested _EXPRs with the same
+ code so that they only appear as the second operand. This should only
+ be used for tree codes which are truly associative, such as
+ COMPOUND_EXPR and TRUTH_ANDIF_EXPR. Arithmetic is not associative
+ enough, due to the limited precision of arithmetic data types.
+
+ This transformation is conservative; the operand 0 of a matching tree
+ node will only change if it is also a matching node. */
+
+tree
+right_assocify_expr (tree top)
+{
+ tree *p = ⊤
+ enum tree_code code = TREE_CODE (*p);
+ while (TREE_CODE (*p) == code)
+ {
+ tree cur = *p;
+ tree lhs = TREE_OPERAND (cur, 0);
+ if (TREE_CODE (lhs) == code)
+ {
+ /* There's a left-recursion. If we have ((a, (b, c)), d), we
+ want to rearrange to (a, (b, (c, d))). */
+ tree *q;
+
+ /* Replace cur with the lhs; move (a, *) up. */
+ *p = lhs;
+
+ if (code == COMPOUND_EXPR)
+ {
+ /* We need to give (b, c) the type of c; previously lhs had
+ the type of b. */
+ TREE_TYPE (lhs) = TREE_TYPE (cur);
+ if (TREE_SIDE_EFFECTS (cur))
+ TREE_SIDE_EFFECTS (lhs) = 1;
+ }
+
+ /* Walk through the op1 chain from there until we find something
+ with a different code. In this case, c. */
+ for (q = &TREE_OPERAND (lhs, 1); TREE_CODE (*q) == code;
+ q = &TREE_OPERAND (*q, 1))
+ TREE_TYPE (*q) = TREE_TYPE (cur);
+
+ /* Change (*, d) into (c, d). */
+ TREE_OPERAND (cur, 0) = *q;
+
+ /* And plug it in where c used to be. */
+ *q = cur;
+ }
+ else
+ p = &TREE_OPERAND (cur, 1);
+ }
+ return top;
+}
+
+/* Normalize the statement TOP. If it is a COMPOUND_EXPR, reorganize it so
+ that we can traverse it without recursion. If it is null, replace it
+ with a nop. */
+
+tree
+rationalize_compound_expr (tree top)
+{
+ if (top == NULL_TREE)
+ top = build_empty_stmt ();
+ else if (TREE_CODE (top) == COMPOUND_EXPR)
+ top = right_assocify_expr (top);
+
+ return top;
+}
+
+/* Given a memory reference expression, return the base address. Note that,
+ in contrast with get_base_var, this will not recurse inside INDIRECT_REF
+ expressions. Therefore, given the reference PTR->FIELD, this function
+ will return *PTR. Whereas get_base_var would've returned PTR. */
+
+tree
+get_base_address (tree t)
+{
+ do
+ {
+ if (SSA_VAR_P (t)
+ || TREE_CODE (t) == INDIRECT_REF)
+ return t;
+
+ switch (TREE_CODE (t))
+ {
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case BIT_FIELD_REF:
+ t = TREE_OPERAND (t, 0);
+ break;
+
+ default:
+ return NULL_TREE;
+ }
+ }
+ while (t);
+
+ return t;
+}
+
+
+void
+recalculate_side_effects (tree t)
+{
+ enum tree_code code = TREE_CODE (t);
+ int fro = first_rtl_op (code);
+ int i;
+
+ switch (TREE_CODE_CLASS (code))
+ {
+ case 'e':
+ switch (code)
+ {
+ case INIT_EXPR:
+ case MODIFY_EXPR:
+ case VA_ARG_EXPR:
+ case RTL_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ /* All of these have side-effects, no matter what their
+ operands are. */
+ return;
+
+ default:
+ break;
+ }
+ /* Fall through. */
+
+ case '<': /* a comparison expression */
+ case '1': /* a unary arithmetic expression */
+ case '2': /* a binary arithmetic expression */
+ case 'r': /* a reference */
+ TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
+ for (i = 0; i < fro; ++i)
+ {
+ tree op = TREE_OPERAND (t, i);
+ if (op && TREE_SIDE_EFFECTS (op))
+ TREE_SIDE_EFFECTS (t) = 1;
+ }
+ break;
+ }
+}
--- /dev/null
+/* Functions to analyze and validate GIMPLE trees.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Diego Novillo <dnovillo@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#ifndef _TREE_SIMPLE_H
+#define _TREE_SIMPLE_H 1
+
+
+#include "tree-iterator.h"
+
+extern tree create_tmp_var_raw (tree, const char *);
+extern tree create_tmp_var (tree, const char *);
+extern bool is_gimple_tmp_var (tree);
+extern tree get_initialized_tmp_var (tree, tree *, tree *);
+extern tree get_formal_tmp_var (tree, tree *);
+extern void declare_tmp_vars (tree, tree);
+
+extern tree rationalize_compound_expr (tree);
+extern tree right_assocify_expr (tree);
+extern void annotate_all_with_locus (tree *, location_t);
+
+/* Validation of GIMPLE expressions. Note that these predicates only check
+ the basic form of the expression, they don't recurse to make sure that
+ underlying nodes are also of the right form. */
+
+/* Returns true iff T is a valid GIMPLE statement. */
+bool is_gimple_stmt (tree);
+
+/* Returns true iff TYPE is a valid type for a scalar register variable. */
+bool is_gimple_reg_type (tree);
+/* Returns true iff T is a scalar register variable. */
+bool is_gimple_reg (tree);
+/* Returns true iff T is any sort of variable. */
+bool is_gimple_variable (tree);
+/* Returns true iff T is a variable or an INDIRECT_REF (of a variable). */
+bool is_gimple_min_lval (tree);
+/* Returns true iff T is an lvalue other than an INDIRECT_REF. */
+bool is_gimple_addr_expr_arg (tree);
+/* Returns true iff T is any valid GIMPLE lvalue. */
+bool is_gimple_lvalue (tree);
+
+/* Returns true iff T is a GIMPLE restricted function invariant. */
+bool is_gimple_min_invariant (tree);
+/* Returns true iff T is a GIMPLE rvalue. */
+bool is_gimple_val (tree);
+/* Returns true iff T is a valid rhs for a MODIFY_EXPR. */
+bool is_gimple_rhs (tree);
+
+/* Returns true iff T is a valid if-statement condition. */
+bool is_gimple_condexpr (tree);
+
+/* Returns true iff T is a type conversion. */
+bool is_gimple_cast (tree);
+/* Returns true iff T is a valid CONSTRUCTOR element (either an rvalue or
+ another CONSTRUCTOR). */
+bool is_gimple_constructor_elt (tree);
+/* Returns true iff T is a variable that does not need to live in memory. */
+bool is_gimple_non_addressable (tree t);
+
+/* If T makes a function call, returns the CALL_EXPR operand. */
+tree get_call_expr_in (tree t);
+
+void recalculate_side_effects (tree);
+
+void append_to_statement_list (tree, tree *);
+void append_to_statement_list_force (tree, tree *);
+void append_to_compound_expr (tree, tree *);
+
+/* FIXME we should deduce this from the predicate. */
+typedef enum fallback_t {
+ fb_none = 0,
+ fb_rvalue = 1,
+ fb_lvalue = 2,
+ fb_mayfail = 4,
+ fb_either= fb_rvalue | fb_lvalue
+} fallback_t;
+
+enum gimplify_status {
+ GS_ERROR = -2, /* Something Bad Seen. */
+ GS_UNHANDLED = -1, /* A langhook result for "I dunno". */
+ GS_OK = 0, /* We did something, maybe more to do. */
+ GS_ALL_DONE = 1 /* The expression is fully gimplified. */
+};
+
+enum gimplify_status gimplify_expr (tree *, tree *, tree *,
+ bool (*) (tree), fallback_t);
+void gimplify_stmt (tree *);
+void gimplify_to_stmt_list (tree *);
+void gimplify_body (tree *, tree);
+void push_gimplify_context (void);
+void pop_gimplify_context (tree);
+
+/* Miscellaneous helpers. */
+tree get_base_address (tree t);
+void gimple_add_tmp_var (tree);
+tree gimple_current_bind_expr (void);
+void gimple_push_bind_expr (tree);
+void gimple_pop_bind_expr (void);
+void unshare_all_trees (tree);
+tree voidify_wrapper_expr (tree);
+tree gimple_build_eh_filter (tree, tree, tree);
+tree build_and_jump (tree *);
+tree alloc_stmt_list (void);
+void free_stmt_list (tree);
+tree force_labels_r (tree *, int *, void *);
+
+/* In tree-nested.c. */
+extern void lower_nested_functions (tree);
+
+#endif /* _TREE_SIMPLE_H */
/* I'm not real happy about this, but we need to handle gimple and
non-gimple trees. */
#include "tree-iterator.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
/* 0 if we should not perform inlining.
1 if we should expand functions calls inline at the tree level.
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-iterator.h"
#include "ggc.h"
#include "flags.h"
#include "function.h"
#include "tree-inline.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-flow.h"
#include "tree-mudflap.h"
#include "tree-dump.h"
#include "function.h"
#include "tree-dump.h"
#include "tree-inline.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-iterator.h"
#include "tree-flow.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "c-tree.h"
#include "c-common.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "diagnostic.h"
#include "hashtab.h"
#include "output.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
+++ /dev/null
-/* Functions to analyze and validate GIMPLE trees.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@redhat.com>
- Rewritten by Jason Merrill <jason@redhat.com>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "ggc.h"
-#include "tm.h"
-#include "tree.h"
-#include "tree-simple.h"
-#include "output.h"
-#include "rtl.h"
-#include "expr.h"
-#include "bitmap.h"
-
-/* GCC GIMPLE structure
-
- Inspired by the SIMPLE C grammar at
-
- http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
-
- function:
- FUNCTION_DECL
- DECL_SAVED_TREE -> block
- block:
- BIND_EXPR
- BIND_EXPR_VARS -> DECL chain
- BIND_EXPR_BLOCK -> BLOCK
- BIND_EXPR_BODY -> compound-stmt
- compound-stmt:
- COMPOUND_EXPR
- op0 -> non-compound-stmt
- op1 -> stmt
- | EXPR_VEC
- (or other alternate solution)
- stmt: compound-stmt | non-compound-stmt
- non-compound-stmt:
- block
- | if-stmt
- | switch-stmt
- | jump-stmt
- | label-stmt
- | try-stmt
- | modify-stmt
- | call-stmt
- if-stmt:
- COND_EXPR
- op0 -> condition
- op1 -> stmt
- op2 -> stmt
- switch-stmt:
- SWITCH_EXPR
- op0 -> val
- op1 -> stmt
- op2 -> array of case labels (as LABEL_DECLs?)
- FIXME: add case value info
- jump-stmt:
- GOTO_EXPR
- op0 -> LABEL_DECL | '*' ID
- | RETURN_EXPR
- op0 -> modify-stmt | NULL_TREE
- (maybe -> RESULT_DECL | NULL_TREE? seems like some of expand_return
- depends on getting a MODIFY_EXPR.)
- | THROW_EXPR? do we need/want such a thing for opts, perhaps
- to generate an ERT_THROW region? I think so.
- Hmm...this would only work at the GIMPLE level, where we know that
- the call args don't have any EH impact. Perhaps
- annotation of the CALL_EXPR would work better.
- | RESX_EXPR
- label-stmt:
- LABEL_EXPR
- op0 -> LABEL_DECL
- | CASE_LABEL_EXPR
- CASE_LOW -> val | NULL_TREE
- CASE_HIGH -> val | NULL_TREE
- CASE_LABEL -> LABEL_DECL FIXME
- try-stmt:
- TRY_CATCH_EXPR
- op0 -> stmt
- op1 -> handler
- | TRY_FINALLY_EXPR
- op0 -> stmt
- op1 -> stmt
- handler:
- catch-seq
- | EH_FILTER_EXPR
- | stmt
- modify-stmt:
- MODIFY_EXPR
- op0 -> lhs
- op1 -> rhs
- call-stmt: CALL_EXPR
- op0 -> ID | '&' ID
- op1 -> arglist
-
- addr-expr-arg : compref | ID
- lhs: addr-expr-arg | '*' ID | bitfieldref
- min-lval: ID | '*' ID
- bitfieldref :
- BIT_FIELD_REF
- op0 -> compref | min-lval
- op1 -> CONST
- op2 -> CONST
- compref :
- COMPONENT_REF
- op0 -> compref | min-lval
- | ARRAY_REF
- op0 -> compref | min-lval
- op1 -> val
- | REALPART_EXPR
- | IMAGPART_EXPR
-
- condition : val | val relop val
- val : ID | CONST
-
- rhs : varname | CONST
- | '*' ID
- | '&' addr-expr-arg
- | call_expr
- | unop val
- | val binop val
- | '(' cast ')' val
-
- (cast here stands for all valid C typecasts)
-
- unop
- : '+'
- | '-'
- | '!'
- | '~'
-
- binop
- : relop | '-'
- | '+'
- | '/'
- | '*'
- | '%'
- | '&'
- | '|'
- | '<<'
- | '>>'
- | '^'
-
- relop
- : '<'
- | '<='
- | '>'
- | '>='
- | '=='
- | '!='
-
-*/
-
-static inline bool is_gimple_id (tree);
-
-/* Validation of GIMPLE expressions. */
-
-/* Return nonzero if T is a GIMPLE RHS:
-
- rhs : varname | CONST
- | '*' ID
- | '&' varname_or_temp
- | call_expr
- | unop val
- | val binop val
- | '(' cast ')' val
- | <CONSTRUCTOR <gimple_val ...>>
-
- The last option is only valid GIMPLE for vector and complex types;
- aggregate types should have their constructors decomposed. */
-
-bool
-is_gimple_rhs (tree t)
-{
- enum tree_code code = TREE_CODE (t);
-
- switch (TREE_CODE_CLASS (code))
- {
- case '1':
- case '2':
- case '<':
- return 1;
-
- default:
- break;
- }
-
- switch (code)
- {
- case TRUTH_NOT_EXPR:
- case TRUTH_AND_EXPR:
- case TRUTH_OR_EXPR:
- case TRUTH_XOR_EXPR:
- case ADDR_EXPR:
- case CALL_EXPR:
- case CONSTRUCTOR:
- case COMPLEX_EXPR:
- /* FIXME lower VA_ARG_EXPR. */
- case VA_ARG_EXPR:
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case COMPLEX_CST:
- case VECTOR_CST:
- return 1;
-
- default:
- break;
- }
-
- if (is_gimple_lvalue (t) || is_gimple_val (t))
- return 1;
-
- return 0;
-}
-
-/* Returns nonzero if T is a valid CONSTRUCTOR component in GIMPLE, either
- a val or another CONSTRUCTOR. */
-
-bool
-is_gimple_constructor_elt (tree t)
-{
- return (is_gimple_val (t)
- || TREE_CODE (t) == CONSTRUCTOR);
-}
-
-/* Return nonzero if T is a valid LHS for a GIMPLE assignment expression. */
-
-bool
-is_gimple_lvalue (tree t)
-{
- return (is_gimple_addr_expr_arg (t)
- || TREE_CODE (t) == INDIRECT_REF
- /* These are complex lvalues, but don't have addresses, so they
- go here. */
- || TREE_CODE (t) == BIT_FIELD_REF);
-}
-
-
-/* Return nonzero if T is a GIMPLE condition:
-
- condexpr
- : val
- | val relop val */
-
-bool
-is_gimple_condexpr (tree t)
-{
- return (is_gimple_val (t)
- || TREE_CODE_CLASS (TREE_CODE (t)) == '<');
-}
-
-
-/* Return nonzero if T is a valid operand for '&':
-
- varname
- : arrayref
- | compref
- | ID */
-
-bool
-is_gimple_addr_expr_arg (tree t)
-{
- return (is_gimple_id (t)
- || TREE_CODE (t) == ARRAY_REF
- || TREE_CODE (t) == COMPONENT_REF
- || TREE_CODE (t) == REALPART_EXPR
- || TREE_CODE (t) == IMAGPART_EXPR);
-}
-
-/* Return nonzero if T is function invariant. Or rather a restricted
- form of function invariant. */
-
-bool
-is_gimple_min_invariant (tree t)
-{
- switch (TREE_CODE (t))
- {
- case ADDR_EXPR:
- return TREE_INVARIANT (t);
-
- case INTEGER_CST:
- case REAL_CST:
- case STRING_CST:
- case COMPLEX_CST:
- case VECTOR_CST:
- return !TREE_OVERFLOW (t);
-
- default:
- return false;
- }
-}
-
-/* Return nonzero if T looks like a valid GIMPLE statement. */
-
-bool
-is_gimple_stmt (tree t)
-{
- enum tree_code code = TREE_CODE (t);
-
- if (IS_EMPTY_STMT (t))
- return 1;
-
- switch (code)
- {
- case BIND_EXPR:
- case COND_EXPR:
- /* These are only valid if they're void. */
- return VOID_TYPE_P (TREE_TYPE (t));
-
- case SWITCH_EXPR:
- case GOTO_EXPR:
- case RETURN_EXPR:
- case LABEL_EXPR:
- case CASE_LABEL_EXPR:
- case TRY_CATCH_EXPR:
- case TRY_FINALLY_EXPR:
- case EH_FILTER_EXPR:
- case CATCH_EXPR:
- case ASM_EXPR:
- case RESX_EXPR:
- case PHI_NODE:
- case STATEMENT_LIST:
- /* These are always void. */
- return 1;
-
- case VA_ARG_EXPR:
- /* FIXME this should be lowered. */
- return 1;
-
- case COMPOUND_EXPR:
- /* FIXME should we work harder to make COMPOUND_EXPRs void? */
- case CALL_EXPR:
- case MODIFY_EXPR:
- /* These are valid regardless of their type. */
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Return nonzero if T is a variable. */
-
-bool
-is_gimple_variable (tree t)
-{
- return (TREE_CODE (t) == VAR_DECL
- || TREE_CODE (t) == PARM_DECL
- || TREE_CODE (t) == RESULT_DECL
- || TREE_CODE (t) == SSA_NAME);
-}
-
-/* Return nonzero if T is a GIMPLE identifier (something with an address). */
-
-static inline bool
-is_gimple_id (tree t)
-{
- return (is_gimple_variable (t)
- || TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == LABEL_DECL
- /* Allow string constants, since they are addressable. */
- || TREE_CODE (t) == STRING_CST);
-}
-
-/* Return nonzero if TYPE is a suitable type for a scalar register
- variable. */
-
-bool
-is_gimple_reg_type (tree type)
-{
- return (!AGGREGATE_TYPE_P (type)
- && TREE_CODE (type) != COMPLEX_TYPE);
-}
-
-
-/* Return nonzero if T is a scalar register variable. */
-
-bool
-is_gimple_reg (tree t)
-{
- if (TREE_CODE (t) == SSA_NAME)
- t = SSA_NAME_VAR (t);
-
- return (is_gimple_variable (t)
- && is_gimple_reg_type (TREE_TYPE (t))
- /* A volatile decl is not acceptable because we can't reuse it as
- needed. We need to copy it into a temp first. */
- && ! TREE_THIS_VOLATILE (t)
- && ! TREE_ADDRESSABLE (t)
- && ! needs_to_live_in_memory (t));
-}
-
-/* Return nonzero if T is a GIMPLE variable whose address is not needed. */
-
-bool
-is_gimple_non_addressable (tree t)
-{
- if (TREE_CODE (t) == SSA_NAME)
- t = SSA_NAME_VAR (t);
-
- return (is_gimple_variable (t)
- && ! TREE_ADDRESSABLE (t)
- && ! needs_to_live_in_memory (t));
-}
-
-/* Return nonzero if T is a GIMPLE rvalue, i.e. an identifier or a
- constant. */
-
-bool
-is_gimple_val (tree t)
-{
- /* Make loads from volatiles and memory vars explicit. */
- if (is_gimple_variable (t)
- && is_gimple_reg_type (TREE_TYPE (t))
- && !is_gimple_reg (t))
- return 0;
-
- /* FIXME make these decls. That can happen only when we expose the
- entire landing-pad construct at the tree level. */
- if (TREE_CODE (t) == EXC_PTR_EXPR || TREE_CODE (t) == FILTER_EXPR)
- return 1;
-
- return (is_gimple_variable (t) || is_gimple_min_invariant (t));
-}
-
-
-/* Return true if T is a GIMPLE minimal lvalue, of the form
-
- min_lval: ID | '(' '*' ID ')'
-
- This never actually appears in the original SIMPLE grammar, but is
- repeated in several places. */
-
-bool
-is_gimple_min_lval (tree t)
-{
- return (is_gimple_id (t)
- || TREE_CODE (t) == INDIRECT_REF);
-}
-
-/* Return nonzero if T is a typecast operation of the form
- '(' cast ')' val. */
-
-bool
-is_gimple_cast (tree t)
-{
- return (TREE_CODE (t) == NOP_EXPR
- || TREE_CODE (t) == CONVERT_EXPR
- || TREE_CODE (t) == FIX_TRUNC_EXPR
- || TREE_CODE (t) == FIX_CEIL_EXPR
- || TREE_CODE (t) == FIX_FLOOR_EXPR
- || TREE_CODE (t) == FIX_ROUND_EXPR);
-}
-
-
-/* If T makes a function call, return the corresponding CALL_EXPR operand.
- Otherwise, return NULL_TREE. */
-
-tree
-get_call_expr_in (tree t)
-{
- if (TREE_CODE (t) == CALL_EXPR)
- return t;
- else if (TREE_CODE (t) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
- return TREE_OPERAND (t, 1);
- else if (TREE_CODE (t) == RETURN_EXPR
- && TREE_OPERAND (t, 0)
- && TREE_CODE (TREE_OPERAND (t, 0)) == MODIFY_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == CALL_EXPR)
- return TREE_OPERAND (TREE_OPERAND (t, 0), 1);
-
- return NULL_TREE;
-}
-
-
-/* Given an _EXPR TOP, reorganize all of the nested _EXPRs with the same
- code so that they only appear as the second operand. This should only
- be used for tree codes which are truly associative, such as
- COMPOUND_EXPR and TRUTH_ANDIF_EXPR. Arithmetic is not associative
- enough, due to the limited precision of arithmetic data types.
-
- This transformation is conservative; the operand 0 of a matching tree
- node will only change if it is also a matching node. */
-
-tree
-right_assocify_expr (tree top)
-{
- tree *p = ⊤
- enum tree_code code = TREE_CODE (*p);
- while (TREE_CODE (*p) == code)
- {
- tree cur = *p;
- tree lhs = TREE_OPERAND (cur, 0);
- if (TREE_CODE (lhs) == code)
- {
- /* There's a left-recursion. If we have ((a, (b, c)), d), we
- want to rearrange to (a, (b, (c, d))). */
- tree *q;
-
- /* Replace cur with the lhs; move (a, *) up. */
- *p = lhs;
-
- if (code == COMPOUND_EXPR)
- {
- /* We need to give (b, c) the type of c; previously lhs had
- the type of b. */
- TREE_TYPE (lhs) = TREE_TYPE (cur);
- if (TREE_SIDE_EFFECTS (cur))
- TREE_SIDE_EFFECTS (lhs) = 1;
- }
-
- /* Walk through the op1 chain from there until we find something
- with a different code. In this case, c. */
- for (q = &TREE_OPERAND (lhs, 1); TREE_CODE (*q) == code;
- q = &TREE_OPERAND (*q, 1))
- TREE_TYPE (*q) = TREE_TYPE (cur);
-
- /* Change (*, d) into (c, d). */
- TREE_OPERAND (cur, 0) = *q;
-
- /* And plug it in where c used to be. */
- *q = cur;
- }
- else
- p = &TREE_OPERAND (cur, 1);
- }
- return top;
-}
-
-/* Normalize the statement TOP. If it is a COMPOUND_EXPR, reorganize it so
- that we can traverse it without recursion. If it is null, replace it
- with a nop. */
-
-tree
-rationalize_compound_expr (tree top)
-{
- if (top == NULL_TREE)
- top = build_empty_stmt ();
- else if (TREE_CODE (top) == COMPOUND_EXPR)
- top = right_assocify_expr (top);
-
- return top;
-}
-
-/* Given a memory reference expression, return the base address. Note that,
- in contrast with get_base_var, this will not recurse inside INDIRECT_REF
- expressions. Therefore, given the reference PTR->FIELD, this function
- will return *PTR. Whereas get_base_var would've returned PTR. */
-
-tree
-get_base_address (tree t)
-{
- do
- {
- if (SSA_VAR_P (t)
- || TREE_CODE (t) == INDIRECT_REF)
- return t;
-
- switch (TREE_CODE (t))
- {
- case ARRAY_REF:
- case COMPONENT_REF:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- case BIT_FIELD_REF:
- t = TREE_OPERAND (t, 0);
- break;
-
- default:
- return NULL_TREE;
- }
- }
- while (t);
-
- return t;
-}
-
-
-void
-recalculate_side_effects (tree t)
-{
- enum tree_code code = TREE_CODE (t);
- int fro = first_rtl_op (code);
- int i;
-
- switch (TREE_CODE_CLASS (code))
- {
- case 'e':
- switch (code)
- {
- case INIT_EXPR:
- case MODIFY_EXPR:
- case VA_ARG_EXPR:
- case RTL_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- /* All of these have side-effects, no matter what their
- operands are. */
- return;
-
- default:
- break;
- }
- /* Fall through. */
-
- case '<': /* a comparison expression */
- case '1': /* a unary arithmetic expression */
- case '2': /* a binary arithmetic expression */
- case 'r': /* a reference */
- TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
- for (i = 0; i < fro; ++i)
- {
- tree op = TREE_OPERAND (t, i);
- if (op && TREE_SIDE_EFFECTS (op))
- TREE_SIDE_EFFECTS (t) = 1;
- }
- break;
- }
-}
+++ /dev/null
-/* Functions to analyze and validate GIMPLE trees.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@redhat.com>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef _TREE_SIMPLE_H
-#define _TREE_SIMPLE_H 1
-
-
-#include "tree-iterator.h"
-
-extern tree create_tmp_var_raw (tree, const char *);
-extern tree create_tmp_var (tree, const char *);
-extern bool is_gimple_tmp_var (tree);
-extern tree get_initialized_tmp_var (tree, tree *, tree *);
-extern tree get_formal_tmp_var (tree, tree *);
-extern void declare_tmp_vars (tree, tree);
-
-extern tree rationalize_compound_expr (tree);
-extern tree right_assocify_expr (tree);
-extern void annotate_all_with_locus (tree *, location_t);
-
-/* Validation of GIMPLE expressions. Note that these predicates only check
- the basic form of the expression, they don't recurse to make sure that
- underlying nodes are also of the right form. */
-
-/* Returns true iff T is a valid GIMPLE statement. */
-bool is_gimple_stmt (tree);
-
-/* Returns true iff TYPE is a valid type for a scalar register variable. */
-bool is_gimple_reg_type (tree);
-/* Returns true iff T is a scalar register variable. */
-bool is_gimple_reg (tree);
-/* Returns true iff T is any sort of variable. */
-bool is_gimple_variable (tree);
-/* Returns true iff T is a variable or an INDIRECT_REF (of a variable). */
-bool is_gimple_min_lval (tree);
-/* Returns true iff T is an lvalue other than an INDIRECT_REF. */
-bool is_gimple_addr_expr_arg (tree);
-/* Returns true iff T is any valid GIMPLE lvalue. */
-bool is_gimple_lvalue (tree);
-
-/* Returns true iff T is a GIMPLE restricted function invariant. */
-bool is_gimple_min_invariant (tree);
-/* Returns true iff T is a GIMPLE rvalue. */
-bool is_gimple_val (tree);
-/* Returns true iff T is a valid rhs for a MODIFY_EXPR. */
-bool is_gimple_rhs (tree);
-
-/* Returns true iff T is a valid if-statement condition. */
-bool is_gimple_condexpr (tree);
-
-/* Returns true iff T is a type conversion. */
-bool is_gimple_cast (tree);
-/* Returns true iff T is a valid CONSTRUCTOR element (either an rvalue or
- another CONSTRUCTOR). */
-bool is_gimple_constructor_elt (tree);
-/* Returns true iff T is a variable that does not need to live in memory. */
-bool is_gimple_non_addressable (tree t);
-
-/* If T makes a function call, returns the CALL_EXPR operand. */
-tree get_call_expr_in (tree t);
-
-void recalculate_side_effects (tree);
-
-void append_to_statement_list (tree, tree *);
-void append_to_statement_list_force (tree, tree *);
-void append_to_compound_expr (tree, tree *);
-
-/* FIXME we should deduce this from the predicate. */
-typedef enum fallback_t {
- fb_none = 0,
- fb_rvalue = 1,
- fb_lvalue = 2,
- fb_mayfail = 4,
- fb_either= fb_rvalue | fb_lvalue
-} fallback_t;
-
-enum gimplify_status {
- GS_ERROR = -2, /* Something Bad Seen. */
- GS_UNHANDLED = -1, /* A langhook result for "I dunno". */
- GS_OK = 0, /* We did something, maybe more to do. */
- GS_ALL_DONE = 1 /* The expression is fully gimplified. */
-};
-
-enum gimplify_status gimplify_expr (tree *, tree *, tree *,
- bool (*) (tree), fallback_t);
-void gimplify_stmt (tree *);
-void gimplify_to_stmt_list (tree *);
-void gimplify_body (tree *, tree);
-void push_gimplify_context (void);
-void pop_gimplify_context (tree);
-
-/* Miscellaneous helpers. */
-tree get_base_address (tree t);
-void gimple_add_tmp_var (tree);
-tree gimple_current_bind_expr (void);
-void gimple_push_bind_expr (tree);
-void gimple_pop_bind_expr (void);
-void unshare_all_trees (tree);
-tree voidify_wrapper_expr (tree);
-tree gimple_build_eh_filter (tree, tree, tree);
-tree build_and_jump (tree *);
-tree alloc_stmt_list (void);
-void free_stmt_list (tree);
-tree force_labels_r (tree *, int *, void *);
-
-/* In tree-nested.c. */
-extern void lower_nested_functions (tree);
-
-#endif /* _TREE_SIMPLE_H */
#include "langhooks.h"
#include "tree-inline.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-dump.h"
#include "tree-pass.h"
#include "timevar.h"
#include "function.h"
#include "diagnostic.h"
#include "tree-dump.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-flow.h"
#include "tree-inline.h"
#include "tree-alias-common.h"
#include "diagnostic.h"
#include "tree-inline.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-dump.h"
#include "tree-pass.h"
#include "timevar.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "timevar.h"
#include "tree-alias-common.h"
#include "tree.h"
#include "diagnostic.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-dump.h"
#include "tree-pass.h"
#include "timevar.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"
#include "diagnostic.h"
#include "tree-inline.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-dump.h"
#include "timevar.h"
#include "fibheap.h"
#include "diagnostic.h"
#include "bitmap.h"
#include "tree-flow.h"
-#include "tree-simple.h"
+#include "tree-gimple.h"
#include "tree-inline.h"
#include "varray.h"
#include "timevar.h"