1/* Java(TM) language-specific gimplification routines.
2   Copyright (C) 2003-2015 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3.  If not see
18<http://www.gnu.org/licenses/>.
19
20Java and all Java-based marks are trademarks or registered trademarks
21of Sun Microsystems, Inc. in the United States and other countries.
22The Free Software Foundation is independent of Sun Microsystems, Inc.  */
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "hash-set.h"
28#include "machmode.h"
29#include "vec.h"
30#include "double-int.h"
31#include "input.h"
32#include "alias.h"
33#include "symtab.h"
34#include "options.h"
35#include "wide-int.h"
36#include "inchash.h"
37#include "tree.h"
38#include "fold-const.h"
39#include "java-tree.h"
40#include "dumpfile.h"
41#include "predict.h"
42#include "tm.h"
43#include "hard-reg-set.h"
44#include "input.h"
45#include "function.h"
46#include "basic-block.h"
47#include "tree-ssa-alias.h"
48#include "internal-fn.h"
49#include "gimple-expr.h"
50#include "is-a.h"
51#include "gimple.h"
52#include "gimplify.h"
53
54static tree java_gimplify_block (tree);
55static enum gimplify_status java_gimplify_modify_expr (tree *);
56static enum gimplify_status java_gimplify_self_mod_expr (tree *, gimple_seq *,
57							 gimple_seq *);
58
59static void dump_java_tree (enum tree_dump_index, tree);
60
61/* Convert a Java tree to GENERIC.  */
62
63void
64java_genericize (tree fndecl)
65{
66  walk_tree (&DECL_SAVED_TREE (fndecl), java_replace_references, NULL, NULL);
67  dump_java_tree (TDI_original, fndecl);
68}
69
70/* Gimplify a Java tree.  */
71
72int
73java_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
74{
75  enum tree_code code = TREE_CODE (*expr_p);
76
77  switch (code)
78    {
79    case BLOCK:
80      *expr_p = java_gimplify_block (*expr_p);
81      break;
82
83    case MODIFY_EXPR:
84      return java_gimplify_modify_expr (expr_p);
85
86    case POSTINCREMENT_EXPR:
87    case POSTDECREMENT_EXPR:
88    case PREINCREMENT_EXPR:
89    case PREDECREMENT_EXPR:
90      return java_gimplify_self_mod_expr (expr_p, pre_p, post_p);
91
92    /* These should already be lowered before we get here.  */
93    case URSHIFT_EXPR:
94    case COMPARE_EXPR:
95    case COMPARE_L_EXPR:
96    case COMPARE_G_EXPR:
97      gcc_unreachable ();
98
99    default:
100      return GS_UNHANDLED;
101    }
102
103  return GS_OK;
104}
105
106static enum gimplify_status
107java_gimplify_modify_expr (tree *modify_expr_p)
108{
109  tree modify_expr = *modify_expr_p;
110  tree lhs = TREE_OPERAND (modify_expr, 0);
111  tree rhs = TREE_OPERAND (modify_expr, 1);
112  tree lhs_type = TREE_TYPE (lhs);
113
114  if (lhs_type != TREE_TYPE (rhs))
115    /* Fix up type mismatches to make legal GIMPLE.  These are
116       generated in several places, in particular null pointer
117       assignment and subclass assignment.  */
118    TREE_OPERAND (modify_expr, 1) = convert (lhs_type, rhs);
119
120  return GS_UNHANDLED;
121}
122
123/*  Special case handling for volatiles: we need to generate a barrier
124    between the reading and the writing.  */
125
126static enum gimplify_status
127java_gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
128			     gimple_seq *post_p ATTRIBUTE_UNUSED)
129{
130  tree lhs = TREE_OPERAND (*expr_p, 0);
131
132  if (TREE_CODE (lhs) == COMPONENT_REF
133      && TREE_THIS_VOLATILE (TREE_OPERAND (lhs, 1)))
134    TREE_THIS_VOLATILE (lhs) = 1;
135
136  return GS_UNHANDLED;
137}
138
139
140/* Gimplify BLOCK into a BIND_EXPR.  */
141
142static tree
143java_gimplify_block (tree java_block)
144{
145  tree decls = BLOCK_VARS (java_block);
146  tree body = BLOCK_EXPR_BODY (java_block);
147  gbind *outer = gimple_current_bind_expr ();
148  tree block;
149
150  /* Don't bother with empty blocks.  */
151  if (! body)
152    return build_empty_stmt (input_location);
153
154  if (IS_EMPTY_STMT (body))
155    return body;
156
157  /* Make a proper block.  Java blocks are unsuitable for BIND_EXPR
158     because they use BLOCK_SUBBLOCKS for another purpose.  */
159  block = make_node (BLOCK);
160  BLOCK_VARS (block) = decls;
161
162  /* The TREE_USED flag on a block determines whether the debug output
163     routines generate info for the variables in that block.  */
164  TREE_USED (block) = 1;
165
166  if (outer != NULL)
167    {
168      tree b = gimple_bind_block (outer);
169      BLOCK_SUBBLOCKS (b) = chainon (BLOCK_SUBBLOCKS (b), block);
170    }
171  BLOCK_EXPR_BODY (java_block) = NULL_TREE;
172
173  return build3 (BIND_EXPR, TREE_TYPE (java_block), decls, body, block);
174}
175
176/* Dump a tree of some kind.  This is a convenience wrapper for the
177   dump_* functions in tree-dump.c.  */
178static void
179dump_java_tree (enum tree_dump_index phase, tree t)
180{
181  FILE *stream;
182  int flags;
183
184  stream = dump_begin (phase, &flags);
185  flags |= TDF_SLIM;
186  if (stream)
187    {
188      dump_node (t, flags, stream);
189      dump_end (phase, stream);
190    }
191}
192