Integrate GUPC into cc1.
[official-gcc.git] / gcc / c-family / c-upc.c
blob1c317b7a8296ab9b44ae1c08f27496fe94d2fbb8
1 /* c-upc.c: implement UPC-related actions
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
3 2010, 2011
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)
16 any later version.
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/>. */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tree.h"
31 #include "stringpool.h"
32 #include "stor-layout.h"
33 #include "input.h"
34 #include "c/c-tree.h"
35 #include "langhooks.h"
36 #include "flags.h"
37 #include "opts.h"
38 #include "options.h"
39 #include "output.h"
40 #include "toplev.h"
41 #include "attribs.h"
42 #include "basic-block.h"
43 #include "gimple-expr.h"
44 #include "ggc.h"
45 #include "tm.h"
46 #include "function.h"
47 #include "target.h"
48 #include "tree-iterator.h"
49 #include "common/common-target.h"
50 #include "cgraph.h"
51 #include "varasm.h"
52 #include "c-upc.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);
63 void
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. */
75 tree
76 upc_build_pointer_type (tree to_type)
78 enum machine_mode pointer_mode;
79 tree ptr_type;
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)))
85 return 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
91 128 bit structs. */
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);
98 return ptr_type;
101 /* Check the type of the operand passed to a
102 upc_*sizeof () operator.
104 The type must *not* be:
105 - an error mark node
106 - an incomplete type
107 - a function type
108 - a void type
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. */
117 static int
118 upc_sizeof_type_check (const char *op_name, tree type)
120 enum tree_code code = TREE_CODE (type);
121 if (code == ERROR_MARK)
123 return 0;
125 else if (!COMPLETE_TYPE_P (type))
127 lang_hooks.types.incomplete_type_error (NULL_TREE, type);
128 return 0;
130 else if (code == FUNCTION_TYPE)
132 error ("UPC operator %s applied to a function type", op_name);
133 return 0;
135 else if (code == VOID_TYPE)
137 error ("UPC operator %s applied to a void type", op_name);
138 return 0;
140 else if (!upc_shared_type_p (type))
142 error ("UPC operator %s applied to a non-shared type", op_name);
143 return 0;
145 return 1;
148 /* Compute the value of the `upc_blocksizeof' operator.
149 The UPC block size is the value of UPC's "layout qualifier".
150 For example:
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) */
159 tree
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);
167 return block_factor;
170 /* Compute the value of the `upc_elemsizeof' operator. */
172 tree
173 upc_elemsizeof (location_t loc, tree type)
175 tree elem_size;
177 if (!(type && upc_sizeof_type_check ("upc_elemsizeof", type)))
178 return size_int (1);
179 elem_size = c_sizeof (loc, strip_array_types (type));
180 return elem_size;
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. */
192 tree
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;
220 else
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,
243 t_factor),
244 block_factor);
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));
259 return local_size;
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. */
267 static int
268 recursive_count_upc_threads_refs (tree expr)
270 enum tree_code code;
271 int i;
272 int count = 0;
273 if (expr == NULL_TREE)
274 return 0;
275 code = TREE_CODE (expr);
276 switch (TREE_CODE_CLASS (code))
278 case tcc_unary:
279 case tcc_binary:
280 case tcc_comparison:
281 case tcc_expression:
282 case tcc_reference:
283 case tcc_statement:
284 for (i = 0; i < TREE_CODE_LENGTH (code); i++)
285 count += recursive_count_upc_threads_refs (TREE_OPERAND (expr, i));
286 break;
287 case tcc_declaration:
288 if (expr == lookup_name (get_identifier ("THREADS")))
289 count = 1;
290 break;
291 default:
292 break;
294 return count;
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)
314 enum tree_code code;
315 if (expr == NULL_TREE)
316 return 0;
317 if (expr == lookup_name (get_identifier ("THREADS")))
318 return 1;
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));
326 return 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. */
333 void
334 set_upc_threads_refs_to_one (tree *expr)
336 enum tree_code code;
337 int i;
338 if (*expr == NULL_TREE)
339 return;
340 code = TREE_CODE (*expr);
341 switch (TREE_CODE_CLASS (code))
343 case tcc_unary:
344 case tcc_binary:
345 case tcc_comparison:
346 case tcc_expression:
347 case tcc_reference:
348 case tcc_statement:
349 for (i = 0; i < TREE_CODE_LENGTH (code); i++)
350 set_upc_threads_refs_to_one (&TREE_OPERAND (*expr, i));
351 break;
352 case tcc_declaration:
353 if (*expr == lookup_name (get_identifier ("THREADS")))
354 *expr = integer_one_node;
355 break;
356 default:
357 break;
359 return;
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
373 must be equal. */
375 tree
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");
388 return NULL_TREE;
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
397 of an array ref. */
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");
419 return NULL_TREE;
421 if (decl_kind == POINTER_TYPE)
423 error_at (loc, "UPC [*] qualifier may not be used in "
424 "declaration of pointers");
425 return NULL_TREE;
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))
433 block_factor =
434 size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type), elt_size);
435 else
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;
445 else
447 block_factor = size_binop (CEIL_DIV_EXPR,
448 size_binop (FLOOR_DIV_EXPR,
449 TYPE_SIZE (type),
450 elt_size),
451 n_threads);
455 else
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;
469 else
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);
478 return NULL_TREE;
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");
485 return NULL_TREE;
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. */
491 if (block_factor)
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;
507 return block_factor;
510 /* If DECL is a UPC shared variable, make sure that it ends up
511 in the executable file. */
513 void
514 upc_check_decl (tree decl)
516 if (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))
544 case POINTER_TYPE:
545 case REFERENCE_TYPE:
546 return upc_shared_type_p (TREE_TYPE (type));
548 case RECORD_TYPE:
549 case UNION_TYPE:
550 case QUAL_UNION_TYPE:
552 tree fields;
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)))
558 return 1;
559 return 0;
562 case ARRAY_TYPE:
563 /* An array type contains pointers if its element type does. */
564 return upc_contains_pts_refs_p (TREE_TYPE (type));
566 default:
567 return 0;
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. */
576 void
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);
585 #endif
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
596 (TLS) section. */
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;
605 else
606 /* Only the TLS model is currently implemented. */
607 gcc_unreachable ();
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. */
617 tree
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);
652 int i;
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, "
659 "use %qs instead",
660 name, deprecated_stmts[i].correct_id);
661 return 1;
664 return 0;
667 /* Expand the pre/post increment/decrement of UPC pointer-to-shared
668 into its equivalent expression tree. */
670 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);
690 return result;
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. */
702 tree
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);
719 tree result;
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)
733 tree elt_cnt;
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);
744 else
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;
775 return result;
778 /* Return an expression that calculates the difference between
779 two UPC pointers-to-shared values. */
781 tree
782 upc_pts_diff (tree op0, tree op1)
784 const tree target_type = TREE_TYPE (TREE_TYPE (op0));
785 tree result;
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);
799 return result;
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));