1 /* upc-act.c: implement UPC-related actions
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4 Free Software Foundation, Inc.
5 Contributed by Gary Funck <gary@intrepid.com>
6 and Nenad Vukicevic <nenad@intrepid.com>.
7 Based on original implementation
8 by Jesse M. Draper <jdraper@super.org>
9 and William W. Carlson <wwc@super.org>.
11 This file is part of GCC.
13 GCC is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3, or (at your option)
18 GCC is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with GCC; see the file COPYING3. If not see
25 <http://www.gnu.org/licenses/>. */
29 #include "coretypes.h"
31 #include "stringpool.h"
32 #include "stor-layout.h"
35 #include "langhooks.h"
42 #include "basic-block.h"
43 #include "gimple-expr.h"
48 #include "tree-iterator.h"
49 #include "common/common-target.h"
51 #include "upc-genericize.h"
53 #include "upc-rts-names.h"
55 #include "c-family/c-common.h"
56 #include "c-family/c-pragma.h"
57 #include "c-family/c-upc.h"
60 /* UPC_PTS is a table of functions that implement various
61 operations on expressions which refer to UPC pointers-to-shared,
62 where their implementation varies with the representation
63 of a pointer-to-shared value. ('packed' or 'struct') */
65 upc_pts_ops_t upc_pts
;
67 static int contains_pts_refs_p (tree
);
68 static int recursive_count_upc_threads_refs (tree
);
69 static void upc_build_init_func (const tree
);
70 static tree
upc_create_static_var (tree
, const char *);
71 static int upc_lang_layout_decl_p (tree
, tree
);
72 static void upc_lang_layout_decl (tree
, tree
);
73 static void upc_parse_init (void);
74 static int upc_sizeof_type_check (const char *, tree
);
75 static void upc_write_init_func (void);
77 static GTY (()) tree upc_init_stmt_list
;
78 static GTY (()) section
*upc_init_array_section
;
79 static GTY ((if_marked ("tree_map_marked_p"),
80 param_is (struct tree_map
)))
81 htab_t upc_block_factor_for_type
;
83 /* Process UPC specific command line switches */
86 upc_handle_option (size_t scode
, const char *arg
, int value
, int kind
,
87 location_t loc
, const struct cl_option_handlers
*handlers
)
89 enum opt_code code
= (enum opt_code
) scode
;
94 result
= c_common_handle_option (scode
, arg
, value
, kind
, loc
,
98 use_upc_dwarf2_extensions
= value
;
101 if ((value
== 1) && (flag_upc_inline_lib
== 1))
102 error ("-fupc-debug is incompatible with -fupc-inline-lib");
103 flag_upc_debug
= value
;
105 case OPT_fupc_inline_lib
:
106 if ((value
== 1) && (flag_upc_instrument
== 1))
107 error ("-fupc-inline-lib is incompatible with -fupc-instrument");
108 if ((value
== 1) && (flag_upc_debug
== 1))
109 error ("-fupc-inline-lib is incompatible with -fupc-debug");
110 flag_upc_inline_lib
= value
;
112 case OPT_fupc_instrument
:
113 if ((value
== 1) && (flag_upc_inline_lib
== 1))
114 error ("-fupc-instrument is incompatible with -fupc-inline-lib");
115 flag_upc_instrument
= value
;
117 case OPT_fupc_instrument_functions
:
118 if ((value
== 1) && (flag_upc_inline_lib
== 1))
120 ("-fupc-instrument-functions is incompatible "
121 "with -fupc-inline-lib");
122 flag_upc_instrument
= value
;
123 flag_upc_instrument_functions
= value
;
125 case OPT_fupc_pthreads_model_tls
:
126 flag_upc_pthreads
= 1;
127 upc_pthreads_model
= upc_pthreads_tls_model
;
129 case OPT_fupc_threads_
:
130 if (value
> UPC_MAX_THREADS
)
132 error ("THREADS value exceeds UPC implementation limit of %d",
136 flag_upc_threads
= value
;
145 /* Generate UPC specific pre-defined macros. */
148 upc_cpp_builtins (cpp_reader
* pfile
)
151 cpp_define (pfile
, "__UPC__=1");
152 cpp_define (pfile
, "__GUPC__=1");
153 /* Define __GCC_UPC__ for backward compatibility. */
154 cpp_define (pfile
, "__GCC_UPC__=1");
155 cpp_define (pfile
, "__UPC_VERSION__=201311L");
156 (void) sprintf (def_buf
, "UPC_MAX_BLOCK_SIZE=%lu",
157 (unsigned long) UPC_MAX_BLOCK_SIZE
);
158 cpp_define (pfile
, def_buf
);
159 #if defined(HAVE_UPC_PTS_PACKED_REP)
160 cpp_define (pfile
, "__UPC_PTS_PACKED_REP__=1");
161 #elif defined(HAVE_UPC_PTS_STRUCT_REP)
162 cpp_define (pfile
, "__UPC_PTS_STRUCT_REP__=1");
163 (void) sprintf (def_buf
, "__UPC_VADDR_TYPE__=%s", UPC_PTS_VADDR_TYPE
);
164 cpp_define (pfile
, def_buf
);
165 (void) sprintf (def_buf
, "__UPC_THREAD_TYPE__=%s", UPC_PTS_THREAD_TYPE
);
166 cpp_define (pfile
, def_buf
);
167 (void) sprintf (def_buf
, "__UPC_PHASE_TYPE__=%s", UPC_PTS_PHASE_TYPE
);
168 cpp_define (pfile
, def_buf
);
169 (void) sprintf (def_buf
, "__UPC_PTS_ALIGN__=%d",
170 (2 * POINTER_SIZE
) / BITS_PER_UNIT
);
171 cpp_define (pfile
, def_buf
);
173 #error cannot determine UPC pointer-to-shared representation
175 #ifdef HAVE_UPC_PTS_VADDR_FIRST
176 cpp_define (pfile
, "__UPC_VADDR_FIRST__=1");
178 (void) sprintf (def_buf
, "__UPC_PTS_SIZE__=%d", UPC_PTS_SIZE
);
179 cpp_define (pfile
, def_buf
);
180 (void) sprintf (def_buf
, "__UPC_VADDR_SIZE__=%d", UPC_PTS_VADDR_SIZE
);
181 cpp_define (pfile
, def_buf
);
182 (void) sprintf (def_buf
, "__UPC_THREAD_SIZE__=%d", UPC_PTS_THREAD_SIZE
);
183 cpp_define (pfile
, def_buf
);
184 (void) sprintf (def_buf
, "__UPC_PHASE_SIZE__=%d", UPC_PTS_PHASE_SIZE
);
185 cpp_define (pfile
, def_buf
);
186 if (flag_upc_threads
)
188 cpp_define (pfile
, "__UPC_STATIC_THREADS__=1");
189 (void) sprintf (def_buf
, "THREADS=%d", flag_upc_threads
);
190 cpp_define (pfile
, def_buf
);
194 cpp_define (pfile
, "__UPC_DYNAMIC_THREADS__=1");
196 if (flag_upc_pthreads
&& (upc_pthreads_model
== upc_pthreads_tls_model
))
198 cpp_define (pfile
, "__UPC_PTHREADS_MODEL_TLS__=1");
200 /* UPC castability library is supported. */
201 cpp_define (parse_in
, "__UPC_CASTABLE__=1");
202 /* Collectives are supported. */
203 cpp_define (parse_in
, "__UPC_COLLECTIVE__=1");
204 /* Wall-clock timers are supported. */
205 cpp_define (parse_in
, "__UPC_TICK__=1");
206 /* If debugging or instrumentation is enabled,
207 then disable inlining of the runtime. */
208 if (flag_upc_debug
|| flag_upc_instrument
)
209 flag_upc_inline_lib
= 0;
210 /* If -f[no-]upc-inline-lib hasn't been asserted, force inlining of the
211 runtime library if optimization is enabled. */
212 if (flag_upc_inline_lib
< 0)
213 flag_upc_inline_lib
= (optimize
>= 1);
214 if (flag_upc_inline_lib
)
215 cpp_define (parse_in
, "__UPC_INLINE_LIB__=1");
216 /* UPC profiling capabilities are implemented. */
217 cpp_define (parse_in
, "__UPC_PUPC__=1");
218 /* UPC profiling instrumentation code will be generated. */
219 if (flag_upc_instrument
)
221 cpp_define (parse_in
, "__UPC_PUPC_INST__=1");
225 /* Initialize the handler table for the UPC pointer-to-shared
226 representation that was selected when the compiler
232 #if HAVE_UPC_PTS_PACKED_REP
233 upc_pts
= upc_pts_packed_ops
;
234 #elif HAVE_UPC_PTS_STRUCT_REP
235 upc_pts
= upc_pts_struct_ops
;
237 # error either HAVE_UPC_PTS_PACKED_REP or HAVE_UPC_PTS_STRUCT_REP must be defined.
239 /* Define the various pre-defined types and values, like 'upc_shared_ptr_t'
240 that depend upon the representation of UPC pointer-to-shared type. */
244 /* Initialize the UPC-specific parts of the compiler.
245 This is called from upc_lang_init(), which in turn
246 called via the LANG_HOOKS_INIT per-language hook. */
249 upc_parse_init (void)
251 set_lang_layout_decl_p (upc_lang_layout_decl_p
);
252 set_lang_layout_decl (upc_lang_layout_decl
);
254 upc_genericize_init ();
255 upc_init_stmt_list
= NULL
;
258 /* Return a UPC pointer-to-shared type with target type, TO_TYPE.
259 If the UPC pointer-to-shared representation has a "register mode",
260 then build a pointer type with that mode. If the UPC pointer-to-shared
261 representation type has BLKmode, then calculate its size based
262 upon the representation type. */
265 upc_build_pointer_type (tree to_type
)
267 enum machine_mode pointer_mode
;
269 if (to_type
== NULL_TREE
|| TREE_CODE (to_type
) == ERROR_MARK
)
270 return error_mark_node
;
271 pointer_mode
= TYPE_MODE (upc_pts_rep_type_node
);
272 ptr_type
= build_pointer_type_for_mode (to_type
, pointer_mode
, false);
273 if (!integer_zerop (TYPE_SIZE (ptr_type
)))
275 /* If the UPC pointer-to-shared representation has a size of zero,
276 then it must have BLKmode. In that case, calculate the sizes
277 and alignment from the underlying representation type. This
278 situation may arise when the 'struct PTS' representation is
279 configured on targets that do not assign TImode to aligned
281 gcc_assert (pointer_mode
== BLKmode
);
282 TYPE_SIZE (ptr_type
) = TYPE_SIZE (upc_pts_rep_type_node
);
283 TYPE_SIZE_UNIT (ptr_type
) = TYPE_SIZE_UNIT (upc_pts_rep_type_node
);
284 TYPE_ALIGN (ptr_type
) = TYPE_ALIGN (upc_pts_rep_type_node
);
285 TYPE_UNSIGNED (ptr_type
) = TYPE_UNSIGNED (upc_pts_rep_type_node
);
286 TYPE_PRECISION (ptr_type
) = TYPE_PRECISION (upc_pts_rep_type_node
);
290 /* For the given kind of UPC synchronization statement given
291 by SYNC_KIND (UPC_SYNC_NOTIFY_OP, UPC_SYNC_WAIT_OP,
292 or UPC_SYNC_BARRIER_OP), build a UPC_SYNC_STMT tree node,
293 and add it to the current statement list. The value of
294 SYNC_EXPR will be non-null if an expression is present
295 in the UPC statement being compiled.
297 If SYNC_EXPR is supplied, it must be assignment compatible
301 upc_build_sync_stmt (location_t loc
, tree sync_kind
, tree sync_expr
)
303 if (sync_expr
!= NULL_TREE
)
305 mark_exp_read (sync_expr
);
306 sync_expr
= c_cvt_expr_for_assign (loc
, integer_type_node
, sync_expr
);
307 if (sync_expr
== error_mark_node
)
309 inform (loc
, "UPC synchronization statement expressions "
310 "must be assignment compatible with type `int'");
311 sync_expr
= NULL_TREE
;
314 return add_stmt (build_stmt (loc
, UPC_SYNC_STMT
, sync_kind
, sync_expr
));
317 /* Check the type of the operand passed to a
318 upc_*sizeof () operator.
320 The type must *not* be:
326 The type *must* be a UPC 'shared' type.
328 UPC defines the following flavors of sizeof operators:
329 upc_blocksizeof, upc_elemsizeof, and upc_localsizeof.
330 These operations have similar syntax and constraints
331 as the "C" language sizeof operator. */
334 upc_sizeof_type_check (const char *op_name
, tree type
)
336 enum tree_code code
= TREE_CODE (type
);
337 if (code
== ERROR_MARK
)
341 else if (!COMPLETE_TYPE_P (type
))
343 c_incomplete_type_error (NULL_TREE
, type
);
346 else if (code
== FUNCTION_TYPE
)
348 error ("UPC operator %s applied to a function type", op_name
);
351 else if (code
== VOID_TYPE
)
353 error ("UPC operator %s applied to a void type", op_name
);
356 else if (!upc_shared_type_p (type
))
358 error ("UPC operator %s applied to a non-shared type", op_name
);
364 /* Compute the value of the `upc_blocksizeof' operator.
365 The UPC block size is the value of UPC's "layout qualifier".
368 Declaration upc_blocksizeof()
369 ----------- ----------------
370 shared int A[5*THREADS]; 1 (default)
371 shared [5] int A[5*THREADS]; 5
372 shared [] int A[5*100]; 0 (indefinite)
373 shared [*] int A[5*THREADS]; 5 (distributed by compiler) */
376 upc_blocksizeof (location_t
ARG_UNUSED (loc
), tree type
)
378 tree block_factor
= size_one_node
;
379 if (!type
|| TREE_CODE (type
) == ERROR_MARK
)
380 return error_mark_node
;
381 if (upc_sizeof_type_check ("upc_blocksizeof", type
))
382 block_factor
= upc_get_block_factor (type
);
386 /* Compute the value of the `upc_elemsizeof' operator. */
389 upc_elemsizeof (location_t loc
, tree type
)
393 if (!(type
&& upc_sizeof_type_check ("upc_elemsizeof", type
)))
395 elem_size
= c_sizeof (loc
, strip_array_types (type
));
399 /* Compute the value of the `upc_localsizeof' operator.
400 Per the language spec:
401 The upc_localsizeof operator returns the size, in bytes, of the
402 local portion of its operand, which may be a shared object or a
403 shared-qualified type. It returns the same value on all threads; the
404 value is an upper bound of the size allocated with affinity to any
405 single thread and may include an unspecified amount of padding. The
406 result of upc_localsizeof is an integer constant. */
409 upc_localsizeof (location_t loc
, tree type
)
411 tree block_factor
, local_size
, total_size
;
413 if (!(type
&& upc_sizeof_type_check ("upc_localsizeof", type
)))
414 return size_one_node
;
416 /* for scalars, return sizeof */
418 if (TREE_CODE (type
) != ARRAY_TYPE
)
419 return c_sizeof (loc
, type
);
421 block_factor
= upc_blocksizeof (loc
, type
);
422 block_factor
= convert (bitsizetype
, block_factor
);
423 total_size
= TYPE_SIZE (type
);
425 if (integer_zerop (block_factor
))
427 /* local size is total size, because the entire
428 object lives on a single thread. This is the
429 case for declarations of types with an "indefinite"
430 layout qualifier. For example, given:
431 shared [] int A[100];
432 the value returned for upc_localsizeof (A)
433 will be: 100 * sizeof (int). */
434 local_size
= total_size
;
438 tree elt_type
, elt_size
, n_elts
;
439 tree t_factor
, n_full_blocks
;
440 tree n_full_blocks_per_thread
, n_elts_in_full_blocks
;
441 tree n_rem_elts
, n_local_elts
;
442 elt_type
= strip_array_types (type
);
443 if (!elt_type
|| TREE_CODE (elt_type
) == ERROR_MARK
)
444 return size_one_node
;
445 elt_size
= TYPE_SIZE (elt_type
);
446 n_elts
= size_binop (EXACT_DIV_EXPR
, total_size
, elt_size
);
447 /* Use the worst case size, if compiling in a dynamic
448 threads environment. The worst case size can
449 be derived by setting T_FACTOR to 1 in the calculations
450 that follow. Otherwise T_FACTOR is equal to THREADS. */
451 t_factor
= flag_upc_threads
? upc_num_threads () : size_one_node
;
452 t_factor
= convert (bitsizetype
, t_factor
);
453 n_full_blocks
= size_binop (FLOOR_DIV_EXPR
, n_elts
, block_factor
);
454 n_full_blocks_per_thread
= size_binop (FLOOR_DIV_EXPR
,
455 n_full_blocks
, t_factor
);
456 n_elts_in_full_blocks
= size_binop (MULT_EXPR
,
457 size_binop (MULT_EXPR
,
458 n_full_blocks_per_thread
,
461 n_rem_elts
= size_binop (MINUS_EXPR
, n_elts
, n_elts_in_full_blocks
);
462 n_local_elts
= size_binop (MULT_EXPR
,
463 n_full_blocks_per_thread
, block_factor
);
464 /* If any elements remain, add a full block size. */
465 if (!integer_zerop (n_rem_elts
))
466 n_local_elts
= size_binop (PLUS_EXPR
, n_local_elts
, block_factor
);
467 local_size
= size_binop (MULT_EXPR
, n_local_elts
, elt_size
);
470 /* Convert local size into bytes, and return result. */
472 local_size
= convert (sizetype
, local_size
);
473 local_size
= size_binop (CEIL_DIV_EXPR
, local_size
,
474 size_int (BITS_PER_UNIT
));
478 /* Traverse the expression and return the number of times
479 THREADS is referenced. This is used to check the restriction
480 on UPC shared array declarations, that the predefined THREADS
481 variable can be mentioned only once. */
484 recursive_count_upc_threads_refs (tree expr
)
489 if (expr
== NULL_TREE
)
491 code
= TREE_CODE (expr
);
492 switch (TREE_CODE_CLASS (code
))
500 for (i
= 0; i
< TREE_CODE_LENGTH (code
); i
++)
501 count
+= recursive_count_upc_threads_refs (TREE_OPERAND (expr
, i
));
503 case tcc_declaration
:
504 if (expr
== lookup_name (get_identifier ("THREADS")))
513 /* Count the number of references to THREADS inside `expr'. */
516 count_upc_threads_refs (tree expr
)
518 return recursive_count_upc_threads_refs (expr
);
521 /* Test that EXPR is an expression tree where THREADS appears on
522 the left or the right hand side of a multiply, in a series
523 of zero or more multiplies. For proper operation, the caller
524 should ensure that THREADS is referenced only once,
525 by calling count_upc_threads_refs () prior to calling this routine. */
528 is_multiple_of_upc_threads (tree expr
)
531 if (expr
== NULL_TREE
)
533 if (expr
== lookup_name (get_identifier ("THREADS")))
535 code
= TREE_CODE (expr
);
536 if (code
== MULT_EXPR
)
537 return is_multiple_of_upc_threads (TREE_OPERAND (expr
, 0))
538 | is_multiple_of_upc_threads (TREE_OPERAND (expr
, 1));
539 if ((code
== NOP_EXPR
) || (code
== NON_LVALUE_EXPR
)
540 || (code
== CONVERT_EXPR
))
541 return is_multiple_of_upc_threads (TREE_OPERAND (expr
, 0));
545 /* Find all references to THREADS and change them into the constant `1'.
546 This is done so that fold () when applied to the dimension of a
547 UPC shared array will yield the local size of the array. */
550 set_upc_threads_refs_to_one (tree
*expr
)
554 if (*expr
== NULL_TREE
)
556 code
= TREE_CODE (*expr
);
557 switch (TREE_CODE_CLASS (code
))
565 for (i
= 0; i
< TREE_CODE_LENGTH (code
); i
++)
566 set_upc_threads_refs_to_one (&TREE_OPERAND (*expr
, i
));
568 case tcc_declaration
:
569 if (*expr
== lookup_name (get_identifier ("THREADS")))
570 *expr
= integer_one_node
;
578 /* Return the blocking factor of the UPC shared type, TYPE.
579 If the blocking factor is NULL, then return the default blocking
583 upc_get_block_factor (const tree type
)
585 tree block_factor
= size_one_node
;
586 const tree elt_type
= strip_array_types (type
);
587 if (elt_type
&& (TREE_CODE (elt_type
) != ERROR_MARK
)
588 && TYPE_HAS_BLOCK_FACTOR (elt_type
))
589 block_factor
= TYPE_BLOCK_FACTOR (elt_type
);
593 /* Lookup the UPC block size of TYPE, and return it if we find one. */
596 upc_block_factor_lookup (const_tree type
)
598 struct tree_map
*h
, in
;
605 /* Drop the const qualifier, avoid the warning. */
606 in
.base
.from
= ct_to_t
.t
;
608 h
= (struct tree_map
*)
609 htab_find_with_hash (upc_block_factor_for_type
, &in
, TYPE_HASH (type
));
615 /* Insert a mapping TYPE->BLOCK_FACTOR in the UPC block factor hashtable. */
618 upc_block_factor_insert (tree type
,
624 gcc_assert (type
&& TYPE_P (type
));
625 gcc_assert (block_factor
&& INTEGRAL_TYPE_P (TREE_TYPE (block_factor
)));
626 gcc_assert (!(integer_zerop (block_factor
) || integer_onep (block_factor
)));
627 h
= ggc_alloc_tree_map ();
629 h
->to
= (tree
) block_factor
;
630 loc
= htab_find_slot_with_hash (upc_block_factor_for_type
,
631 h
, TYPE_HASH (type
), INSERT
);
632 *(struct tree_map
**) loc
= h
;
635 /* As part of declaration processing, for a particular kind
636 of declaration, DECL_KIND, and a given LAYOUT_QUALIFIER, calculate
637 the resulting blocking factor and return it. Issue an error
638 diagnostic if the LAYOUT_QUALIFIER specification is invalid.
639 For array types, the TYPE parameter may be the MAIN_VARIANT,
640 and not shared qualified; in that case - ELEM_BLOCK_FACTOR
641 is the blocking factor derived from the original element type.
642 If LAYOUT_QUALIFIER is NULL and ELEM_BLOCK_FACTOR is non-null,
643 then the ELEM_BLOCK_FACTOR will be used. This situation occurs
644 when the element type is a typedef, for example. If both
645 LAYOUT_QUALIFIER and ELEM_BLOCK_FACTOR are non-NULL, then they
649 upc_grok_layout_qualifier (location_t loc
, const enum tree_code decl_kind
,
650 tree type
, tree elem_block_factor
,
651 tree layout_qualifier
)
653 tree block_factor
= NULL_TREE
;
655 if (!type
|| (TREE_CODE (type
) == ERROR_MARK
))
656 return error_mark_node
;
658 if (TREE_CODE (type
) == VOID_TYPE
)
660 error_at (loc
, "UPC layout qualifier cannot be applied to a void type");
664 /* If no explicit layout qualifier was supplied, then
665 use the blocking factor derived from the element type. */
666 if (!layout_qualifier
&& elem_block_factor
)
667 return elem_block_factor
;
669 /* The layout qualifier is given as the subscript operand
671 gcc_assert (layout_qualifier
);
672 gcc_assert (TREE_CODE (layout_qualifier
) == ARRAY_REF
);
673 layout_qualifier
= TREE_OPERAND (layout_qualifier
, 1);
675 if (layout_qualifier
== NULL_TREE
)
677 /* The layout qualifier is [], which is
678 equivalent to specifying [0]. */
679 block_factor
= size_zero_node
;
681 else if ((TREE_CODE (layout_qualifier
) == INDIRECT_REF
)
682 && ((TREE_OPERAND (layout_qualifier
, 0)) == NULL_TREE
))
684 tree elt_size
, elt_type
, n_threads
;
685 /* The layout qualifier is [*]. The compiler must calculate
686 a blocking factor that evenly distributes the array's
687 elements over all the UPC threads. */
688 if (!COMPLETE_TYPE_P (type
))
690 error_at (loc
, "UPC layout qualifier of the form [*] cannot be "
691 "applied to an incomplete type");
694 if (decl_kind
== POINTER_TYPE
)
696 error_at (loc
, "UPC [*] qualifier may not be used in "
697 "declaration of pointers");
700 /* The blocking factor is given by this expression:
701 (sizeof (a) / upc_elemsizeof (a) + (THREADS - 1)) / THREADS,
702 where 'a' is the array being distributed. */
703 elt_type
= strip_array_types (type
);
704 elt_size
= TYPE_SIZE (elt_type
);
705 if (TYPE_HAS_THREADS_FACTOR (type
))
707 size_binop (FLOOR_DIV_EXPR
, TYPE_SIZE (type
), elt_size
);
710 n_threads
= convert (bitsizetype
, upc_num_threads ());
711 if (TREE_CODE (n_threads
) != INTEGER_CST
)
713 error_at (loc
, "a UPC layout qualifier of '[*]' requires that "
714 "the array size is either an integral constant "
715 "or an integral multiple of THREADS");
716 block_factor
= size_one_node
;
720 block_factor
= size_binop (CEIL_DIV_EXPR
,
721 size_binop (FLOOR_DIV_EXPR
,
730 STRIP_NOPS (layout_qualifier
);
731 if (TREE_CODE (layout_qualifier
) != INTEGER_CST
)
733 error_at (loc
, "UPC layout qualifier is not an integral constant");
734 block_factor
= size_one_node
;
736 else if (tree_to_shwi (layout_qualifier
) < 0)
738 error_at (loc
, "UPC layout qualifier must be a non-negative "
739 "integral constant");
740 block_factor
= size_one_node
;
743 block_factor
= fold (layout_qualifier
);
746 if (TREE_OVERFLOW_P (block_factor
)
747 || tree_to_uhwi (block_factor
) > UPC_MAX_BLOCK_SIZE
)
749 error_at (loc
, "the maximum UPC block size in this implementation "
750 "is %ld", (long int) UPC_MAX_BLOCK_SIZE
);
754 if (tree_int_cst_compare (block_factor
, integer_zero_node
) < 0)
756 error_at (loc
, "UPC layout qualifier must be a "
757 "non-negative integral constant");
761 /* Make sure that the UPC blocking factors are of type
762 'size_t' so that a compare of the tree pointers
763 is sufficient to match block sizes. */
765 block_factor
= convert (sizetype
, block_factor
);
767 if ((block_factor
&& elem_block_factor
)
768 && block_factor
!= elem_block_factor
)
770 error_at (loc
, "UPC layout qualifier is incompatible with "
771 "the referenced type");
772 return elem_block_factor
;
775 /* A block size of [1] is the same as specifying no
776 block size at all. */
777 if (block_factor
== size_one_node
)
778 block_factor
= NULL_TREE
;
783 /* If DECL is a UPC shared variable, make sure that it ends up
784 in the executable file. */
787 upc_check_decl (tree decl
)
790 && TREE_CODE (decl
) == VAR_DECL
791 && TREE_TYPE (decl
) && upc_shared_type_p (TREE_TYPE (decl
)))
793 TREE_USED (decl
) = 1;
794 TREE_ADDRESSABLE (decl
) = 1;
795 TREE_STATIC (decl
) = 1;
796 /* Work-around a problem where the front-end doesn't
797 properly process the used flags set above, on
798 static variables when flag_unit_at_a_time isn't set. */
799 if ((TREE_STATIC (decl
) && !DECL_EXTERNAL (decl
))
800 && !flag_unit_at_a_time
801 && !lookup_attribute ("used", DECL_ATTRIBUTES (decl
)))
803 tree used_id
= get_identifier ("used");
804 tree used_attrib
= tree_cons (used_id
, NULL_TREE
, NULL_TREE
);
805 decl_attributes (&decl
, used_attrib
, 0);
810 /* Return TRUE if TYPE contains any references to UPC pointers-to-shared. */
813 contains_pts_refs_p (tree type
)
815 switch (TREE_CODE (type
))
819 return upc_shared_type_p (TREE_TYPE (type
));
823 case QUAL_UNION_TYPE
:
826 /* For a type that has fields, see if the fields have pointers. */
827 for (fields
= TYPE_FIELDS (type
); fields
;
828 fields
= TREE_CHAIN (fields
))
829 if (TREE_CODE (fields
) == FIELD_DECL
830 && contains_pts_refs_p (TREE_TYPE (fields
)))
836 /* An array type contains pointers if its element type does. */
837 return contains_pts_refs_p (TREE_TYPE (type
));
844 /* Return TRUE if either DECL's type is a UPC shared type, or if
845 the value on the right-hand-side of the initialization has a
846 type that is a UPC shared type. Initializations that meet
847 this criteria generally need to be actively initialized
851 upc_check_decl_init (tree decl
, tree init
)
854 int is_shared_var_decl_init
;
855 int is_decl_init_with_shared_addr_refs
;
857 if (!(decl
&& init
&& TREE_TYPE (decl
) && TREE_TYPE (init
)))
859 if ((TREE_CODE (decl
) == ERROR_MARK
)
860 || (TREE_CODE (TREE_TYPE (decl
)) == ERROR_MARK
)
861 || (TREE_CODE (init
) == ERROR_MARK
)
862 || (TREE_CODE (TREE_TYPE (init
)) == ERROR_MARK
))
864 init_type
= TREE_TYPE (init
);
865 is_shared_var_decl_init
= (TREE_CODE (decl
) == VAR_DECL
)
866 && TREE_TYPE (decl
) && upc_shared_type_p (TREE_TYPE (decl
));
867 is_decl_init_with_shared_addr_refs
= TREE_STATIC (decl
)
868 && contains_pts_refs_p (init_type
);
869 is_upc_decl
= (is_shared_var_decl_init
870 || is_decl_init_with_shared_addr_refs
);
874 /* Add the initialization statement:
876 onto a list, `upc_init_stmt_list', which collects
877 initializations that must be made at runtime.
879 This runtime initialization necessary because, in general, UPC
880 shared addresses are not known, or cannot be easily generated
884 upc_decl_init (tree decl
, tree init
)
887 if (TREE_CODE (init
) == ERROR_MARK
)
889 if (TREE_CODE (TREE_TYPE (decl
)) == ARRAY_TYPE
)
891 error ("initialization of UPC shared arrays "
892 "is currently not supported");
895 if (!upc_init_stmt_list
)
896 upc_init_stmt_list
= alloc_stmt_list ();
897 init_stmt
= build2 (INIT_EXPR
, void_type_node
, decl
, init
);
898 append_to_statement_list_force (init_stmt
, &upc_init_stmt_list
);
901 /* Return TRUE if DECL's size is zero,
902 and DECL is a UPC shared array. */
905 upc_lang_layout_decl_p (tree decl
, tree type
)
907 int need_to_size_shared_array_decl
= 0;
910 if (decl
&& DECL_SIZE (decl
) == 0)
912 while (t
!= NULL
&& TREE_CODE (t
) == ARRAY_TYPE
913 && TREE_CODE (TREE_TYPE (t
)) == ARRAY_TYPE
)
916 need_to_size_shared_array_decl
= t
&& TREE_CODE (t
) == ARRAY_TYPE
917 && upc_shared_type_p (TREE_TYPE (t
));
920 return need_to_size_shared_array_decl
;
923 /* Assign DECL to a specific linker section, if required.
924 UPC shared variables are given their own link section on
925 most target platforms, and if compiling in "pthreads mode"
926 regular local file scope variables are made thread local. */
929 upc_set_decl_section (tree decl
)
931 if (TREE_SHARED (decl
))
933 #ifdef UPC_SHARED_SECTION_NAME
934 /* UPC shared variables are placed in their own shared section */
935 int slen
= strlen (UPC_SHARED_SECTION_NAME
);
936 DECL_SECTION_NAME (decl
) = build_string (slen
, UPC_SHARED_SECTION_NAME
);
939 else if (flag_upc_pthreads
940 && ((TREE_STATIC (decl
) && (DECL_SECTION_NAME (decl
) == NULL_TREE
))
941 || DECL_EXTERNAL (decl
)))
943 /* If we're compiling with -fupc-pthreads-model-tls asserted
944 and this is a regular "C" static scoped object which
945 is either declared in a system header file,
946 or is being compiled in a UPC setting,
947 then assign the object to the thread local storage
949 extern int c_header_level
; /* in c-lex.c */
950 if (compiling_upc
&& (c_header_level
<= 0))
952 if (upc_pthreads_model
== upc_pthreads_tls_model
)
954 DECL_TLS_MODEL (decl
) = decl_default_tls_model (decl
);
955 DECL_COMMON (decl
) = 0;
958 /* Only the TLS model is currently implemented. */
964 /* Given that TYPE describes a UPC shared array, and that DECL's size hasn't
965 been calculated, calculate the size of the type and adjust the size
966 attributes in DECL. */
969 upc_lang_layout_decl (tree decl
, tree type
)
973 while (TREE_CODE (t
) == ARRAY_TYPE
974 && TREE_CODE (TREE_TYPE (t
)) == ARRAY_TYPE
)
977 if (TREE_CODE (t
) == ARRAY_TYPE
978 && TYPE_SIZE (type
) != NULL_TREE
979 && !integer_zerop (TYPE_SIZE (type
))
980 && upc_shared_type_p (TREE_TYPE (t
)))
982 const tree elt_type
= TREE_TYPE (t
);
983 const tree elt_size
= TYPE_SIZE (elt_type
);
984 const tree block_factor
= TYPE_HAS_BLOCK_FACTOR (elt_type
)
985 ? convert (bitsizetype
, TYPE_BLOCK_FACTOR (elt_type
)) : NULL
;
986 if (block_factor
&& integer_zerop (block_factor
))
988 /* Allocate the entire UPC shared array on thread 0. */
989 if (TYPE_HAS_THREADS_FACTOR (type
))
991 const tree n_threads
=
992 convert (bitsizetype
, upc_num_threads ());
993 DECL_SIZE (decl
) = size_binop (MULT_EXPR
, elt_size
, n_threads
);
996 DECL_SIZE (decl
) = TYPE_SIZE (type
);
1000 const tree t_size
= TYPE_SIZE (type
);
1001 const tree n_elem
= size_binop (FLOOR_DIV_EXPR
, t_size
, elt_size
);
1002 const tree n_threads
= convert (bitsizetype
, upc_num_threads ());
1003 if (TYPE_HAS_THREADS_FACTOR (type
))
1007 const tree blk_size
= convert (bitsizetype
, block_factor
);
1009 t1
= size_binop (CEIL_DIV_EXPR
, n_elem
, blk_size
);
1010 t2
= size_binop (MULT_EXPR
, t1
, blk_size
);
1011 DECL_SIZE (decl
) = size_binop (MULT_EXPR
, t2
, elt_size
);
1014 DECL_SIZE (decl
) = t_size
;
1018 /* We want to allocate ceiling (N_ELEM / N_THREADS)
1019 elements per thread, where N_ELEM is the total number of
1020 elements in the array. If the array is blocked,
1021 then we allocate (ceiling (ceiling
1022 (N_ELEM / BLOCK_FACTOR) / N_THREADS)
1023 * block_factor) * N_ELEM_PER_THREAD. */
1024 tree n_elem_per_thread
;
1027 tree block_count
, blocks_per_thread
;
1028 block_count
= size_binop (CEIL_DIV_EXPR
,
1029 n_elem
, block_factor
);
1030 blocks_per_thread
= size_binop (CEIL_DIV_EXPR
,
1031 block_count
, n_threads
);
1032 n_elem_per_thread
= size_binop (MULT_EXPR
,
1037 n_elem_per_thread
= size_binop (CEIL_DIV_EXPR
,
1040 /* In the special case of an array of size 1, we know that
1041 we want a constant size no matter what N_THREADS is. Make
1042 the size a constant so that declarations of the form:
1044 will work in a dynamic THREADS compilation environment. */
1045 if (integer_onep (n_elem
))
1046 DECL_SIZE (decl
) = elt_size
;
1048 DECL_SIZE (decl
) = size_binop (MULT_EXPR
, n_elem_per_thread
,
1052 if (DECL_SIZE_UNIT (decl
) == 0)
1053 DECL_SIZE_UNIT (decl
)
1055 fold_convert (sizetype
,
1056 size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
1057 bitsize_unit_node
));
1059 else if (DECL_SIZE (decl
) == 0)
1061 DECL_SIZE (decl
) = TYPE_SIZE (type
);
1062 DECL_SIZE_UNIT (decl
) = TYPE_SIZE_UNIT (type
);
1064 else if (DECL_SIZE_UNIT (decl
) == 0)
1065 DECL_SIZE_UNIT (decl
)
1066 = fold_convert (sizetype
, size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
1067 bitsize_unit_node
));
1070 /* Implement UPC's upc_forall 'affinity' test.
1071 If the type of AFFINITY is a UPC pointer-to-shared type,
1073 upc_threadof (AFFINITY) == MYTHREAD
1074 If AFFINITY is an integer expression, then
1076 (AFFINITY % THREADS) == MYTHREAD */
1079 upc_affinity_test (location_t loc
, tree affinity
)
1084 gcc_assert (affinity
!= NULL_TREE
);
1086 if (TREE_CODE (TREE_TYPE (affinity
)) == POINTER_TYPE
1087 && upc_shared_type_p (TREE_TYPE (TREE_TYPE (affinity
))))
1089 /* We have a pointer to a UPC shared object and the affinity is
1090 determined by the thread component of the address. */
1091 const tree pts_rep
= build1 (VIEW_CONVERT_EXPR
, upc_pts_rep_type_node
,
1092 save_expr (affinity
));
1093 affinity
= (*upc_pts
.threadof
) (loc
, pts_rep
);
1095 else if (TREE_CODE (TREE_TYPE (affinity
)) == INTEGER_TYPE
)
1097 tree n_threads
= upc_num_threads ();
1099 build_binary_op (loc
, FLOOR_MOD_EXPR
, affinity
, n_threads
, 0);
1104 ("UPC affinity expression is neither an integer nor the address of "
1106 return error_mark_node
;
1109 /* Generate an external reference to the "MYTHREAD" identifier. */
1111 mythread
= lookup_name (get_identifier ("MYTHREAD"));
1112 gcc_assert (mythread
!= NULL_TREE
);
1113 assemble_external (mythread
);
1114 TREE_USED (mythread
) = 1;
1116 /* AFFINITY now contains an integer value that can be compared to MY_THREAD.
1117 Create an expression that tests if AFFINITY is equal to MYTHREAD. */
1119 if (!c_types_compatible_p (TREE_TYPE (affinity
), TREE_TYPE (mythread
)))
1120 affinity
= convert (TREE_TYPE (mythread
), affinity
);
1121 affinity_test
= c_objc_common_truthvalue_conversion (loc
,
1122 build_binary_op (loc
, EQ_EXPR
,
1123 affinity
, mythread
, 1));
1124 /* Remove any MAYBE_CONST_EXPR's. */
1126 affinity_test
= c_fully_fold (affinity_test
, false, NULL
);
1128 return affinity_test
;
1131 /* Return an external reference to an integer variable maintained
1132 by the compiler and runtime to track the dynamic nesting
1133 of 'upc_forall' statements. The variable's name is given by
1134 UPC_FORALL_DEPTH_NAME. */
1137 upc_rts_forall_depth_var (void)
1139 tree upc_forall_depth
= lookup_name (
1140 get_identifier (UPC_FORALL_DEPTH_NAME
));
1141 if (upc_forall_depth
== NULL_TREE
)
1142 internal_error ("the UPC runtime variable '" UPC_FORALL_DEPTH_NAME
"' "
1143 "cannot be located; this variable should be defined "
1144 "in a compiler-supplied include file");
1145 assemble_external (upc_forall_depth
);
1146 TREE_USED (upc_forall_depth
) = 1;
1147 return upc_forall_depth
;
1150 /* Check for the possible need to convert UPC-specific types.
1151 This routine must return 0, if it isn't absolutely certain
1152 that the types are equivalent. */
1155 upc_types_compatible_p (tree x
, tree y
)
1157 /* If "C" doesn't think they're compatible neither does UPC. */
1158 if (!c_types_compatible_p (x
, y
))
1160 if (POINTER_TYPE_P (x
) && POINTER_TYPE_P (y
))
1162 const tree ttx
= TREE_TYPE (x
);
1163 const tree tty
= TREE_TYPE (y
);
1164 if (upc_shared_type_p (ttx
) && upc_shared_type_p (tty
))
1166 tree bx
, by
, sx
, sy
;
1167 int x_has_zero_phase
, y_has_zero_phase
;
1169 /* If both types are generic UPC pointers-to-shared,
1170 then they're compatible. */
1171 if (VOID_TYPE_P (ttx
) && VOID_TYPE_P (tty
))
1173 /* Intermediate conversions to (shared void *) (defined
1174 to be a "generic pointer-to-shared" in the UPC
1175 specification) cannot always be optimized away.
1177 p1 = (shared void *) p2;
1178 preserves the phase of p2, when assigning to p1.
1179 We need to be conservative, and not consider conversions
1180 involving a generic UPC pointer-to-shared value to be
1182 if (VOID_TYPE_P (ttx
) != VOID_TYPE_P (tty
))
1184 bx
= upc_get_block_factor (ttx
);
1185 by
= upc_get_block_factor (tty
);
1186 sx
= TYPE_SIZE (ttx
);
1187 sy
= TYPE_SIZE (tty
);
1188 x_has_zero_phase
= (integer_zerop (bx
) || integer_onep (bx
));
1189 y_has_zero_phase
= (integer_zerop (by
) || integer_onep (by
));
1190 /* Normalize type size so that 0 => NULL. */
1191 if (sx
&& integer_zerop (sx
))
1193 if (sy
&& integer_zerop (sy
))
1195 /* If the target types have the same UPC block size
1196 (or they both have a phase value of zero)
1197 and the same size and the target types are
1198 otherwise compatible, then the pointer-to-shared
1199 types are compatible. */
1200 result
= (tree_int_cst_equal (bx
, by
)
1201 || (x_has_zero_phase
&& y_has_zero_phase
))
1202 && tree_int_cst_equal (sx
, sy
);
1205 /* If one operand has a UPC shared type,
1206 and the other operand's type is not a UPC shared type,
1207 then they aren't equivalent. */
1208 else if (upc_shared_type_p (ttx
) != upc_shared_type_p (tty
))
1211 else if (upc_shared_type_p (x
) || upc_shared_type_p (y
))
1213 /* In UPC, blocking factors can be applied to
1214 non-pointer objects/types. They're compatible
1215 if the block sizes are equal. */
1216 const tree bx
= upc_get_block_factor (x
);
1217 const tree by
= upc_get_block_factor (y
);
1218 return tree_int_cst_equal (bx
, by
)
1219 && c_types_compatible_p (TYPE_MAIN_VARIANT (x
),
1220 TYPE_MAIN_VARIANT (y
));
1222 /* C thinks they're compatible, and there are no special
1227 /* Return the value of THREADS.
1229 UPC defines a reserved variable, THREADS, which returns the
1230 number of threads that will be created when the UPC program
1231 executes. The value of threads can be specified at runtime via
1232 the -fupc-threads-N switch, where N is an integer specifying
1233 the number of threads. When the value of THREADS is specified
1234 at compile-time, this is called the "static threads compilation
1237 In the static threads compilation environment, THREADS is a
1238 pre-defined preprocessor macro with the value, N.
1240 If no value for threads is given at compile-time, then the value
1241 must be specified when the application program is executed.
1242 This is method of establishing the value of THREADS is called
1243 the "dynamic threads compilation environment". */
1246 upc_num_threads (void)
1249 n
= flag_upc_threads
? ssize_int (flag_upc_threads
)
1250 : lookup_name (get_identifier ("THREADS"));
1253 error ("the UPC-required THREADS variable is undefined; "
1254 "when compiling pre-processed source, "
1255 "all -fupc-* switches must be passed on the command line, "
1256 "asserting the same values as supplied when the "
1257 "original source file was preprocessed");
1264 /* Diagnose instances of UPC statements that were
1265 defined in very early UPC language specifications and that
1266 have since been deprecated. */
1269 upc_diagnose_deprecated_stmt (location_t loc
, tree id
)
1271 const char *name
= IDENTIFIER_POINTER (id
);
1272 struct deprecated_stmt_entry
1274 const char *deprecated_id
;
1275 const char *correct_id
;
1277 static const struct deprecated_stmt_entry deprecated_stmts
[] =
1278 { {"barrier", "upc_barrier"},
1279 {"barrier_wait", "upc_wait"},
1280 {"barrier_notify", "upc_notify"},
1281 {"fence", "upc_fence"},
1282 {"forall", "upc_forall"} };
1283 const int n_deprecated_stmts
= sizeof (deprecated_stmts
)
1284 / sizeof (struct deprecated_stmt_entry
);
1286 for (i
= 0; i
< n_deprecated_stmts
; ++i
)
1288 if (!strcmp (name
, deprecated_stmts
[i
].deprecated_id
))
1290 error_at (loc
, "%qs was supported in version 1.0 of the UPC "
1291 "specification, it has been deprecated, "
1293 name
, deprecated_stmts
[i
].correct_id
);
1300 /* Expand the pre/post increment/decrement of UPC pointer-to-shared
1301 into its equivalent expression tree. */
1304 upc_pts_increment (location_t location ATTRIBUTE_UNUSED
,
1305 enum tree_code code
, tree arg
)
1307 /* The result type is a pointer of the same type as the argument
1308 type after dropping the shared qualifier (for PTS's that happen
1309 to live in shared memory). */
1310 tree stable_arg
= stabilize_reference (arg
);
1311 tree val
= (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
1312 ? stable_arg
: save_expr (stable_arg
);
1313 enum tree_code incr_op
= (code
== PREINCREMENT_EXPR
1314 || code
== POSTINCREMENT_EXPR
)
1315 ? PLUS_EXPR
: MINUS_EXPR
;
1316 tree incr_val
, result
;
1317 incr_val
= upc_pts_int_sum (location
, incr_op
, val
, integer_one_node
);
1318 TREE_SIDE_EFFECTS (incr_val
) = 1;
1319 result
= build_modify_expr (location
, arg
, NULL_TREE
, NOP_EXPR
,
1320 location
, incr_val
, NULL_TREE
);
1321 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
1322 result
= build2 (COMPOUND_EXPR
, TREE_TYPE (incr_val
), result
, val
);
1326 /* Return an expression that calculates the sum of a UPC
1327 pointer-to-shared value and an integer value. The sum
1328 operator may be PLUS_EXPR or MINUS_EXPR. The result is a
1329 POINTER_PLUS_EXPR with a properly scaled integer operand.
1330 This POINTER_PLUS_EXPR will be translated by the UPC lowering
1331 pass into the sequence of operations dictated both by the
1332 properties of the UPC pointer-to-shared type, and the UPC
1333 pointer-to-shared representation. */
1336 upc_pts_int_sum (location_t loc
,
1337 enum tree_code resultcode
, tree ptrop
, tree intop
)
1340 /* The result type is a pointer of the same type that is being added,
1341 after dropping the UPC shared qualifier. For example, this would
1342 apply to UPC pointers-to-shared that happen to live in shared memory;
1343 the result of the expression must not be UPC shared qualified. */
1345 const tree ttype
= TREE_TYPE (ptrop
);
1346 const int shared_quals
=
1347 (TYPE_QUAL_SHARED
| TYPE_QUAL_STRICT
| TYPE_QUAL_RELAXED
);
1348 const int quals_minus_shared
= TYPE_QUALS (ttype
) & ~shared_quals
;
1349 const tree result_type
= c_build_qualified_type (ttype
, quals_minus_shared
);
1350 const tree result_targ_type
= TREE_TYPE (result_type
);
1351 const tree base_type
= strip_array_types (result_targ_type
);
1354 if (TREE_CODE (result_targ_type
) == VOID_TYPE
)
1355 error_at (loc
, "UPC does not allow a pointer of type %<shared void *%> "
1356 "to be used in arithmetic");
1358 /* We have a pointer to a UPC shared object. For pointers to
1359 simple objects, just build a "resultcode" tree with the intop and
1360 let upc_genericize() handle the arithmetic correctly. For pointers to
1361 arrays, compute the number of elements represented by the intop
1362 and build a "resultcode" tree with the ptrop and that number. */
1364 if (result_targ_type
!= base_type
)
1367 gcc_assert (TREE_CODE (result_targ_type
) == ARRAY_TYPE
);
1368 if (TREE_CODE (TYPE_SIZE (result_targ_type
)) == INTEGER_CST
)
1370 tree n_threads
= convert (sizetype
, upc_num_threads ());
1371 int size
= TREE_INT_CST_LOW (TYPE_SIZE (result_targ_type
));
1372 int elt_size
= TREE_INT_CST_LOW (TYPE_SIZE (base_type
));
1373 elt_cnt
= size_int (size
/ elt_size
);
1374 if (TYPE_HAS_THREADS_FACTOR (result_targ_type
))
1375 elt_cnt
= size_binop (MULT_EXPR
, n_threads
, elt_cnt
);
1379 tree size
= TYPE_SIZE (result_targ_type
);
1380 tree elt_size
= TYPE_SIZE (base_type
);
1381 elt_cnt
= build2 (EXACT_DIV_EXPR
, sizetype
, size
, elt_size
);
1383 intop
= convert (sizetype
, intop
);
1384 intop
= size_binop (MULT_EXPR
, intop
, elt_cnt
);
1386 gcc_assert (resultcode
== PLUS_EXPR
|| resultcode
== MINUS_EXPR
);
1387 if (resultcode
== MINUS_EXPR
)
1388 intop
= build1 (NEGATE_EXPR
, TREE_TYPE (intop
), intop
);
1389 intop
= fold (intop
);
1391 /* POINTER_PLUS expects the operand to be sizetype, which
1392 is potentially unsigned. This will have to be dealt
1393 with later, when expanding the UPC pointer-to-shared arithmetic. */
1395 intop
= convert (sizetype
, intop
);
1396 result
= build2 (POINTER_PLUS_EXPR
, result_type
, ptrop
, intop
);
1398 /* Although there may be some specific cases where the
1399 addition of a constant integer to a UPC pointer-to-shared can
1400 be calculated at compile-time, in the more general
1401 cases the calculation must be made at runtime, so
1402 we mark the resulting sum as non-constant. This will
1403 avoid situations where the compiler attempts to convert
1404 things like &A[14] where A is a shared array into a
1405 compile-time constant. */
1407 TREE_CONSTANT (result
) = 0;
1411 /* Return an expression that calculates the difference between
1412 two UPC pointers-to-shared values. */
1415 upc_pts_diff (tree op0
, tree op1
)
1417 const tree target_type
= TREE_TYPE (TREE_TYPE (op0
));
1420 /* The two pointers must both point to shared objects. */
1422 if ((upc_shared_type_p (target_type
)
1423 && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1
))))
1424 || (upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1
)))
1425 && !upc_shared_type_p (target_type
)))
1427 error ("attempt to take the difference of a UPC pointer-to-shared "
1428 "and a local pointer");
1429 return size_one_node
;
1431 result
= build2 (MINUS_EXPR
, ptrdiff_type_node
, op0
, op1
);
1435 /* Return TRUE if EXP is a null UPC pointer-to-shared value.
1436 (Call the representation-specific hook routine to
1437 perform the check.) */
1440 upc_is_null_pts_p (tree exp
)
1442 return (*upc_pts
.is_null_p
) (exp
);
1445 /* Return TRUE if the type of EXP is a UPC pointer-to-shared type. */
1448 upc_pts_is_valid_p (tree exp
)
1450 tree type
= TREE_TYPE (exp
);
1451 return (TREE_CODE (type
) == POINTER_TYPE
)
1452 && upc_shared_type_p (TREE_TYPE (type
));
1455 /* Create a static variable of type 'type'.
1456 This routine mimics the behavior of 'objc_create_temporary_var'
1457 with the change that it creates a static (file scoped) variable. */
1459 upc_create_static_var (tree type
, const char *name
)
1461 tree id
= get_identifier (name
);
1462 tree decl
= build_decl (input_location
, VAR_DECL
, id
, type
);
1463 TREE_USED (decl
) = 1;
1464 TREE_STATIC (decl
) = 1;
1465 TREE_READONLY (decl
) = 1;
1466 TREE_THIS_VOLATILE (decl
) = 0;
1467 TREE_ADDRESSABLE (decl
) = 0;
1468 DECL_PRESERVE_P (decl
) = 1;
1469 DECL_ARTIFICIAL (decl
) = 1;
1470 DECL_EXTERNAL (decl
) = 0;
1471 DECL_IGNORED_P (decl
) = 1;
1472 DECL_CONTEXT (decl
) = NULL
;
1473 pushdecl_top_level (decl
);
1477 /* Build a function that will be called by the UPC runtime
1478 to initialize UPC shared variables. STMT_LIST is a
1479 list of initialization statements. */
1482 upc_build_init_func (const tree stmt_list
)
1484 tree init_func_id
= get_identifier (UPC_INIT_DECLS_FUNC
);
1485 struct c_declspecs
*specs
;
1486 struct c_typespec void_spec
;
1487 struct c_declarator
*init_func_decl
;
1488 struct c_arg_info args
;
1489 tree init_func
, fn_body
;
1490 tree init_func_ptr_type
, init_func_addr
;
1491 location_t loc
= input_location
;
1493 memset (&void_spec
, '\0', sizeof (struct c_typespec
));
1494 void_spec
.kind
= ctsk_typedef
;
1495 void_spec
.spec
= lookup_name (get_identifier ("void"));
1496 specs
= declspecs_add_type (loc
, build_null_declspecs (), void_spec
);
1497 init_func_decl
= build_id_declarator (init_func_id
);
1498 init_func_decl
->id_loc
= loc
;
1499 memset (&args
, '\0', sizeof (struct c_arg_info
));
1500 args
.types
= tree_cons (NULL_TREE
, void_type_node
, NULL_TREE
);
1501 init_func_decl
= build_function_declarator (&args
, init_func_decl
);
1502 decl_ok
= start_function (specs
, init_func_decl
, NULL_TREE
);
1503 gcc_assert (decl_ok
);
1504 store_parm_decls ();
1505 init_func
= current_function_decl
;
1506 DECL_SOURCE_LOCATION (current_function_decl
) = loc
;
1507 TREE_PUBLIC (current_function_decl
) = 0;
1508 TREE_USED (current_function_decl
) = 1;
1509 fn_body
= c_begin_compound_stmt (true);
1510 append_to_statement_list_force (stmt_list
, &fn_body
);
1511 fn_body
= c_end_compound_stmt (loc
, fn_body
, true);
1514 gcc_assert (DECL_RTL (init_func
));
1515 mark_decl_referenced (init_func
);
1516 DECL_PRESERVE_P (init_func
) = 1;
1517 init_func_ptr_type
= build_pointer_type (TREE_TYPE (init_func
));
1518 init_func_addr
= upc_create_static_var (init_func_ptr_type
,
1519 "__upc_init_func_addr");
1520 DECL_INITIAL (init_func_addr
) = build_unary_op (loc
, ADDR_EXPR
,
1522 DECL_SECTION_NAME (init_func_addr
) = build_string (
1523 strlen (UPC_INIT_ARRAY_SECTION_NAME
),
1524 UPC_INIT_ARRAY_SECTION_NAME
);
1527 /* If the accumulated UPC initialization statement list is
1528 not empty, then build (and define) the per-file UPC
1529 global initialization function. */
1532 upc_write_init_func (void)
1534 if (upc_init_stmt_list
)
1536 int pupc_mode
= disable_pupc_mode ();
1537 upc_build_init_func (upc_init_stmt_list
);
1538 set_pupc_mode (pupc_mode
);
1539 upc_init_stmt_list
= NULL
;
1543 /* Write out the UPC global initialization function, if required
1544 and call upc_genericize_finish() to free the hash table
1545 used to track the "shadow" variables that are created
1546 to generate addresses of UPC shared variables.
1548 This function is called from c_common_parse_file(), just after
1549 parsing the main source file. */
1552 upc_write_global_declarations (void)
1554 upc_write_init_func ();
1555 upc_genericize_finish ();
1558 /* UPC Language-specific 'finish' hook. */
1566 /* UPC language-specific initialization ('init' hook). */
1569 upc_lang_init (void)
1571 if (!targetm_common
.have_named_sections
)
1573 fatal_error ("UPC is not implemented on this target; "
1574 "the target linker does not support separately "
1578 /* c_obj_common_init is also called from regular 'C'
1579 It will return 'false' if we're pre-processing only. */
1581 if (c_objc_common_init () == false)
1584 upc_block_factor_for_type
= htab_create_ggc (512, tree_map_hash
,
1589 #include "gt-upc-upc-act.h"