Merge trunk version 204345 into gupc branch.
[official-gcc.git] / gcc / upc / upc-genericize.c
blob29b2b74c9ddca8b58512124eca9b050bc61c4758
1 /* upc-genericize.c: UPC language specific tree lowering pass
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 Free Software Foundation, Inc.
4 Contributed by Gary Funck <gary@intrepid.com>
5 and Nenad Vukicevic <nenad@intrepid.com>.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "input.h"
28 #include "c/c-tree.h"
29 #include "flags.h"
30 #include "opts.h"
31 #include "options.h"
32 #include "toplev.h"
33 #include "output.h"
34 #include "tm.h"
35 #include "rtl.h"
36 #include "insn-flags.h"
37 #include "expr.h"
38 #include "c-family/c-common.h"
39 #include "c-family/c-pragma.h"
40 #include "c-family/c-upc.h"
41 #include "function.h"
42 #include "bitmap.h"
43 #include "cgraph.h"
44 #include "gimple.h"
45 #include "gimple-low.h"
46 #include "timevar.h"
47 #include "tree-check.h"
48 #include "tree-cfg.h"
49 #include "tree-iterator.h"
50 #include "ggc.h"
51 #include "target.h"
52 #include "upc-tree.h"
53 #include "upc-act.h"
54 #include "upc-pts.h"
55 #include "upc-rts-names.h"
56 #include "upc-gasp.h"
57 #include "upc-genericize.h"
58 #include "langhooks.h"
60 static void get_lc_mode_name (char *, enum machine_mode);
61 static tree upc_expand_get (location_t, tree, int);
62 static tree upc_expand_put (location_t, tree, tree, int);
63 static tree upc_create_tmp_var (tree);
64 static tree upc_copy_value_to_tmp_var (tree *, tree);
65 static tree upc_make_bit_field_ref (tree, tree, int, int);
66 static tree upc_build_shared_var_addr (location_t, tree);
67 static tree upc_shared_addr (location_t, tree);
68 static tree upc_shared_addr_rep (location_t, tree);
69 static tree upc_simplify_shared_ref (location_t, tree);
70 static void upc_strip_useless_generic_pts_cvt (tree *);
72 /* Given a shared variable's VAR_DECL node, map to another
73 VAR_DECL that has a similar external symbol name, with
74 the "shared" qualifier removed from its type. This
75 "shadow variable" is used to generate conventional
76 address constants when referring to a shared variable. */
78 struct GTY (()) uid_tree_map
80 unsigned int uid;
81 tree to;
83 static GTY ((param_is (struct uid_tree_map))) htab_t unshared_vars;
84 static hashval_t uid_tree_map_hash (const void *);
85 static int uid_tree_map_eq (const void *, const void *);
86 static tree create_unshared_var (location_t, const tree);
87 static tree lookup_unshared_var (const tree);
88 static void map_unshared_var (const tree, const tree);
89 static tree unshared_var_addr (location_t, const tree);
90 static tree unshared_var_name (const tree);
91 static void upc_free_unshared_var_table (void);
93 static void upc_genericize_addr_expr (location_t, tree *);
94 static void upc_genericize_array_ref (location_t, tree *);
95 static void upc_genericize_compound_expr (tree *, int);
96 static void upc_genericize_cond_expr (tree *, int);
97 static void upc_genericize_decl_expr (tree *);
98 static tree upc_genericize_expr (tree *, int *, void *);
99 static void upc_genericize_fndecl (tree);
100 static void upc_genericize_field_ref (location_t, tree *);
101 static void upc_genericize_forall_stmt (tree *);
102 static void upc_genericize_indirect_ref (location_t, tree *);
103 static void upc_genericize_modify_expr (location_t, tree *, int);
104 static void upc_genericize_pts_arith_expr (location_t, tree *);
105 static void upc_genericize_pts_cond_expr (location_t, tree *);
106 static void upc_genericize_pts_cvt (location_t, tree *);
107 static void upc_genericize_pts_to_int_cvt (location_t, tree *);
108 static void upc_genericize_real_imag_ref (location_t, tree *);
109 static void upc_genericize_shared_inc_dec_expr (location_t, tree *, int);
110 static void upc_genericize_shared_var_ref (location_t, tree *);
111 static void upc_genericize_walk (tree *, int);
112 static void upc_genericize_stmt_list (tree *);
113 static void upc_genericize_sync_stmt (location_t, tree *);
115 /* Create a new temporary variable declaration of type TYPE.
116 Push the variable into the current function binding. */
118 static tree
119 upc_create_tmp_var (tree type)
121 tree tmp_var;
122 /* We don't allow types that are addressable or incomplete. */
123 gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));
124 /* The temp. must not be shared qualified. If it is, then
125 remove the 'shared' qualifier. */
126 if (upc_shared_type_p (type))
127 type = build_upc_unshared_type (type);
128 tmp_var = create_tmp_var_raw (type, "UPC");
129 DECL_CONTEXT (tmp_var) = current_function_decl;
130 DECL_SEEN_IN_BIND_EXPR_P (tmp_var) = 1;
131 /* record_vars() will do what we want, but not if GIMPLE_DF is set.
132 (since we haven't gimplified yet, it should not be set). */
133 gcc_assert (!cfun->gimple_df);
134 record_vars (tmp_var);
135 return tmp_var;
138 /* Create a temporary variable and initialize it to VAL.
139 The expression used to initialize the temporary value
140 is returned in *VAL_EXPR. */
142 static tree
143 upc_copy_value_to_tmp_var (tree *val_expr, tree val)
145 const tree type = TREE_TYPE (val);
146 const tree tmp_var = upc_create_tmp_var (type);
147 *val_expr = build2 (INIT_EXPR, type, tmp_var, val);
148 SET_EXPR_LOCATION (*val_expr, EXPR_LOC_OR_HERE (val));
149 return tmp_var;
152 static void
153 get_lc_mode_name (char *mname, enum machine_mode mode)
155 char *m = mname;
156 const char *m_upper = GET_MODE_NAME (mode);
157 while (*m_upper)
158 *m++ = TOLOWER (*m_upper++);
159 *m = '\0';
162 /* Generate a call to the runtime to implement a 'get' of a shared
163 object. SRC is a reference to a UPC shared value; it must
164 be addressable. */
166 static tree
167 upc_expand_get (location_t loc, tree src, int want_stable_value)
169 tree type = TREE_TYPE (src);
170 /* Drop the shared qualifier. */
171 tree result_type = TYPE_MAIN_VARIANT (type);
172 int strict_mode = TYPE_STRICT (type)
173 || (!TYPE_RELAXED (type) && get_upc_consistency_mode ());
174 int doprofcall = flag_upc_debug
175 || (flag_upc_instrument && get_upc_pupc_mode ());
176 enum machine_mode mode = TYPE_MODE (type);
177 enum machine_mode op_mode = (mode == TImode) ? BLKmode : mode;
178 expanded_location s = expand_location (loc);
179 const char *src_filename = s.file;
180 const int src_line = s.line;
181 char libfunc_name[16], mname[8];
182 tree src_addr, result, result_tmp, libfunc, lib_args, lib_call;
183 src_addr = upc_shared_addr_rep (loc, src);
184 gcc_assert (TREE_TYPE (src_addr) == upc_pts_rep_type_node);
185 get_lc_mode_name (mname, (op_mode));
186 sprintf (libfunc_name, "__get%s%s%s%s",
187 strict_mode ? "s" : "",
188 doprofcall ? "g" : "",
189 mname,
190 (op_mode == BLKmode)
191 ? (doprofcall ? "5" : "3")
192 : (doprofcall ? "3" : "2"));
193 libfunc = identifier_global_value (get_identifier (libfunc_name));
194 if (!libfunc)
195 internal_error ("UPC runtime function %s not found", libfunc_name);
196 if (op_mode == BLKmode)
198 tree size = size_in_bytes (result_type);
199 tree result_addr;
200 result_tmp = upc_create_tmp_var (result_type);
201 TREE_ADDRESSABLE (result_tmp) = 1;
202 result_addr = build_fold_addr_expr_loc (loc, result_tmp);
203 lib_args = tree_cons (NULL_TREE, result_addr,
204 tree_cons (NULL_TREE, src_addr,
205 tree_cons (NULL_TREE, size,
206 NULL_TREE)));
207 if (doprofcall)
208 lib_args = upc_gasp_add_src_args (lib_args,
209 src_filename, src_line);
210 lib_call = build_function_call (loc, libfunc, lib_args);
211 result = build2 (COMPOUND_EXPR, result_type, lib_call, result_tmp);
213 else
215 lib_args = tree_cons (NULL_TREE, src_addr, NULL_TREE);
216 if (doprofcall)
217 lib_args = upc_gasp_add_src_args (lib_args,
218 src_filename, src_line);
219 lib_call = build_function_call (loc, libfunc, lib_args);
220 if (!lang_hooks.types_compatible_p (result_type, TREE_TYPE (lib_call)))
221 lib_call = build1 (NOP_EXPR, result_type, lib_call);
222 result = lib_call;
223 if (want_stable_value)
225 tree result_tmp_init_expr;
226 result_tmp = upc_copy_value_to_tmp_var (&result_tmp_init_expr,
227 result);
228 result = build2 (COMPOUND_EXPR, result_type,
229 result_tmp_init_expr, result_tmp);
232 return result;
235 /* Generate a call to the runtime to implement a 'put' into a shared
236 object. DEST is a reference to the destination in UPC shared memory;
237 it must be addressable. SRC is the value to be stored into the
238 destination. If WANT_VALUE is set, then return a compound expression
239 which evaluates to the value of SRC. */
241 static tree
242 upc_expand_put (location_t loc, tree dest, tree src, int want_value)
244 tree type = TREE_TYPE (dest);
245 int strict_mode = TYPE_STRICT (type)
246 || (!TYPE_RELAXED (type) && get_upc_consistency_mode ());
247 int doprofcall = flag_upc_debug
248 || (flag_upc_instrument && get_upc_pupc_mode ());
249 enum machine_mode mode = TYPE_MODE (type);
250 enum machine_mode op_mode = (mode == TImode) ? BLKmode : mode;
251 int is_src_shared = (TREE_SHARED (src)
252 || upc_shared_type_p (TREE_TYPE (src)));
253 int local_copy = want_value
254 || (op_mode == BLKmode
255 && !(is_src_shared && INDIRECT_REF_P (src))
256 && (!is_gimple_addressable (src)
257 || !is_gimple_variable (src)
258 || needs_to_live_in_memory (src)));
259 int is_shared_copy = !local_copy && (op_mode == BLKmode) && is_src_shared;
260 char libfunc_name[16], mname[8];
261 expanded_location s = expand_location (loc);
262 const char *src_filename = s.file;
263 const int src_line = s.line;
264 tree dest_addr, libfunc, lib_args, src_tmp_init_expr, result;
265 dest_addr = upc_shared_addr_rep (loc, dest);
266 gcc_assert (TREE_TYPE (dest_addr) == upc_pts_rep_type_node);
267 if (local_copy)
268 src = upc_copy_value_to_tmp_var (&src_tmp_init_expr, src);
269 lib_args = tree_cons (NULL_TREE, dest_addr, NULL_TREE);
270 if (is_shared_copy)
272 sprintf (libfunc_name, "__copy%s%sblk%s",
273 strict_mode ? "s" : "",
274 doprofcall ? "g" : "",
275 doprofcall ? "5" : "3");
277 else
279 get_lc_mode_name (mname, op_mode);
280 sprintf (libfunc_name, "__put%s%s%s%s",
281 strict_mode ? "s" : "",
282 doprofcall ? "g" : "",
283 mname,
284 (op_mode == BLKmode)
285 ? (doprofcall ? "5" : "3")
286 : (doprofcall ? "4" : "2"));
288 libfunc = identifier_global_value (get_identifier (libfunc_name));
289 if (!libfunc)
290 internal_error ("UPC runtime function %s not found", libfunc_name);
291 if (op_mode == BLKmode)
293 const tree size = tree_expr_size (src);
294 tree src_addr;
295 if (is_shared_copy)
296 src_addr = upc_shared_addr_rep (loc, src);
297 else
298 src_addr = build_fold_addr_expr_loc (loc, src);
299 lib_args = chainon (lib_args,
300 tree_cons (NULL_TREE, src_addr,
301 tree_cons (NULL_TREE, size, NULL_TREE)));
302 if (doprofcall)
303 lib_args = upc_gasp_add_src_args (lib_args, src_filename, src_line);
305 else
307 tree src_type = lang_hooks.types.type_for_mode (mode, 0);
308 tree libfunc_arg_types = TYPE_ARG_TYPES (TREE_TYPE (libfunc));
309 tree put_arg_type = TREE_VALUE (TREE_CHAIN (libfunc_arg_types));
310 if (TYPE_PRECISION (put_arg_type) != TYPE_PRECISION (src_type))
311 internal_error ("%s: UPC put operation argument precision mismatch",
312 libfunc_name);
313 /* Avoid warnings about implicit conversion between
314 the actual parameter value's type, and the type of the
315 runtime routine's parameter. */
316 if (!lang_hooks.types_compatible_p (src_type, TREE_TYPE (src)))
317 src = build1 (AGGREGATE_TYPE_P (TREE_TYPE (src))
318 ? VIEW_CONVERT_EXPR : NOP_EXPR, src_type, src);
319 lib_args = chainon (lib_args, tree_cons (NULL_TREE, src, NULL_TREE));
320 if (doprofcall)
321 lib_args = upc_gasp_add_src_args (lib_args, src_filename, src_line);
323 result = build_function_call (loc, libfunc, lib_args);
324 if (want_value)
325 result = build2 (COMPOUND_EXPR, TREE_TYPE (src), result, src);
326 if (local_copy)
327 result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
328 src_tmp_init_expr, result);
329 return result;
332 /* Return a BIT_FIELD_REF of type TYPE to refer to BITSIZE bits of INNER
333 starting at BITPOS. The field is unsigned if UNSIGNEDP is nonzero. */
335 static tree
336 upc_make_bit_field_ref (tree inner, tree type, int bitsize, int bitpos)
338 tree result;
339 if (bitpos == 0)
341 tree size = TYPE_SIZE (TREE_TYPE (inner));
342 if ((INTEGRAL_TYPE_P (TREE_TYPE (inner))
343 || POINTER_TYPE_P (TREE_TYPE (inner)))
344 && host_integerp (size, 0)
345 && tree_low_cst (size, 0) == bitsize)
346 return fold_convert (type, inner);
348 result = build3 (BIT_FIELD_REF, type, inner,
349 size_int (bitsize), bitsize_int (bitpos));
350 return result;
353 /* On entry, EXP points to a shared field reference
354 or array reference. Simplify it so that is in
355 one of two forms:
356 1) (INDIRECT_REF <pointer to shared object>)
357 2) (BIT_FIELD_REF (INDIRECT_REF <pointer to shared object>) ...)
358 The first form is returned for all shared field references
359 except those that require access to bit fields within
360 a storage unit. */
362 static tree
363 upc_simplify_shared_ref (location_t loc, tree exp)
365 tree ref_type = TREE_TYPE (exp);
366 tree base, base_addr, ref, t_offset;
367 enum machine_mode mode = VOIDmode;
368 HOST_WIDE_INT bitsize = 0;
369 HOST_WIDE_INT bitpos = 0;
370 int unsignedp = 0;
371 int volatilep = 0;
372 tree offset = NULL_TREE;
373 base = get_inner_reference (exp, &bitsize, &bitpos, &offset,
374 &mode, &unsignedp, &volatilep, false);
375 gcc_assert (upc_shared_type_p (TREE_TYPE (base)));
376 base_addr = build_fold_addr_expr (base);
377 if (bitpos)
379 t_offset = size_int (bitpos / BITS_PER_UNIT);
380 if (offset)
381 t_offset = fold (build_binary_op (loc, PLUS_EXPR,
382 offset, t_offset, 0));
384 else
385 t_offset = offset;
387 const tree base_addr_type = TREE_TYPE (base_addr);
388 const enum tree_code cvt_op =
389 upc_types_compatible_p ( upc_char_pts_type_node, base_addr_type)
390 ? NOP_EXPR : CONVERT_EXPR;
391 /* Convert the base address to (shared [] char *), which may
392 reset the pointer's phase to zero. This is the behavior
393 that is required to reference a field in a structure and
394 to meaningfully add an offset to the base address. */
395 base_addr = build1 (cvt_op, upc_char_pts_type_node, base_addr);
396 if (t_offset)
398 /* Adjust the base address so that it points to the
399 simplified lvalue. */
400 base_addr = fold (build_binary_op (loc, PLUS_EXPR,
401 base_addr, t_offset, 0));
402 base_addr = convert (base_addr_type, base_addr);
405 /* We need to construct a pointer-to-shared type that
406 will be used to point to the referenced value. However,
407 for a COMPONENT_REF, the original type will likely not have
408 upc_shared_type_p() asserted, but rather, the expression node itself
409 will have TREE_SHARED asserted. We need to first propagate
410 this information into a new shared type, which will in turn be
411 used to build the required pointer-to-shared type. Further,
412 any pointer to a shared component must be constrained to have
413 a blocking factor of zero. */
414 if (!upc_shared_type_p (ref_type))
416 const int shared_quals = TYPE_QUALS (TREE_TYPE (exp))
417 | TREE_QUALS (exp);
418 gcc_assert (shared_quals & TYPE_QUAL_SHARED);
419 ref_type = c_build_qualified_type_1 (ref_type, shared_quals,
420 size_zero_node);
422 if (TREE_TYPE (TREE_TYPE (base_addr)) != ref_type)
423 base_addr = convert (build_pointer_type (ref_type), base_addr);
424 /* The simplified reference is an indirect ref., using
425 the adjusted base_addr */
426 ref = build_fold_indirect_ref_loc (loc, base_addr);
427 /* If this is a BIT_FIELD_REF then adjust its base address. */
428 if (TREE_CODE (exp) == BIT_FIELD_REF)
429 ref = upc_make_bit_field_ref (ref, ref_type, bitsize, bitpos);
430 return ref;
433 /* Create and return a "shadow variable" that has the same type as VAR,
434 but with all UPC shared qualifiers removed from the type.
435 The assembler name of this shadow variable is the same
436 as that of the original variable, VAR. */
438 static tree
439 create_unshared_var (location_t loc, const tree var)
441 tree u_name, u_type, u;
442 gcc_assert (var && TREE_CODE (var) == VAR_DECL);
443 u_name = unshared_var_name (var);
444 u_type = build_upc_unshared_type (TREE_TYPE (var));
445 u = build_decl (loc, VAR_DECL, u_name, u_type);
446 TREE_USED (u) = 1;
447 TREE_ADDRESSABLE (u) = 1;
448 TREE_PUBLIC (u) = TREE_PUBLIC (var);
449 TREE_STATIC (u) = TREE_STATIC (var);
450 DECL_ARTIFICIAL (u) = 1;
451 DECL_IGNORED_P (u) = 1;
452 DECL_EXTERNAL (u) = DECL_EXTERNAL (var);
453 DECL_SECTION_NAME (u) = DECL_SECTION_NAME (var);
454 DECL_CONTEXT (u) = DECL_CONTEXT (var);
456 /* Alias the unshared variable to the shared variable. */
458 SET_DECL_ASSEMBLER_NAME (u, DECL_ASSEMBLER_NAME (var));
460 /* Make sure the variable is referenced. */
462 mark_decl_referenced (var);
463 return u;
466 /* Return a hash value given the argument P, which
467 is a pointer to a uid_tree_map. The pointer
468 value is used directly to yield a hash value. */
470 static hashval_t
471 uid_tree_map_hash (const void *p)
473 const struct uid_tree_map *const map = (const struct uid_tree_map *) p;
474 return map->uid;
477 /* Return TRUE if the UID fields of two uid_tree_map
478 structures are equal. This function is called by
479 the `htab_find_with_hash function' to match entries
480 in the `unshared_vars' hash table. */
482 static int
483 uid_tree_map_eq (const void *va, const void *vb)
485 const struct uid_tree_map *const a = (const struct uid_tree_map *) va;
486 const struct uid_tree_map *const b = (const struct uid_tree_map *) vb;
487 return a->uid == b->uid;
490 /* Return the "shadow variable" created for VAR that
491 has the same type as VAR, but with the UPC shared
492 qualifiers removed. */
494 static tree
495 lookup_unshared_var (const tree var)
497 const struct uid_tree_map *h;
498 struct uid_tree_map in;
499 unsigned int uid;
500 gcc_assert (var && TREE_CODE (var) == VAR_DECL);
501 uid = DECL_UID (var);
502 in.uid = uid;
503 in.to = NULL_TREE;
504 h = (struct uid_tree_map *) htab_find_with_hash (unshared_vars, &in, uid);
505 return h ? h->to : NULL_TREE;
508 #define UNSHARE_PREFIX "_u_"
510 /* Return an identifier that will be used to declare the "shadow variable"
511 which has the same type as VAR, but with all UPC shared qualifiers
512 removed from the type. The identifier has the same name as
513 that of VAR, prefixed with the string given by the
514 value of `UNSHARE_PREFIX'. */
516 static tree
517 unshared_var_name (const tree var)
519 const tree name = DECL_NAME (var);
520 const size_t len = IDENTIFIER_LENGTH (name);
521 char *tmp_name = (char *) alloca (len + sizeof (UNSHARE_PREFIX));
522 strcpy (tmp_name, UNSHARE_PREFIX);
523 strcat (tmp_name, IDENTIFIER_POINTER (name));
524 return get_identifier (tmp_name);
527 /* Register the mapping between the UPC shared variable, VAR,
528 and its unshared counter-part, U_VAR. "unshared" in
529 this context means that the shadow variable U_VAR
530 has the same type as VAR, with the UPC shared,
531 strict, and relaxed qualifiers removed. */
533 static void
534 map_unshared_var (const tree var, const tree u_var)
536 struct uid_tree_map *h;
537 unsigned int uid;
538 void **loc;
539 gcc_assert (var && TREE_CODE (var) == VAR_DECL);
540 gcc_assert (u_var && TREE_CODE (u_var) == VAR_DECL);
541 uid = DECL_UID (var);
542 h = ggc_alloc_uid_tree_map ();
543 h->uid = uid;
544 h->to = u_var;
545 loc = htab_find_slot_with_hash (unshared_vars, h, uid, INSERT);
546 *(struct uid_tree_map **) loc = h;
549 /* Return a tree node that evaluates to the address that the
550 linker assigns to the UPC shared variable, VAR. This is not
551 the final location of the UPC shared variable. The linker is
552 used only to lay out a given UPC thread's contribution to the
553 UPC shared global memory region.
555 The address expression returned will point to a "shadow
556 variable" declaration that is created from the UPC shared
557 variable declaration, VAR. This shadow variable has the same
558 type and other attributes as VAR, with the UPS shared type
559 qualifiers removed. */
561 static tree
562 unshared_var_addr (location_t loc, const tree var)
564 tree unshared_var, addr;
565 unshared_var = lookup_unshared_var (var);
566 if (!unshared_var)
568 unshared_var = create_unshared_var (loc, var);
569 map_unshared_var (var, unshared_var);
571 addr = build_fold_addr_expr (unshared_var);
572 TREE_CONSTANT (addr) = 1;
573 TREE_READONLY (addr) = 1;
574 return addr;
577 /* Free the hash table used to map UPC VAR_DECL's
578 into the "unshared" shadow variables that were created
579 in order to establish the offset of a UPC shared
580 variable with the special linker section that is
581 created to collect the UPC shared variables. */
583 static void
584 upc_free_unshared_var_table (void)
586 if (unshared_vars)
588 htab_delete (unshared_vars);
589 unshared_vars = NULL;
593 /* Convert the shared variable reference VAR into a UPC pointer-to-shared
594 value of the form {0, 0, &VAR}. */
596 static tree
597 upc_build_shared_var_addr (location_t loc, tree var)
599 tree var_addr, val;
600 gcc_assert (TREE_CODE (var) == VAR_DECL && TREE_SHARED (var));
601 /* Refer to a shadow variable that has the same type as VAR, but
602 with the shared qualifier removed. */
603 var_addr = unshared_var_addr (loc, var);
604 #ifdef HAVE_UPC_PTS_PACKED_REP
606 const tree char_ptr_type = build_pointer_type (char_type_node);
607 tree shared_vaddr_base;
608 /* Subtract off the shared section base address so that the
609 resulting quantity will fit into the vaddr field. */
610 shared_vaddr_base =
611 identifier_global_value (get_identifier ("__upc_shared_start"));
612 if (!shared_vaddr_base)
613 shared_vaddr_base =
614 identifier_global_value (get_identifier ("UPCRL_shared_begin"));
615 if (!shared_vaddr_base)
616 fatal_error ("UPC shared section start address not found; "
617 "cannot find a definition for either "
618 "__upc_shared_start or UPCRL_shared_begin");
619 assemble_external (shared_vaddr_base);
620 TREE_USED (shared_vaddr_base) = 1;
621 shared_vaddr_base = build1 (ADDR_EXPR, char_ptr_type, shared_vaddr_base);
622 var_addr = build_binary_op (loc, MINUS_EXPR,
623 convert (ptrdiff_type_node, var_addr),
624 convert (ptrdiff_type_node,
625 shared_vaddr_base), 0);
627 #endif
628 val = (*upc_pts.build) (loc, build_pointer_type (TREE_TYPE (var)),
629 var_addr, integer_zero_node, integer_zero_node);
630 return val;
633 /* Return the UPC shared address of the lvalue
634 identified by EXP. The type of the result is
635 the UPC pointer-to-shared representation type. */
637 static tree
638 upc_shared_addr_rep (location_t loc, tree exp)
640 tree addr = upc_shared_addr (loc, exp);
641 /* Convert to internal UPC pointer-to-shared representation,
642 possibly removing an unnecessary chain of VIEW_CONVERT_EXPR's. */
643 addr = fold (build1 (VIEW_CONVERT_EXPR, upc_pts_rep_type_node, addr));
644 return addr;
647 /* Return the UPC shared address of the lvalue
648 identified by EXP. The type of the result is
649 the UPC pointer-to-shared representation type. */
651 static tree
652 upc_shared_addr (location_t loc, tree exp)
654 tree ref = exp;
655 const enum tree_code code = TREE_CODE (exp);
656 tree addr;
657 switch (code)
659 case VAR_DECL:
660 addr = upc_build_shared_var_addr (loc, exp);
661 break;
662 case ARRAY_REF:
663 case COMPONENT_REF:
664 ref = upc_simplify_shared_ref (loc, exp);
665 if (TREE_CODE (ref) == ERROR_MARK)
666 return ref;
667 addr = build_fold_addr_expr_loc (loc, ref);
668 upc_genericize_walk (&addr, /* want_value */ 1);
669 break;
670 case INDIRECT_REF:
671 /* Remove the indirection by taking the address and simplifying. */
672 addr = build_fold_addr_expr_loc (loc, ref);
673 upc_genericize_walk (&addr, /* want_value */ 1);
674 break;
675 case BIT_FIELD_REF:
676 error ("invalid & operation applied to a UPC shared bit field");
677 return error_mark_node;
678 default:
679 gcc_unreachable ();
681 return addr;
684 /* Rewrite a 'upc_forall' statement into a
685 regular 'for' statement. */
687 static void
688 upc_genericize_forall_stmt (tree *expr_p ATTRIBUTE_UNUSED)
690 /* Handled in c-parser.c. */
691 gcc_unreachable ();
694 /* Rewrite a UPC synchronization statement (upc_wait, upc_notify,
695 and upc_barrier) into a call to the runtime. */
697 static void
698 upc_genericize_sync_stmt (location_t loc, tree *stmt_p)
700 /* The first operand is the synchronization operation, UPC_SYNC_OP:
701 UPC_SYNC_NOTIFY_OP 1 Notify operation
702 UPC_SYNC_WAIT_OP 2 Wait operation
703 UPC_SYNC_BARRIER_OP 3 Barrier operation
704 The second operand, UPC_SYNC_ID is the (optional) expression
705 whose value specifies the barrier identifier which is checked
706 by the various synchronization operations. */
707 tree stmt = *stmt_p;
708 tree sync_op = UPC_SYNC_OP (stmt);
709 tree sync_id = UPC_SYNC_ID (stmt);
710 const int op = (int) tree_low_cst (sync_op, 1);
711 const char *libfunc_name = (char *) 0;
712 int doprofcall = flag_upc_debug
713 || (flag_upc_instrument && get_upc_pupc_mode ());
714 tree libfunc, lib_args;
715 switch (op)
717 case UPC_SYNC_NOTIFY_OP:
718 libfunc_name = doprofcall ? UPC_NOTIFYG_LIBCALL : UPC_NOTIFY_LIBCALL;
719 break;
720 case UPC_SYNC_WAIT_OP:
721 libfunc_name = doprofcall ? UPC_WAITG_LIBCALL : UPC_WAIT_LIBCALL;
722 break;
723 case UPC_SYNC_BARRIER_OP:
724 libfunc_name = doprofcall ? UPC_BARRIERG_LIBCALL : UPC_BARRIER_LIBCALL;
725 break;
726 default:
727 gcc_unreachable ();
729 libfunc = identifier_global_value (get_identifier (libfunc_name));
730 if (!libfunc)
731 internal_error ("UPC runtime function %s not found", libfunc_name);
732 if (!sync_id)
733 sync_id = build_int_cst (NULL_TREE, INT_MIN);
734 lib_args = tree_cons (NULL_TREE, sync_id, NULL_TREE);
735 if (doprofcall)
736 lib_args = upc_gasp_add_src_args (lib_args, input_filename, input_line);
737 *stmt_p = build_function_call (loc, libfunc, lib_args);
740 /* Rewrite a reference to a UPC shared variable into a 'get' operation. */
742 static void
743 upc_genericize_shared_var_ref (location_t loc, tree *expr_p)
745 tree src = *expr_p;
746 *expr_p = upc_expand_get (loc, src, 0);
749 /* Expand & of a UPC shared object into equivalent code. */
751 static void
752 upc_genericize_addr_expr (location_t loc, tree *expr_p)
754 const tree op0 = TREE_OPERAND (*expr_p, 0);
755 *expr_p = upc_shared_addr (loc, op0);
758 /* Expand indirection through a UPC pointer-to-shared
759 into a UPC get operation. */
761 static void
762 upc_genericize_indirect_ref (location_t loc, tree *expr_p)
764 tree src = *expr_p;
765 *expr_p = upc_expand_get (loc, src, 0);
768 static void
769 upc_genericize_real_imag_ref (location_t loc ATTRIBUTE_UNUSED,
770 tree *expr_p ATTRIBUTE_UNUSED)
772 error ("accesses to .real and .imag are not yet implemented");
773 *expr_p = error_mark_node;
776 /* Rewrite a[i] into *(a + i). This code is derived from
777 build_array_ref(). We could call build_array_ref()
778 directly, and depend upon it to do this rewrite if
779 the array is shared, but it is clearer to handle
780 it explicitly here. */
782 static void
783 upc_genericize_array_ref (location_t loc, tree *expr_p)
785 tree exp = *expr_p;
786 tree array = TREE_OPERAND (exp, 0);
787 tree index = TREE_OPERAND (exp, 1);
788 tree ar = default_conversion (array);
789 gcc_assert (TREE_CODE (exp) == ARRAY_REF);
790 if (ar == error_mark_node)
791 return;
792 gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
793 gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
794 *expr_p = build_indirect_ref (loc,
795 build_binary_op (loc, PLUS_EXPR, ar, index,
796 0), RO_ARRAY_INDEXING);
797 upc_genericize_indirect_ref (loc, expr_p);
800 /* Handle conversions between UPC pointers-to-shared and
801 local pointers, or between UPC pointers-to-shared which
802 have differing block factors. */
804 static void
805 upc_genericize_pts_cvt (location_t loc, tree *expr_p)
807 *expr_p = (*upc_pts.cvt) (loc, *expr_p);
810 /* Handle conversions from a UPC pointer-to-shared into
811 an integer value. */
813 static void
814 upc_genericize_pts_to_int_cvt (location_t loc, tree *expr_p)
816 tree pts, pts_arg, ref_type, upc_addrfield;
817 tree *pts_p;
818 int shared_quals;
819 upc_addrfield = identifier_global_value (get_identifier ("upc_addrfield"));
820 if (!upc_addrfield)
821 internal_error ("UPC runtime function `upc_addrfield` not found");
822 pts_p = &TREE_OPERAND (*expr_p, 0);
823 pts = *pts_p;
824 ref_type = TREE_TYPE (TREE_TYPE (pts));
825 shared_quals = TYPE_QUALS (ref_type) | TREE_QUALS (pts);
826 gcc_assert (shared_quals & TYPE_QUAL_SHARED);
827 if ((shared_quals & TYPE_QUAL_CONST) != 0)
829 /* drop 'const' qualifier to arg. type mis-match. */
830 shared_quals &= ~TYPE_QUAL_CONST;
831 ref_type = c_build_qualified_type_1 (ref_type, shared_quals, size_zero_node);
832 TREE_TYPE (pts) = build_pointer_type (ref_type);
834 pts_arg = tree_cons (NULL_TREE, pts, NULL_TREE);
835 *pts_p = build_function_call (loc, upc_addrfield, pts_arg);
838 /* Rewrite op0 CMP op1 into either a bitwise
839 comparison of the UPC pointer-to-shared operands
840 or by taking the difference, and comparing it
841 to zero. */
843 static void
844 upc_genericize_pts_cond_expr (location_t loc, tree *expr_p)
846 *expr_p = (*upc_pts.cond_expr) (loc, *expr_p);
849 /* Rewrite a reference to a bit field within a UPC shared struct/union.
850 When implemented, the translated tree will need to fetch
851 the container for this bit-field from UPC shared memory,
852 and then isolate the bit field within the container. */
854 static void
855 upc_genericize_field_ref (location_t loc, tree *expr_p)
857 tree ref = upc_simplify_shared_ref (loc, *expr_p);
858 if (TREE_CODE (ref) == BIT_FIELD_REF)
860 error_at (loc, "accesses to UPC shared bit fields "
861 "are not yet implemented");
862 ref = error_mark_node;
864 else
865 ref = upc_expand_get (loc, ref, 0);
866 *expr_p = ref;
869 /* Expand the addition of UPC pointer-to-shared value and an integer.
870 When the operation is subtraction, rewrite the expression (p - i)
871 into (p + (-i)) and expand the sum. The special handling of
872 subtraction is required because addition/subtraction of UPC
873 pointers-to-shared is a non-trivial operation, and it simpler
874 to only implement addition. */
876 static void
877 upc_genericize_pts_arith_expr (location_t loc, tree *expr_p)
879 tree exp = *expr_p;
880 if (TREE_CODE (exp) == PLUS_EXPR || TREE_CODE (exp) == POINTER_PLUS_EXPR)
882 *expr_p = (*upc_pts.sum) (loc, exp);
884 else if (TREE_CODE (exp) == MINUS_EXPR)
886 const tree type0 = TREE_TYPE (TREE_OPERAND (exp, 0));
887 const tree type1 = TREE_TYPE (TREE_OPERAND (exp, 1));
888 if ((TREE_CODE (type0) == POINTER_TYPE)
889 && (TREE_CODE (type1) == INTEGER_TYPE))
891 /* Rewrite the expression p - i into p + (-i),
892 and expand the sum. */
893 tree int_op = TREE_OPERAND (exp, 1);
894 if (TREE_CODE (int_op) == INTEGER_CST
895 && TREE_CODE (TREE_TYPE (int_op)) == POINTER_TYPE)
897 /* Earlier passes have altered the type of the integer
898 constant to be a UPC pointer-to-shared type. This won't
899 play well when we try to negate it. For now, convert
900 it back to a size type. */
901 int_op = ssize_int (tree_low_cst (int_op, 0));
903 TREE_SET_CODE (exp, PLUS_EXPR);
904 /* Make sure that int_op is a signed type to
905 ensure negation works properly. */
906 if (TYPE_UNSIGNED (TREE_TYPE (int_op)))
907 int_op = convert (ssizetype, int_op);
908 TREE_OPERAND (exp, 1) =
909 build_unary_op (loc, NEGATE_EXPR, int_op, 0);
910 *expr_p = (*upc_pts.sum) (loc, exp);
912 else
913 *expr_p = (*upc_pts.diff) (loc, exp);
915 else
916 gcc_unreachable ();
919 /* Rewrite the increment/decrement of a UPC shared value into
920 an equivalent assignment statement. (Although some future
921 implementations of the UPC runtime API might be able to
922 implement these operations atomically, that is not currently
923 defined in the runtime API.) If WANT_VALUE is set, then
924 generate a compound expression that yields the appropriate value. */
926 static void
927 upc_genericize_shared_inc_dec_expr (location_t loc, tree *expr_p,
928 int want_value)
930 const tree exp = *expr_p;
931 const enum tree_code code = TREE_CODE (exp);
932 const tree op0 = TREE_OPERAND (exp, 0);
933 const int is_inc_op = (code == POSTINCREMENT_EXPR
934 || code == PREINCREMENT_EXPR);
935 const enum tree_code inc_dec_code = is_inc_op ? PLUS_EXPR : MINUS_EXPR;
936 tree val, val_init_expr, inc_dec_expr, mod_expr;
937 val = upc_copy_value_to_tmp_var (&val_init_expr, op0);
938 inc_dec_expr = build_binary_op (loc, inc_dec_code,
939 val, integer_one_node, 0);
940 mod_expr = build2 (MODIFY_EXPR, TREE_TYPE (val), op0, inc_dec_expr);
941 if (want_value)
943 if (code == PREDECREMENT_EXPR || code == PREINCREMENT_EXPR)
944 upc_genericize_modify_expr (loc, &mod_expr, 1);
945 else
947 upc_genericize_modify_expr (loc, &mod_expr, 0);
948 mod_expr = build2 (COMPOUND_EXPR, TREE_TYPE (val), mod_expr, val);
951 else
952 upc_genericize_modify_expr (loc, &mod_expr, 0);
953 *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (mod_expr),
954 val_init_expr, mod_expr);
957 /* Simplify assignments to generic pointer-to-shared objects,
958 where an intermediate conversion appears on the right hand
959 side of the assignment. Conversions from non-generic
960 pointer-to-shared to generic pointer-to-shared are preserved
961 up to the point of the final assignment, because a conversion
962 from generic pointer-to-shared to non-generic pointer-to-shared
963 may reset the phase in some cases, and we can only determine
964 that the conversion is unnecessary when we know the target
965 of the assignment expression. */
967 static void
968 upc_strip_useless_generic_pts_cvt (tree *expr_p)
970 while (TREE_CODE (*expr_p) == CONVERT_EXPR
971 && POINTER_TYPE_P (TREE_TYPE (*expr_p))
972 && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*expr_p))))
974 *expr_p = TREE_OPERAND (*expr_p, 0);
978 /* Generify the MODIFY_EXPR node of the 'shared' value
979 pointed to by EXPR_P. If the target of the assignment
980 is a UPC 'shared' reference, or an indirection via a UPC
981 pointer-to-shared, the assignment statement is rewritten into
982 a call to a runtime routine that does a remote 'put'.
983 If WANT_VALUE is set, then return a compound expression
984 that evaluates to the value of the source operand. */
986 static void
987 upc_genericize_modify_expr (location_t loc, tree *expr_p, int want_value)
989 const tree dest = TREE_OPERAND (*expr_p, 0);
990 tree src = TREE_OPERAND (*expr_p, 1);
991 if (TREE_SHARED (dest)
992 || (TREE_TYPE (dest) && upc_shared_type_p (TREE_TYPE (dest))))
994 /* <shared dest> = <(shared|unshared) src> */
995 *expr_p = upc_expand_put (loc, dest, src, want_value);
997 else if (TREE_SHARED (src)
998 || (TREE_TYPE (src) && upc_shared_type_p (TREE_TYPE (src))))
1000 /* <unshared dest> = <shared src> */
1001 /* We could check for BLKmode and in
1002 that case perform a upc_memget() here. */
1003 src = upc_expand_get (loc, src, want_value);
1004 TREE_OPERAND (*expr_p, 1) = src;
1008 typedef struct walk_data_struct
1010 int want_value;
1011 } walk_data_t;
1012 typedef walk_data_t *walk_data_p;
1014 /* This routine is called to convert UPC specific constructs
1015 into GENERIC. It is called from 'walk_tree' as it traverses
1016 the function body.
1018 The DATA parameter will point to a 'walk_data_t'
1019 structure, which presently has a single field,
1020 'want_value'. If 'want_value' is non-zero, it
1021 indicates that the value of the expression should
1022 be returned. */
1024 static tree
1025 upc_genericize_expr (tree *expr_p, int *walk_subtrees, void *data)
1027 const walk_data_p wdata = (walk_data_p) data;
1028 const tree expr = *expr_p;
1029 const enum tree_code code = TREE_CODE (expr);
1030 const tree type = CODE_CONTAINS_STRUCT (code, TS_TYPED)
1031 ? TREE_TYPE (expr) : NULL;
1032 const int want_value = wdata->want_value
1033 && !(type && VOID_TYPE_P (type));
1034 const tree op0 = (TREE_CODE_LENGTH (code) >= 1)
1035 ? TREE_OPERAND (expr, 0) : NULL_TREE;
1036 const tree type0 = (op0 != NULL_TREE) ? TREE_TYPE (op0) : NULL_TREE;
1037 tree op1 = (TREE_CODE_LENGTH (code) >= 2)
1038 ? TREE_OPERAND (expr, 1) : NULL_TREE;
1039 tree type1 = (op1 != NULL_TREE) ? TREE_TYPE (op1) : NULL_TREE;
1040 location_t saved_location = input_location;
1041 location_t loc;
1042 if (EXPR_HAS_LOCATION (expr))
1043 input_location = EXPR_LOCATION (expr);
1044 loc = input_location;
1045 switch (code)
1047 case UPC_FORALL_STMT:
1048 upc_genericize_forall_stmt (expr_p);
1049 break;
1051 case UPC_SYNC_STMT:
1052 upc_genericize_sync_stmt (loc, expr_p);
1053 break;
1055 case ADDR_EXPR:
1056 if (POINTER_TYPE_P (type) && TREE_TYPE (type)
1057 && upc_shared_type_p (TREE_TYPE (type)))
1058 upc_genericize_addr_expr (loc, expr_p);
1059 break;
1061 case ARRAY_REF:
1062 case ARRAY_RANGE_REF:
1063 if (op0 && TREE_SHARED (op0))
1064 upc_genericize_array_ref (loc, expr_p);
1065 break;
1067 case BIT_FIELD_REF:
1068 case COMPONENT_REF:
1069 if (op0 && TREE_SHARED (op0))
1070 upc_genericize_field_ref (loc, expr_p);
1071 break;
1073 case INDIRECT_REF:
1074 if (type0 && (TREE_CODE (type0) == POINTER_TYPE)
1075 && upc_shared_type_p (TREE_TYPE (type0)))
1076 upc_genericize_indirect_ref (loc, expr_p);
1077 break;
1079 case REALPART_EXPR:
1080 case IMAGPART_EXPR:
1081 if (op0 && TREE_SHARED (op0))
1082 upc_genericize_real_imag_ref (loc, expr_p);
1083 break;
1085 case VAR_DECL:
1086 if (type && upc_shared_type_p (type))
1087 upc_genericize_shared_var_ref (loc, expr_p);
1088 break;
1090 case VIEW_CONVERT_EXPR:
1091 if (type && upc_shared_type_p (type))
1092 TREE_TYPE (expr) = build_upc_unshared_type (type);
1093 gcc_assert (!TREE_SHARED (expr));
1094 break;
1096 case NON_LVALUE_EXPR:
1097 case NOP_EXPR:
1098 case CONVERT_EXPR:
1099 /* Conversions to a UPC shared type aren't valid.
1100 The front-end will sometimes convert
1101 an expression operand to the type of another
1102 operand. If that operand has UPC shared type,
1103 then the conversion target type is 'shared' qualified.
1104 We unshare the type in order to produce a
1105 valid tree. */
1106 if (type && upc_shared_type_p (type))
1107 TREE_TYPE (expr) = build_upc_unshared_type (type);
1108 if (upc_pts_cvt_op_p (expr))
1109 upc_genericize_pts_cvt (loc, expr_p);
1110 else if (code == CONVERT_EXPR && TREE_CODE (type) == INTEGER_TYPE
1111 && POINTER_TYPE_P (type0)
1112 && upc_shared_type_p (TREE_TYPE (type0)))
1113 upc_genericize_pts_to_int_cvt (loc, expr_p);
1114 break;
1116 case EQ_EXPR:
1117 case GE_EXPR:
1118 case GT_EXPR:
1119 case LE_EXPR:
1120 case LT_EXPR:
1121 case NE_EXPR:
1122 if ((type0 && (TREE_CODE (type0) == POINTER_TYPE)
1123 && upc_shared_type_p (TREE_TYPE (type0)))
1124 || (type1 && (TREE_CODE (type1) == POINTER_TYPE)
1125 && upc_shared_type_p (TREE_TYPE (type1))))
1126 upc_genericize_pts_cond_expr (loc, expr_p);
1127 break;
1129 case MINUS_EXPR:
1130 case PLUS_EXPR:
1131 case POINTER_PLUS_EXPR:
1132 if ((type0 && (TREE_CODE (type0) == POINTER_TYPE)
1133 && upc_shared_type_p (TREE_TYPE (type0)))
1134 || (type1 && (TREE_CODE (type1) == POINTER_TYPE)
1135 && upc_shared_type_p (TREE_TYPE (type1))))
1136 upc_genericize_pts_arith_expr (loc, expr_p);
1137 break;
1139 case MODIFY_EXPR:
1140 case INIT_EXPR:
1141 if (POINTER_TYPE_P (type0) && upc_shared_type_p (TREE_TYPE (type0))
1142 && VOID_TYPE_P (TREE_TYPE (type0))
1143 && TREE_CODE (op1) == CONVERT_EXPR
1144 && POINTER_TYPE_P (type1) && VOID_TYPE_P (TREE_TYPE (type1)))
1146 upc_strip_useless_generic_pts_cvt (&TREE_OPERAND (expr, 1));
1147 /* Recalculate OP1 and TYPE1 because TREE_OPERAND (expr, 1)
1148 was rewritten, above. */
1149 op1 = TREE_OPERAND (expr, 1);
1150 type1 = TREE_TYPE (op1);
1152 if ((op0 && (TREE_SHARED (op0)
1153 || (type0 && upc_shared_type_p (type0))))
1154 || (op1 && (TREE_SHARED (op1)
1155 || (type1 && upc_shared_type_p (type1)))))
1156 upc_genericize_modify_expr (loc, expr_p, want_value);
1157 break;
1159 case POSTDECREMENT_EXPR:
1160 case POSTINCREMENT_EXPR:
1161 case PREDECREMENT_EXPR:
1162 case PREINCREMENT_EXPR:
1163 if ((op0 && TREE_SHARED (op0))
1164 || (type0 && (upc_shared_type_p (type0)
1165 || (POINTER_TYPE_P (type0)
1166 && upc_shared_type_p (TREE_TYPE (type0))))))
1167 upc_genericize_shared_inc_dec_expr (loc, expr_p, want_value);
1168 break;
1170 case INTEGER_CST:
1171 /* Integer constants can't be UPC 'shared' qualified.
1172 The front-end can create integer constants with shared
1173 type when changing the type to agree with that of another
1174 expression operand.
1176 Unsharing an integer constant requires special handling
1177 because an internal hash table is kept on a type by type
1178 basis. Thus, we can't rewrite TREE_TYPE() directly.
1179 We re-create the constant with its unshared type to
1180 ensure that the hash table is updated. */
1181 if (type && upc_shared_type_p (type))
1183 const tree u_type = build_upc_unshared_type (type);
1184 *expr_p = build_int_cst_wide (u_type,
1185 TREE_INT_CST_LOW (expr),
1186 TREE_INT_CST_HIGH (expr));
1188 gcc_assert (!TREE_SHARED (expr));
1189 break;
1191 case REAL_CST:
1192 case COMPLEX_CST:
1193 case STRING_CST:
1194 case VECTOR_CST:
1195 case CONSTRUCTOR:
1196 /* A constant's type can't be UPC 'shared' qualified.
1197 The front-end will sometimes convert
1198 an expression operand to the type of another
1199 operand. If that other operand has UPC shared type,
1200 then the converted constant's type will be shared.
1201 We unshare the type in order to produce a
1202 valid constant. */
1203 if (type && upc_shared_type_p (type))
1204 TREE_TYPE (expr) = build_upc_unshared_type (type);
1205 gcc_assert (!TREE_SHARED (expr));
1206 break;
1208 case STATEMENT_LIST:
1209 upc_genericize_stmt_list (expr_p);
1210 *walk_subtrees = 0;
1211 break;
1213 case COMPOUND_EXPR:
1214 upc_genericize_compound_expr (expr_p, want_value);
1215 *walk_subtrees = 0;
1216 break;
1218 case COND_EXPR:
1219 upc_genericize_cond_expr (expr_p, want_value);
1220 *walk_subtrees = 0;
1221 break;
1223 case DECL_EXPR:
1224 upc_genericize_decl_expr (expr_p);
1225 *walk_subtrees = 0;
1226 break;
1228 default:
1229 gcc_assert (!TREE_SHARED (expr));
1230 break;
1233 /* Restore the input location. */
1234 input_location = saved_location;
1236 /* After evaluating the current node, assert the
1237 want_value flag so that all subtrees of this root node
1238 will be fully evaluated. */
1239 if (!wdata->want_value)
1240 wdata->want_value = 1;
1242 /* Continue tree traversal. */
1243 return NULL_TREE;
1246 /* Convert a compound expression into GENERIC form.
1247 A compound expression contains two expressions to compute,
1248 one (the LHS) followed by the other (the RHS).
1249 The LHS value is ignored. The RHS value is used. */
1251 static void
1252 upc_genericize_compound_expr (tree *expr_p, int want_value)
1254 tree *lhs_p = &TREE_OPERAND (*expr_p, 0);
1255 tree *rhs_p = &TREE_OPERAND (*expr_p, 1);
1256 upc_genericize_walk (lhs_p, 0);
1257 upc_genericize_walk (rhs_p, want_value);
1260 /* Convert a conditional expression into GENERIC form.
1261 A conditional expression contains three expressions
1262 and is of the form expression ( ... ? ... : ... in C).
1263 The first operand is the condition, the second is
1264 the then-value and the third is the else-value. */
1266 static void
1267 upc_genericize_cond_expr (tree *expr_p, int want_value)
1269 tree *cond_p = &TREE_OPERAND (*expr_p, 0);
1270 tree *then_p = &TREE_OPERAND (*expr_p, 1);
1271 tree *else_p = &TREE_OPERAND (*expr_p, 2);
1272 upc_genericize_walk (cond_p, 1);
1273 if (*then_p)
1274 upc_genericize_walk (then_p, want_value);
1275 if (*else_p)
1276 upc_genericize_walk (else_p, want_value);
1279 /* Convert a declaration expression into GENERIC form.
1280 A declaration expression is used to represent a local declaration.
1281 The operand refers to the DECL associated with
1282 the given declaration statement. */
1284 static void
1285 upc_genericize_decl_expr (tree *expr_p)
1287 tree decl = DECL_EXPR_DECL (*expr_p);
1288 tree *decl_init_p = &DECL_INITIAL (decl);
1289 if (*decl_init_p)
1290 upc_genericize_walk (decl_init_p, 0);
1293 /* Convert the tree rooted at EXPR_P into GENERIC.
1294 WANT_VALUE is the initial value the flag that
1295 upc_genericize_expr() will query to determine
1296 whether the expression node should return a value.
1297 NOTE: EXPR_P can point to any kind of expression node. */
1299 static void
1300 upc_genericize_walk (tree *expr_p, int want_value)
1302 walk_data_t wdata;
1303 wdata.want_value = want_value;
1304 (void) walk_tree (expr_p, upc_genericize_expr, &wdata, NULL);
1307 /* Convert a statement list to GENERIC. */
1309 static void
1310 upc_genericize_stmt_list (tree *stmt_list_p)
1312 tree_stmt_iterator s = tsi_start (*stmt_list_p);
1313 while (!tsi_end_p (s))
1315 tree *stmt_p = tsi_stmt_ptr (s);
1316 upc_genericize_walk (stmt_p, 0);
1317 tsi_next (&s);
1321 /* Convert the function body identified by BODY_P into GENERIC.
1322 Traverse the function body by calling upc_genericize_walk().
1323 Initially assert WANT_VALUE as FALSE. */
1325 static void
1326 upc_genericize_body (tree *body_p, tree fndecl)
1328 location_t saved_location = input_location;
1330 timevar_push (TV_TREE_UPC_GENERICIZE);
1332 input_location = DECL_SOURCE_LOCATION (fndecl);
1334 upc_genericize_walk (body_p, /* want_value */ 0);
1336 timevar_pop (TV_TREE_UPC_GENERICIZE);
1338 input_location = saved_location;
1341 /* Convert the function tree rooted at FNDECL into GENERIC.
1342 After some initial set up, call upc_genericize_body()
1343 on the function body. */
1345 static void
1346 upc_genericize_function_tree (tree fndecl)
1348 tree oldfn;
1350 gcc_assert (DECL_SAVED_TREE (fndecl));
1352 oldfn = current_function_decl;
1353 current_function_decl = fndecl;
1354 if (DECL_STRUCT_FUNCTION (fndecl))
1355 push_cfun (DECL_STRUCT_FUNCTION (fndecl));
1356 else
1357 push_struct_function (fndecl);
1359 upc_genericize_body (&DECL_SAVED_TREE (fndecl), fndecl);
1361 if (flag_upc_instrument_functions
1362 && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
1363 && !flag_instrument_functions_exclude_p (fndecl))
1365 upc_instrument_func (fndecl);
1368 current_function_decl = oldfn;
1369 pop_cfun ();
1372 /* Convert the tree representation of FNDECL, along with all nested
1373 functions defined within it, into the GENERIC form. */
1375 static void
1376 upc_genericize_fndecl (tree fndecl)
1378 struct cgraph_node *cgn;
1379 /* Lower this function and any nested functions. */
1380 upc_genericize_function_tree (fndecl);
1381 cgn = cgraph_get_create_node (fndecl);
1382 for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
1383 upc_genericize_fndecl (cgn->decl);
1386 /* Convert the tree representation of FNDECL built by the UPC front-end
1387 into the GENERIC form. Then call the "C" genericize hook. */
1389 void
1390 upc_genericize (tree fndecl)
1392 upc_genericize_fndecl (fndecl);
1393 c_genericize (fndecl);
1396 void
1397 upc_genericize_finish (void)
1399 upc_free_unshared_var_table ();
1402 void
1403 upc_genericize_init (void)
1405 unshared_vars = htab_create_ggc (101, uid_tree_map_hash,
1406 uid_tree_map_eq, NULL);
1409 #include "gt-upc-upc-genericize.h"