1 /* c-upc.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"
53 #include "c-upc-gasp.h"
54 #include "c-upc-low.h"
55 #include "c-upc-pts.h"
56 #include "c-upc-pts-ops.h"
57 #include "c-upc-rts-names.h"
60 static int recursive_count_upc_threads_refs (tree
);
61 static int upc_sizeof_type_check (const char *, tree
);
64 upc_block_factor_lookup_init (void)
69 /* Return a UPC pointer-to-shared type with target type, TO_TYPE.
70 If the UPC pointer-to-shared representation has a "register mode",
71 then build a pointer type with that mode. If the UPC pointer-to-shared
72 representation type has BLKmode, then calculate its size based
73 upon the representation type. */
76 upc_build_pointer_type (tree to_type
)
78 enum machine_mode pointer_mode
;
80 if (to_type
== NULL_TREE
|| TREE_CODE (to_type
) == ERROR_MARK
)
81 return error_mark_node
;
82 pointer_mode
= TYPE_MODE (upc_pts_rep_type_node
);
83 ptr_type
= build_pointer_type_for_mode (to_type
, pointer_mode
, false);
84 if (!integer_zerop (TYPE_SIZE (ptr_type
)))
86 /* If the UPC pointer-to-shared representation has a size of zero,
87 then it must have BLKmode. In that case, calculate the sizes
88 and alignment from the underlying representation type. This
89 situation may arise when the 'struct PTS' representation is
90 configured on targets that do not assign TImode to aligned
92 gcc_assert (pointer_mode
== BLKmode
);
93 TYPE_SIZE (ptr_type
) = TYPE_SIZE (upc_pts_rep_type_node
);
94 TYPE_SIZE_UNIT (ptr_type
) = TYPE_SIZE_UNIT (upc_pts_rep_type_node
);
95 TYPE_ALIGN (ptr_type
) = TYPE_ALIGN (upc_pts_rep_type_node
);
96 TYPE_UNSIGNED (ptr_type
) = TYPE_UNSIGNED (upc_pts_rep_type_node
);
97 TYPE_PRECISION (ptr_type
) = TYPE_PRECISION (upc_pts_rep_type_node
);
101 /* Check the type of the operand passed to a
102 upc_*sizeof () operator.
104 The type must *not* be:
110 The type *must* be a UPC 'shared' type.
112 UPC defines the following flavors of sizeof operators:
113 upc_blocksizeof, upc_elemsizeof, and upc_localsizeof.
114 These operations have similar syntax and constraints
115 as the "C" language sizeof operator. */
118 upc_sizeof_type_check (const char *op_name
, tree type
)
120 enum tree_code code
= TREE_CODE (type
);
121 if (code
== ERROR_MARK
)
125 else if (!COMPLETE_TYPE_P (type
))
127 lang_hooks
.types
.incomplete_type_error (NULL_TREE
, type
);
130 else if (code
== FUNCTION_TYPE
)
132 error ("UPC operator %s applied to a function type", op_name
);
135 else if (code
== VOID_TYPE
)
137 error ("UPC operator %s applied to a void type", op_name
);
140 else if (!upc_shared_type_p (type
))
142 error ("UPC operator %s applied to a non-shared type", op_name
);
148 /* Compute the value of the `upc_blocksizeof' operator.
149 The UPC block size is the value of UPC's "layout qualifier".
152 Declaration upc_blocksizeof()
153 ----------- ----------------
154 shared int A[5*THREADS]; 1 (default)
155 shared [5] int A[5*THREADS]; 5
156 shared [] int A[5*100]; 0 (indefinite)
157 shared [*] int A[5*THREADS]; 5 (distributed by compiler) */
160 upc_blocksizeof (location_t
ARG_UNUSED (loc
), tree type
)
162 tree block_factor
= size_one_node
;
163 if (!type
|| TREE_CODE (type
) == ERROR_MARK
)
164 return error_mark_node
;
165 if (upc_sizeof_type_check ("upc_blocksizeof", type
))
166 block_factor
= upc_get_block_factor (type
);
170 /* Compute the value of the `upc_elemsizeof' operator. */
173 upc_elemsizeof (location_t loc
, tree type
)
177 if (!(type
&& upc_sizeof_type_check ("upc_elemsizeof", type
)))
179 elem_size
= c_sizeof (loc
, strip_array_types (type
));
183 /* Compute the value of the `upc_localsizeof' operator.
184 Per the language spec:
185 The upc_localsizeof operator returns the size, in bytes, of the
186 local portion of its operand, which may be a shared object or a
187 shared-qualified type. It returns the same value on all threads; the
188 value is an upper bound of the size allocated with affinity to any
189 single thread and may include an unspecified amount of padding. The
190 result of upc_localsizeof is an integer constant. */
193 upc_localsizeof (location_t loc
, tree type
)
195 tree block_factor
, local_size
, total_size
;
197 if (!(type
&& upc_sizeof_type_check ("upc_localsizeof", type
)))
198 return size_one_node
;
200 /* for scalars, return sizeof */
202 if (TREE_CODE (type
) != ARRAY_TYPE
)
203 return c_sizeof (loc
, type
);
205 block_factor
= upc_blocksizeof (loc
, type
);
206 block_factor
= convert (bitsizetype
, block_factor
);
207 total_size
= TYPE_SIZE (type
);
209 if (integer_zerop (block_factor
))
211 /* local size is total size, because the entire
212 object lives on a single thread. This is the
213 case for declarations of types with an "indefinite"
214 layout qualifier. For example, given:
215 shared [] int A[100];
216 the value returned for upc_localsizeof (A)
217 will be: 100 * sizeof (int). */
218 local_size
= total_size
;
222 tree elt_type
, elt_size
, n_elts
;
223 tree t_factor
, n_full_blocks
;
224 tree n_full_blocks_per_thread
, n_elts_in_full_blocks
;
225 tree n_rem_elts
, n_local_elts
;
226 elt_type
= strip_array_types (type
);
227 if (!elt_type
|| TREE_CODE (elt_type
) == ERROR_MARK
)
228 return size_one_node
;
229 elt_size
= TYPE_SIZE (elt_type
);
230 n_elts
= size_binop (EXACT_DIV_EXPR
, total_size
, elt_size
);
231 /* Use the worst case size, if compiling in a dynamic
232 threads environment. The worst case size can
233 be derived by setting T_FACTOR to 1 in the calculations
234 that follow. Otherwise T_FACTOR is equal to THREADS. */
235 t_factor
= flag_upc_threads
? upc_num_threads () : size_one_node
;
236 t_factor
= convert (bitsizetype
, t_factor
);
237 n_full_blocks
= size_binop (FLOOR_DIV_EXPR
, n_elts
, block_factor
);
238 n_full_blocks_per_thread
= size_binop (FLOOR_DIV_EXPR
,
239 n_full_blocks
, t_factor
);
240 n_elts_in_full_blocks
= size_binop (MULT_EXPR
,
241 size_binop (MULT_EXPR
,
242 n_full_blocks_per_thread
,
245 n_rem_elts
= size_binop (MINUS_EXPR
, n_elts
, n_elts_in_full_blocks
);
246 n_local_elts
= size_binop (MULT_EXPR
,
247 n_full_blocks_per_thread
, block_factor
);
248 /* If any elements remain, add a full block size. */
249 if (!integer_zerop (n_rem_elts
))
250 n_local_elts
= size_binop (PLUS_EXPR
, n_local_elts
, block_factor
);
251 local_size
= size_binop (MULT_EXPR
, n_local_elts
, elt_size
);
254 /* Convert local size into bytes, and return result. */
256 local_size
= convert (sizetype
, local_size
);
257 local_size
= size_binop (CEIL_DIV_EXPR
, local_size
,
258 size_int (BITS_PER_UNIT
));
262 /* Traverse the expression and return the number of times
263 THREADS is referenced. This is used to check the restriction
264 on UPC shared array declarations, that the predefined THREADS
265 variable can be mentioned only once. */
268 recursive_count_upc_threads_refs (tree expr
)
273 if (expr
== NULL_TREE
)
275 code
= TREE_CODE (expr
);
276 switch (TREE_CODE_CLASS (code
))
284 for (i
= 0; i
< TREE_CODE_LENGTH (code
); i
++)
285 count
+= recursive_count_upc_threads_refs (TREE_OPERAND (expr
, i
));
287 case tcc_declaration
:
288 if (expr
== lookup_name (get_identifier ("THREADS")))
297 /* Count the number of references to THREADS inside `expr'. */
300 count_upc_threads_refs (tree expr
)
302 return recursive_count_upc_threads_refs (expr
);
305 /* Test that EXPR is an expression tree where THREADS appears on
306 the left or the right hand side of a multiply, in a series
307 of zero or more multiplies. For proper operation, the caller
308 should ensure that THREADS is referenced only once,
309 by calling count_upc_threads_refs () prior to calling this routine. */
312 is_multiple_of_upc_threads (tree expr
)
315 if (expr
== NULL_TREE
)
317 if (expr
== lookup_name (get_identifier ("THREADS")))
319 code
= TREE_CODE (expr
);
320 if (code
== MULT_EXPR
)
321 return is_multiple_of_upc_threads (TREE_OPERAND (expr
, 0))
322 | is_multiple_of_upc_threads (TREE_OPERAND (expr
, 1));
323 if ((code
== NOP_EXPR
) || (code
== NON_LVALUE_EXPR
)
324 || (code
== CONVERT_EXPR
))
325 return is_multiple_of_upc_threads (TREE_OPERAND (expr
, 0));
329 /* Find all references to THREADS and change them into the constant `1'.
330 This is done so that fold () when applied to the dimension of a
331 UPC shared array will yield the local size of the array. */
334 set_upc_threads_refs_to_one (tree
*expr
)
338 if (*expr
== NULL_TREE
)
340 code
= TREE_CODE (*expr
);
341 switch (TREE_CODE_CLASS (code
))
349 for (i
= 0; i
< TREE_CODE_LENGTH (code
); i
++)
350 set_upc_threads_refs_to_one (&TREE_OPERAND (*expr
, i
));
352 case tcc_declaration
:
353 if (*expr
== lookup_name (get_identifier ("THREADS")))
354 *expr
= integer_one_node
;
362 /* As part of declaration processing, for a particular kind
363 of declaration, DECL_KIND, and a given LAYOUT_QUALIFIER, calculate
364 the resulting blocking factor and return it. Issue an error
365 diagnostic if the LAYOUT_QUALIFIER specification is invalid.
366 For array types, the TYPE parameter may be the MAIN_VARIANT,
367 and not shared qualified; in that case - ELEM_BLOCK_FACTOR
368 is the blocking factor derived from the original element type.
369 If LAYOUT_QUALIFIER is NULL and ELEM_BLOCK_FACTOR is non-null,
370 then the ELEM_BLOCK_FACTOR will be used. This situation occurs
371 when the element type is a typedef, for example. If both
372 LAYOUT_QUALIFIER and ELEM_BLOCK_FACTOR are non-NULL, then they
376 upc_grok_layout_qualifier (location_t loc
, const enum tree_code decl_kind
,
377 tree type
, tree elem_block_factor
,
378 tree layout_qualifier
)
380 tree block_factor
= NULL_TREE
;
382 if (!type
|| (TREE_CODE (type
) == ERROR_MARK
))
383 return error_mark_node
;
385 if (TREE_CODE (type
) == VOID_TYPE
)
387 error_at (loc
, "UPC layout qualifier cannot be applied to a void type");
391 /* If no explicit layout qualifier was supplied, then
392 use the blocking factor derived from the element type. */
393 if (!layout_qualifier
&& elem_block_factor
)
394 return elem_block_factor
;
396 /* The layout qualifier is given as the subscript operand
398 gcc_assert (layout_qualifier
);
399 gcc_assert (TREE_CODE (layout_qualifier
) == ARRAY_REF
);
400 layout_qualifier
= TREE_OPERAND (layout_qualifier
, 1);
402 if (layout_qualifier
== NULL_TREE
)
404 /* The layout qualifier is [], which is
405 equivalent to specifying [0]. */
406 block_factor
= size_zero_node
;
408 else if ((TREE_CODE (layout_qualifier
) == INDIRECT_REF
)
409 && ((TREE_OPERAND (layout_qualifier
, 0)) == NULL_TREE
))
411 tree elt_size
, elt_type
, n_threads
;
412 /* The layout qualifier is [*]. The compiler must calculate
413 a blocking factor that evenly distributes the array's
414 elements over all the UPC threads. */
415 if (!COMPLETE_TYPE_P (type
))
417 error_at (loc
, "UPC layout qualifier of the form [*] cannot be "
418 "applied to an incomplete type");
421 if (decl_kind
== POINTER_TYPE
)
423 error_at (loc
, "UPC [*] qualifier may not be used in "
424 "declaration of pointers");
427 /* The blocking factor is given by this expression:
428 (sizeof (a) / upc_elemsizeof (a) + (THREADS - 1)) / THREADS,
429 where 'a' is the array being distributed. */
430 elt_type
= strip_array_types (type
);
431 elt_size
= TYPE_SIZE (elt_type
);
432 if (TYPE_HAS_THREADS_FACTOR (type
))
434 size_binop (FLOOR_DIV_EXPR
, TYPE_SIZE (type
), elt_size
);
437 n_threads
= convert (bitsizetype
, upc_num_threads ());
438 if (TREE_CODE (n_threads
) != INTEGER_CST
)
440 error_at (loc
, "a UPC layout qualifier of '[*]' requires that "
441 "the array size is either an integral constant "
442 "or an integral multiple of THREADS");
443 block_factor
= size_one_node
;
447 block_factor
= size_binop (CEIL_DIV_EXPR
,
448 size_binop (FLOOR_DIV_EXPR
,
457 STRIP_NOPS (layout_qualifier
);
458 if (TREE_CODE (layout_qualifier
) != INTEGER_CST
)
460 error_at (loc
, "UPC layout qualifier is not an integral constant");
461 block_factor
= size_one_node
;
463 else if (tree_to_shwi (layout_qualifier
) < 0)
465 error_at (loc
, "UPC layout qualifier must be a non-negative "
466 "integral constant");
467 block_factor
= size_one_node
;
470 block_factor
= fold (layout_qualifier
);
473 if (TREE_OVERFLOW_P (block_factor
)
474 || tree_to_uhwi (block_factor
) > UPC_MAX_BLOCK_SIZE
)
476 error_at (loc
, "the maximum UPC block size in this implementation "
477 "is %ld", (long int) UPC_MAX_BLOCK_SIZE
);
481 if (tree_int_cst_compare (block_factor
, integer_zero_node
) < 0)
483 error_at (loc
, "UPC layout qualifier must be a "
484 "non-negative integral constant");
488 /* Make sure that the UPC blocking factors are of type
489 'size_t' so that a compare of the tree pointers
490 is sufficient to match block sizes. */
492 block_factor
= convert (sizetype
, block_factor
);
494 if ((block_factor
&& elem_block_factor
)
495 && block_factor
!= elem_block_factor
)
497 error_at (loc
, "UPC layout qualifier is incompatible with "
498 "the referenced type");
499 return elem_block_factor
;
502 /* A block size of [1] is the same as specifying no
503 block size at all. */
504 if (block_factor
== size_one_node
)
505 block_factor
= NULL_TREE
;
510 /* If DECL is a UPC shared variable, make sure that it ends up
511 in the executable file. */
514 upc_check_decl (tree decl
)
517 && TREE_CODE (decl
) == VAR_DECL
518 && TREE_TYPE (decl
) && upc_shared_type_p (TREE_TYPE (decl
)))
520 TREE_USED (decl
) = 1;
521 TREE_ADDRESSABLE (decl
) = 1;
522 TREE_STATIC (decl
) = 1;
523 /* Work-around a problem where the front-end doesn't
524 properly process the used flags set above, on
525 static variables when flag_unit_at_a_time isn't set. */
526 if ((TREE_STATIC (decl
) && !DECL_EXTERNAL (decl
))
527 && !flag_unit_at_a_time
528 && !lookup_attribute ("used", DECL_ATTRIBUTES (decl
)))
530 tree used_id
= get_identifier ("used");
531 tree used_attrib
= tree_cons (used_id
, NULL_TREE
, NULL_TREE
);
532 decl_attributes (&decl
, used_attrib
, 0);
537 /* Return TRUE if TYPE contains any references to UPC pointers-to-shared. */
540 upc_contains_pts_refs_p (tree type
)
542 switch (TREE_CODE (type
))
546 return upc_shared_type_p (TREE_TYPE (type
));
550 case QUAL_UNION_TYPE
:
553 /* For a type that has fields, see if the fields have pointers. */
554 for (fields
= TYPE_FIELDS (type
); fields
;
555 fields
= TREE_CHAIN (fields
))
556 if (TREE_CODE (fields
) == FIELD_DECL
557 && upc_contains_pts_refs_p (TREE_TYPE (fields
)))
563 /* An array type contains pointers if its element type does. */
564 return upc_contains_pts_refs_p (TREE_TYPE (type
));
571 /* Assign DECL to a specific linker section, if required.
572 UPC shared variables are given their own link section on
573 most target platforms, and if compiling in "pthreads mode"
574 regular local file scope variables are made thread local. */
577 upc_set_decl_section (tree decl
)
579 if (TREE_SHARED (decl
))
581 #ifdef UPC_SHARED_SECTION_NAME
582 /* UPC shared variables are placed in their own shared section */
583 int slen
= strlen (UPC_SHARED_SECTION_NAME
);
584 DECL_SECTION_NAME (decl
) = build_string (slen
, UPC_SHARED_SECTION_NAME
);
587 else if (flag_upc_pthreads
588 && ((TREE_STATIC (decl
) && (DECL_SECTION_NAME (decl
) == NULL_TREE
))
589 || DECL_EXTERNAL (decl
)))
591 /* If we're compiling with -fupc-pthreads-model-tls asserted
592 and this is a regular "C" static scoped object which
593 is either declared in a system header file,
594 or is being compiled in a UPC setting,
595 then assign the object to the thread local storage
597 extern int c_header_level
; /* in c-lex.c */
598 if (flag_upc
&& (c_header_level
<= 0))
600 if (upc_pthreads_model
== upc_pthreads_tls_model
)
602 DECL_TLS_MODEL (decl
) = decl_default_tls_model (decl
);
603 DECL_COMMON (decl
) = 0;
606 /* Only the TLS model is currently implemented. */
612 /* Return an external reference to an integer variable maintained
613 by the compiler and runtime to track the dynamic nesting
614 of 'upc_forall' statements. The variable's name is given by
615 UPC_FORALL_DEPTH_NAME. */
618 upc_rts_forall_depth_var (void)
620 tree upc_forall_depth
= lookup_name (
621 get_identifier (UPC_FORALL_DEPTH_NAME
));
622 if (upc_forall_depth
== NULL_TREE
)
623 internal_error ("the UPC runtime variable '" UPC_FORALL_DEPTH_NAME
"' "
624 "cannot be located; this variable should be defined "
625 "in a compiler-supplied include file");
626 assemble_external (upc_forall_depth
);
627 TREE_USED (upc_forall_depth
) = 1;
628 return upc_forall_depth
;
631 /* Diagnose instances of UPC statements that were
632 defined in very early UPC language specifications and that
633 have since been deprecated. */
636 upc_diagnose_deprecated_stmt (location_t loc
, tree id
)
638 const char *name
= IDENTIFIER_POINTER (id
);
639 struct deprecated_stmt_entry
641 const char *deprecated_id
;
642 const char *correct_id
;
644 static const struct deprecated_stmt_entry deprecated_stmts
[] =
645 { {"barrier", "upc_barrier"},
646 {"barrier_wait", "upc_wait"},
647 {"barrier_notify", "upc_notify"},
648 {"fence", "upc_fence"},
649 {"forall", "upc_forall"} };
650 const int n_deprecated_stmts
= sizeof (deprecated_stmts
)
651 / sizeof (struct deprecated_stmt_entry
);
653 for (i
= 0; i
< n_deprecated_stmts
; ++i
)
655 if (!strcmp (name
, deprecated_stmts
[i
].deprecated_id
))
657 error_at (loc
, "%qs was supported in version 1.0 of the UPC "
658 "specification, it has been deprecated, "
660 name
, deprecated_stmts
[i
].correct_id
);
667 /* Expand the pre/post increment/decrement of UPC pointer-to-shared
668 into its equivalent expression tree. */
671 upc_pts_increment (location_t location ATTRIBUTE_UNUSED
,
672 enum tree_code code
, tree arg
)
674 /* The result type is a pointer of the same type as the argument
675 type after dropping the shared qualifier (for PTS's that happen
676 to live in shared memory). */
677 tree stable_arg
= stabilize_reference (arg
);
678 tree val
= (code
== PREINCREMENT_EXPR
|| code
== PREDECREMENT_EXPR
)
679 ? stable_arg
: save_expr (stable_arg
);
680 enum tree_code incr_op
= (code
== PREINCREMENT_EXPR
681 || code
== POSTINCREMENT_EXPR
)
682 ? PLUS_EXPR
: MINUS_EXPR
;
683 tree incr_val
, result
;
684 incr_val
= upc_pts_int_sum (location
, incr_op
, val
, integer_one_node
);
685 TREE_SIDE_EFFECTS (incr_val
) = 1;
686 result
= build_modify_expr (location
, arg
, NULL_TREE
, NOP_EXPR
,
687 location
, incr_val
, NULL_TREE
);
688 if (code
== POSTINCREMENT_EXPR
|| code
== POSTDECREMENT_EXPR
)
689 result
= build2 (COMPOUND_EXPR
, TREE_TYPE (incr_val
), result
, val
);
693 /* Return an expression that calculates the sum of a UPC
694 pointer-to-shared value and an integer value. The sum
695 operator may be PLUS_EXPR or MINUS_EXPR. The result is a
696 POINTER_PLUS_EXPR with a properly scaled integer operand.
697 This POINTER_PLUS_EXPR will be translated by the UPC lowering
698 pass into the sequence of operations dictated both by the
699 properties of the UPC pointer-to-shared type, and the UPC
700 pointer-to-shared representation. */
703 upc_pts_int_sum (location_t loc
,
704 enum tree_code resultcode
, tree ptrop
, tree intop
)
707 /* The result type is a pointer of the same type that is being added,
708 after dropping the UPC shared qualifier. For example, this would
709 apply to UPC pointers-to-shared that happen to live in shared memory;
710 the result of the expression must not be UPC shared qualified. */
712 const tree ttype
= TREE_TYPE (ptrop
);
713 const int shared_quals
=
714 (TYPE_QUAL_SHARED
| TYPE_QUAL_STRICT
| TYPE_QUAL_RELAXED
);
715 const int quals_minus_shared
= TYPE_QUALS (ttype
) & ~shared_quals
;
716 const tree result_type
= c_build_qualified_type (ttype
, quals_minus_shared
);
717 const tree result_targ_type
= TREE_TYPE (result_type
);
718 const tree base_type
= strip_array_types (result_targ_type
);
721 if (TREE_CODE (result_targ_type
) == VOID_TYPE
)
722 error_at (loc
, "UPC does not allow a pointer of type %<shared void *%> "
723 "to be used in arithmetic");
725 /* We have a pointer to a UPC shared object. For pointers to
726 simple objects, just build a "resultcode" tree with the intop and
727 let upc_genericize() handle the arithmetic correctly. For pointers to
728 arrays, compute the number of elements represented by the intop
729 and build a "resultcode" tree with the ptrop and that number. */
731 if (result_targ_type
!= base_type
)
734 gcc_assert (TREE_CODE (result_targ_type
) == ARRAY_TYPE
);
735 if (TREE_CODE (TYPE_SIZE (result_targ_type
)) == INTEGER_CST
)
737 tree n_threads
= convert (sizetype
, upc_num_threads ());
738 int size
= TREE_INT_CST_LOW (TYPE_SIZE (result_targ_type
));
739 int elt_size
= TREE_INT_CST_LOW (TYPE_SIZE (base_type
));
740 elt_cnt
= size_int (size
/ elt_size
);
741 if (TYPE_HAS_THREADS_FACTOR (result_targ_type
))
742 elt_cnt
= size_binop (MULT_EXPR
, n_threads
, elt_cnt
);
746 tree size
= TYPE_SIZE (result_targ_type
);
747 tree elt_size
= TYPE_SIZE (base_type
);
748 elt_cnt
= build2 (EXACT_DIV_EXPR
, sizetype
, size
, elt_size
);
750 intop
= convert (sizetype
, intop
);
751 intop
= size_binop (MULT_EXPR
, intop
, elt_cnt
);
753 gcc_assert (resultcode
== PLUS_EXPR
|| resultcode
== MINUS_EXPR
);
754 if (resultcode
== MINUS_EXPR
)
755 intop
= build1 (NEGATE_EXPR
, TREE_TYPE (intop
), intop
);
756 intop
= fold (intop
);
758 /* POINTER_PLUS expects the operand to be sizetype, which
759 is potentially unsigned. This will have to be dealt
760 with later, when expanding the UPC pointer-to-shared arithmetic. */
762 intop
= convert (sizetype
, intop
);
763 result
= build2 (POINTER_PLUS_EXPR
, result_type
, ptrop
, intop
);
765 /* Although there may be some specific cases where the
766 addition of a constant integer to a UPC pointer-to-shared can
767 be calculated at compile-time, in the more general
768 cases the calculation must be made at runtime, so
769 we mark the resulting sum as non-constant. This will
770 avoid situations where the compiler attempts to convert
771 things like &A[14] where A is a shared array into a
772 compile-time constant. */
774 TREE_CONSTANT (result
) = 0;
778 /* Return an expression that calculates the difference between
779 two UPC pointers-to-shared values. */
782 upc_pts_diff (tree op0
, tree op1
)
784 const tree target_type
= TREE_TYPE (TREE_TYPE (op0
));
787 /* The two pointers must both point to shared objects. */
789 if ((upc_shared_type_p (target_type
)
790 && !upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1
))))
791 || (upc_shared_type_p (TREE_TYPE (TREE_TYPE (op1
)))
792 && !upc_shared_type_p (target_type
)))
794 error ("attempt to take the difference of a UPC pointer-to-shared "
795 "and a local pointer");
796 return size_one_node
;
798 result
= build2 (MINUS_EXPR
, ptrdiff_type_node
, op0
, op1
);
802 /* Return TRUE if EXP is a null UPC pointer-to-shared value.
803 (Call the representation-specific hook routine to
804 perform the check.) */
807 upc_is_null_pts_p (tree exp
)
809 return (*upc_pts
.is_null_p
) (exp
);
812 /* Return TRUE if the type of EXP is a UPC pointer-to-shared type. */
815 upc_pts_is_valid_p (tree exp
)
817 tree type
= TREE_TYPE (exp
);
818 return (TREE_CODE (type
) == POINTER_TYPE
)
819 && upc_shared_type_p (TREE_TYPE (type
));