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)
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/>. */
25 #include "coretypes.h"
36 #include "insn-flags.h"
38 #include "c-family/c-common.h"
39 #include "c-family/c-pragma.h"
40 #include "c-family/c-upc.h"
45 #include "gimple-low.h"
47 #include "tree-check.h"
49 #include "tree-iterator.h"
55 #include "upc-rts-names.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
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. */
119 upc_create_tmp_var (tree type
)
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
);
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. */
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
));
153 get_lc_mode_name (char *mname
, enum machine_mode mode
)
156 const char *m_upper
= GET_MODE_NAME (mode
);
158 *m
++ = TOLOWER (*m_upper
++);
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
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" : "",
191 ? (doprofcall
? "5" : "3")
192 : (doprofcall
? "3" : "2"));
193 libfunc
= identifier_global_value (get_identifier (libfunc_name
));
195 internal_error ("UPC runtime function %s not found", libfunc_name
);
196 if (op_mode
== BLKmode
)
198 tree size
= size_in_bytes (result_type
);
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
,
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
);
215 lib_args
= tree_cons (NULL_TREE
, src_addr
, NULL_TREE
);
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
);
223 if (want_stable_value
)
225 tree result_tmp_init_expr
;
226 result_tmp
= upc_copy_value_to_tmp_var (&result_tmp_init_expr
,
228 result
= build2 (COMPOUND_EXPR
, result_type
,
229 result_tmp_init_expr
, result_tmp
);
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. */
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
);
268 src
= upc_copy_value_to_tmp_var (&src_tmp_init_expr
, src
);
269 lib_args
= tree_cons (NULL_TREE
, dest_addr
, NULL_TREE
);
272 sprintf (libfunc_name
, "__copy%s%sblk%s",
273 strict_mode
? "s" : "",
274 doprofcall
? "g" : "",
275 doprofcall
? "5" : "3");
279 get_lc_mode_name (mname
, op_mode
);
280 sprintf (libfunc_name
, "__put%s%s%s%s",
281 strict_mode
? "s" : "",
282 doprofcall
? "g" : "",
285 ? (doprofcall
? "5" : "3")
286 : (doprofcall
? "4" : "2"));
288 libfunc
= identifier_global_value (get_identifier (libfunc_name
));
290 internal_error ("UPC runtime function %s not found", libfunc_name
);
291 if (op_mode
== BLKmode
)
293 const tree size
= tree_expr_size (src
);
296 src_addr
= upc_shared_addr_rep (loc
, src
);
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
)));
303 lib_args
= upc_gasp_add_src_args (lib_args
, src_filename
, src_line
);
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",
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
));
321 lib_args
= upc_gasp_add_src_args (lib_args
, src_filename
, src_line
);
323 result
= build_function_call (loc
, libfunc
, lib_args
);
325 result
= build2 (COMPOUND_EXPR
, TREE_TYPE (src
), result
, src
);
327 result
= build2 (COMPOUND_EXPR
, TREE_TYPE (result
),
328 src_tmp_init_expr
, 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. */
336 upc_make_bit_field_ref (tree inner
, tree type
, int bitsize
, int bitpos
)
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
));
353 /* On entry, EXP points to a shared field reference
354 or array reference. Simplify it so that is in
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
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;
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
);
379 t_offset
= size_int (bitpos
/ BITS_PER_UNIT
);
381 t_offset
= fold (build_binary_op (loc
, PLUS_EXPR
,
382 offset
, t_offset
, 0));
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
);
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
))
418 gcc_assert (shared_quals
& TYPE_QUAL_SHARED
);
419 ref_type
= c_build_qualified_type_1 (ref_type
, shared_quals
,
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
);
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. */
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
);
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
);
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. */
471 uid_tree_map_hash (const void *p
)
473 const struct uid_tree_map
*const map
= (const struct uid_tree_map
*) p
;
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. */
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. */
495 lookup_unshared_var (const tree var
)
497 const struct uid_tree_map
*h
;
498 struct uid_tree_map in
;
500 gcc_assert (var
&& TREE_CODE (var
) == VAR_DECL
);
501 uid
= DECL_UID (var
);
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'. */
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. */
534 map_unshared_var (const tree var
, const tree u_var
)
536 struct uid_tree_map
*h
;
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 ();
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. */
562 unshared_var_addr (location_t loc
, const tree var
)
564 tree unshared_var
, addr
;
565 unshared_var
= lookup_unshared_var (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;
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. */
584 upc_free_unshared_var_table (void)
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}. */
597 upc_build_shared_var_addr (location_t loc
, tree var
)
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. */
611 identifier_global_value (get_identifier ("__upc_shared_start"));
612 if (!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);
628 val
= (*upc_pts
.build
) (loc
, build_pointer_type (TREE_TYPE (var
)),
629 var_addr
, integer_zero_node
, integer_zero_node
);
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. */
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
));
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. */
652 upc_shared_addr (location_t loc
, tree exp
)
655 const enum tree_code code
= TREE_CODE (exp
);
660 addr
= upc_build_shared_var_addr (loc
, exp
);
664 ref
= upc_simplify_shared_ref (loc
, exp
);
665 if (TREE_CODE (ref
) == ERROR_MARK
)
667 addr
= build_fold_addr_expr_loc (loc
, ref
);
668 upc_genericize_walk (&addr
, /* want_value */ 1);
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);
676 error ("invalid & operation applied to a UPC shared bit field");
677 return error_mark_node
;
684 /* Rewrite a 'upc_forall' statement into a
685 regular 'for' statement. */
688 upc_genericize_forall_stmt (tree
*expr_p ATTRIBUTE_UNUSED
)
690 /* Handled in c-parser.c. */
694 /* Rewrite a UPC synchronization statement (upc_wait, upc_notify,
695 and upc_barrier) into a call to the runtime. */
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. */
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
;
717 case UPC_SYNC_NOTIFY_OP
:
718 libfunc_name
= doprofcall
? UPC_NOTIFYG_LIBCALL
: UPC_NOTIFY_LIBCALL
;
720 case UPC_SYNC_WAIT_OP
:
721 libfunc_name
= doprofcall
? UPC_WAITG_LIBCALL
: UPC_WAIT_LIBCALL
;
723 case UPC_SYNC_BARRIER_OP
:
724 libfunc_name
= doprofcall
? UPC_BARRIERG_LIBCALL
: UPC_BARRIER_LIBCALL
;
729 libfunc
= identifier_global_value (get_identifier (libfunc_name
));
731 internal_error ("UPC runtime function %s not found", libfunc_name
);
733 sync_id
= build_int_cst (NULL_TREE
, INT_MIN
);
734 lib_args
= tree_cons (NULL_TREE
, sync_id
, NULL_TREE
);
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. */
743 upc_genericize_shared_var_ref (location_t loc
, tree
*expr_p
)
746 *expr_p
= upc_expand_get (loc
, src
, 0);
749 /* Expand & of a UPC shared object into equivalent code. */
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. */
762 upc_genericize_indirect_ref (location_t loc
, tree
*expr_p
)
765 *expr_p
= upc_expand_get (loc
, src
, 0);
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. */
783 upc_genericize_array_ref (location_t loc
, tree
*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
)
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. */
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
814 upc_genericize_pts_to_int_cvt (location_t loc
, tree
*expr_p
)
816 tree pts
, pts_arg
, ref_type
, upc_addrfield
;
819 upc_addrfield
= identifier_global_value (get_identifier ("upc_addrfield"));
821 internal_error ("UPC runtime function `upc_addrfield` not found");
822 pts_p
= &TREE_OPERAND (*expr_p
, 0);
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
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. */
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
;
865 ref
= upc_expand_get (loc
, ref
, 0);
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. */
877 upc_genericize_pts_arith_expr (location_t loc
, tree
*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
);
913 *expr_p
= (*upc_pts
.diff
) (loc
, exp
);
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. */
927 upc_genericize_shared_inc_dec_expr (location_t loc
, tree
*expr_p
,
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
);
943 if (code
== PREDECREMENT_EXPR
|| code
== PREINCREMENT_EXPR
)
944 upc_genericize_modify_expr (loc
, &mod_expr
, 1);
947 upc_genericize_modify_expr (loc
, &mod_expr
, 0);
948 mod_expr
= build2 (COMPOUND_EXPR
, TREE_TYPE (val
), mod_expr
, val
);
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. */
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. */
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
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
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
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
;
1042 if (EXPR_HAS_LOCATION (expr
))
1043 input_location
= EXPR_LOCATION (expr
);
1044 loc
= input_location
;
1047 case UPC_FORALL_STMT
:
1048 upc_genericize_forall_stmt (expr_p
);
1052 upc_genericize_sync_stmt (loc
, expr_p
);
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
);
1062 case ARRAY_RANGE_REF
:
1063 if (op0
&& TREE_SHARED (op0
))
1064 upc_genericize_array_ref (loc
, expr_p
);
1069 if (op0
&& TREE_SHARED (op0
))
1070 upc_genericize_field_ref (loc
, expr_p
);
1074 if (type0
&& (TREE_CODE (type0
) == POINTER_TYPE
)
1075 && upc_shared_type_p (TREE_TYPE (type0
)))
1076 upc_genericize_indirect_ref (loc
, expr_p
);
1081 if (op0
&& TREE_SHARED (op0
))
1082 upc_genericize_real_imag_ref (loc
, expr_p
);
1086 if (type
&& upc_shared_type_p (type
))
1087 upc_genericize_shared_var_ref (loc
, expr_p
);
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
));
1096 case NON_LVALUE_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
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
);
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
);
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
);
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
);
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
);
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
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
));
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
1203 if (type
&& upc_shared_type_p (type
))
1204 TREE_TYPE (expr
) = build_upc_unshared_type (type
);
1205 gcc_assert (!TREE_SHARED (expr
));
1208 case STATEMENT_LIST
:
1209 upc_genericize_stmt_list (expr_p
);
1214 upc_genericize_compound_expr (expr_p
, want_value
);
1219 upc_genericize_cond_expr (expr_p
, want_value
);
1224 upc_genericize_decl_expr (expr_p
);
1229 gcc_assert (!TREE_SHARED (expr
));
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. */
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. */
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. */
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);
1274 upc_genericize_walk (then_p
, want_value
);
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. */
1285 upc_genericize_decl_expr (tree
*expr_p
)
1287 tree decl
= DECL_EXPR_DECL (*expr_p
);
1288 tree
*decl_init_p
= &DECL_INITIAL (decl
);
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. */
1300 upc_genericize_walk (tree
*expr_p
, int want_value
)
1303 wdata
.want_value
= want_value
;
1304 (void) walk_tree (expr_p
, upc_genericize_expr
, &wdata
, NULL
);
1307 /* Convert a statement list to GENERIC. */
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);
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. */
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. */
1346 upc_genericize_function_tree (tree fndecl
)
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
));
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
;
1372 /* Convert the tree representation of FNDECL, along with all nested
1373 functions defined within it, into the GENERIC form. */
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. */
1390 upc_genericize (tree fndecl
)
1392 upc_genericize_fndecl (fndecl
);
1393 c_genericize (fndecl
);
1397 upc_genericize_finish (void)
1399 upc_free_unshared_var_table ();
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"