Merge trunk version 217032 into gupc branch.
[official-gcc.git] / gcc / c / c-upc-lang.c
blob3b2b6fc5d2e21479160d755c219f4bb26d602340
1 /* c-upc-lang.c: UPC language-specific functions.
2 Copyright (C) 2003-2014 Free Software Foundation, Inc.
3 Contributed by Gary Funck <gary@intrepid.com>
4 and Nenad Vukicevic <nenad@intrepid.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 tree init_func_ptr_type, init_func_addr;
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "tree-upc.h"
29 #include "stringpool.h"
30 #include "tree-iterator.h"
31 #include "c/c-tree.h"
32 #include "ggc.h"
33 #include "stor-layout.h"
34 #include "c-family/c-upc.h"
35 #include "c-family/c-upc-pts.h"
36 #include "c-family/c-upc-low.h"
37 #include "c-family/c-upc-rts-names.h"
38 #include "common/common-target.h"
39 #include "varasm.h"
41 static GTY (()) section *upc_init_array_section;
43 /* Create a static variable of type 'type'.
44 This routine mimics the behavior of 'objc_create_temporary_var'
45 with the change that it creates a static (file scoped) variable. */
46 static tree
47 upc_create_static_var (tree type, const char *name)
49 tree id = get_identifier (name);
50 tree decl = build_decl (input_location, VAR_DECL, id, type);
51 TREE_USED (decl) = 1;
52 TREE_STATIC (decl) = 1;
53 TREE_READONLY (decl) = 1;
54 TREE_THIS_VOLATILE (decl) = 0;
55 TREE_ADDRESSABLE (decl) = 0;
56 DECL_PRESERVE_P (decl) = 1;
57 DECL_ARTIFICIAL (decl) = 1;
58 DECL_EXTERNAL (decl) = 0;
59 DECL_IGNORED_P (decl) = 1;
60 DECL_CONTEXT (decl) = NULL;
61 pushdecl_top_level (decl);
62 return decl;
65 /* Return TRUE if DECL's size is zero,
66 and DECL is a UPC shared array. */
67 bool
68 upc_lang_layout_decl_p (tree decl, tree type)
70 int need_to_size_shared_array_decl = 0;
71 tree t = type;
73 if (decl && DECL_SIZE (decl) == 0)
75 while (t != NULL && TREE_CODE (t) == ARRAY_TYPE
76 && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
77 t = TREE_TYPE (t);
79 if (t && TREE_CODE (t) == ARRAY_TYPE)
81 tree tt = TREE_TYPE (t);
82 tree tt_size = TYPE_SIZE (tt);
83 need_to_size_shared_array_decl =
84 upc_shared_type_p (tt)
85 && tt_size != NULL_TREE
86 && !integer_zerop (tt_size);
89 return need_to_size_shared_array_decl;
92 /* Given that TYPE describes a UPC shared array, and that DECL's size hasn't
93 been calculated, calculate the size of the type and adjust the size
94 attributes in DECL. */
96 void
97 upc_lang_layout_decl (tree decl, tree type)
99 tree t = type;
100 gcc_checking_assert (upc_lang_layout_decl_p (decl, type));
101 while (TREE_CODE (t) == ARRAY_TYPE
102 && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
103 t = TREE_TYPE (t);
106 const tree elt_type = TREE_TYPE (t);
107 const tree elt_size = TYPE_SIZE (elt_type);
108 const tree block_factor = TYPE_HAS_UPC_BLOCK_FACTOR (elt_type)
109 ? convert (bitsizetype, TYPE_UPC_BLOCK_FACTOR (elt_type)) : NULL;
110 if (block_factor && integer_zerop (block_factor))
112 /* Allocate the entire UPC shared array on thread 0. */
113 if (TYPE_HAS_THREADS_FACTOR (type))
115 const tree n_threads =
116 convert (bitsizetype, upc_num_threads ());
117 DECL_SIZE (decl) = size_binop (MULT_EXPR, elt_size, n_threads);
119 else
120 DECL_SIZE (decl) = TYPE_SIZE (type);
122 else
124 const tree t_size = TYPE_SIZE (type);
125 const tree n_elem = size_binop (FLOOR_DIV_EXPR, t_size, elt_size);
126 const tree n_threads = convert (bitsizetype, upc_num_threads ());
127 if (TYPE_HAS_THREADS_FACTOR (type))
129 if (block_factor)
131 const tree blk_size = convert (bitsizetype, block_factor);
132 tree t1, t2;
133 t1 = size_binop (CEIL_DIV_EXPR, n_elem, blk_size);
134 t2 = size_binop (MULT_EXPR, t1, blk_size);
135 DECL_SIZE (decl) = size_binop (MULT_EXPR, t2, elt_size);
137 else
138 DECL_SIZE (decl) = t_size;
140 else
142 /* We want to allocate ceiling (N_ELEM / N_THREADS)
143 elements per thread, where N_ELEM is the total number of
144 elements in the array. If the array is blocked,
145 then we allocate (ceiling (ceiling
146 (N_ELEM / BLOCK_FACTOR) / N_THREADS)
147 * block_factor) * N_ELEM_PER_THREAD. */
148 tree n_elem_per_thread;
149 if (block_factor)
151 tree block_count, blocks_per_thread;
152 block_count = size_binop (CEIL_DIV_EXPR,
153 n_elem, block_factor);
154 blocks_per_thread = size_binop (CEIL_DIV_EXPR,
155 block_count, n_threads);
156 n_elem_per_thread = size_binop (MULT_EXPR,
157 blocks_per_thread,
158 block_factor);
160 else
161 n_elem_per_thread = size_binop (CEIL_DIV_EXPR,
162 n_elem, n_threads);
164 /* In the special case of an array of size 1, we know that
165 we want a constant size no matter what N_THREADS is. Make
166 the size a constant so that declarations of the form:
167 shared int x[1];
168 will work in a dynamic THREADS compilation environment. */
169 if (integer_onep (n_elem))
170 DECL_SIZE (decl) = elt_size;
171 else
172 DECL_SIZE (decl) = size_binop (MULT_EXPR, n_elem_per_thread,
173 elt_size);
176 if (DECL_SIZE_UNIT (decl) == 0)
177 DECL_SIZE_UNIT (decl)
178 = fold_convert (sizetype,
179 size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
180 bitsize_unit_node));
184 /* Initialize the UPC-specific parts of the compiler. */
186 static void
187 upc_parse_init (void)
189 upc_pts_init ();
190 upc_genericize_init ();
194 * Build the internal representation of UPC's pointer-to-shared type.
196 void
197 upc_pts_struct_init_type (void)
199 tree fields = NULL_TREE;
200 tree name = NULL_TREE;
201 tree ref;
202 machine_mode pts_mode;
203 const location_t loc = UNKNOWN_LOCATION;
204 struct c_struct_parse_info *null_struct_parse_info = NULL;
205 int save_pedantic = pedantic;
206 ref = start_struct (loc, RECORD_TYPE, name, &null_struct_parse_info);
207 /* Ensure that shared pointers have twice the alignment of a pointer. */
208 TYPE_ALIGN (ref) = 2 * TYPE_ALIGN (ptr_type_node);
209 TYPE_USER_ALIGN (ref) = 1;
210 name = get_identifier ("vaddr");
211 upc_vaddr_field_node = build_decl (loc, FIELD_DECL, name,
212 build_pointer_type (char_type_node));
213 fields = chainon (fields, upc_vaddr_field_node);
214 DECL_NONADDRESSABLE_P (upc_vaddr_field_node) = 0;
215 DECL_INITIAL (upc_vaddr_field_node) = NULL_TREE;
216 upc_thread_field_node =
217 build_decl (loc, FIELD_DECL, get_identifier ("thread"),
218 c_common_type_for_size (UPC_PTS_THREAD_SIZE, 1));
219 fields = chainon (fields, upc_thread_field_node);
220 if (!(UPC_PTS_THREAD_SIZE % 8))
222 DECL_NONADDRESSABLE_P (upc_thread_field_node) = 0;
223 DECL_INITIAL (upc_thread_field_node) = NULL_TREE;
225 else
227 DECL_NONADDRESSABLE_P (upc_thread_field_node) = 1;
228 DECL_INITIAL (upc_thread_field_node) = size_int (UPC_PTS_THREAD_SIZE);
230 upc_phase_field_node =
231 build_decl (loc, FIELD_DECL, get_identifier ("phase"),
232 c_common_type_for_size (UPC_PTS_PHASE_SIZE, 1));
233 fields = chainon (fields, upc_phase_field_node);
234 if (!(UPC_PTS_PHASE_SIZE % 8))
236 DECL_NONADDRESSABLE_P (upc_phase_field_node) = 0;
237 DECL_INITIAL (upc_phase_field_node) = NULL_TREE;
239 else
241 DECL_NONADDRESSABLE_P (upc_phase_field_node) = 1;
242 DECL_INITIAL (upc_phase_field_node) = size_int (UPC_PTS_PHASE_SIZE);
244 #if !HAVE_UPC_PTS_VADDR_FIRST
245 fields = nreverse (fields);
246 #endif
247 /* avoid spurious complaints regarding the definition
248 * `phase' and `thread'. */
249 pedantic = 0;
250 upc_pts_rep_type_node = finish_struct (loc, ref, fields, NULL_TREE,
251 null_struct_parse_info);
252 pedantic = save_pedantic;
253 gcc_assert (TYPE_SIZE (upc_pts_rep_type_node));
254 gcc_assert (tree_fits_uhwi_p (TYPE_SIZE (upc_pts_rep_type_node)));
255 gcc_assert (tree_to_uhwi (TYPE_SIZE (upc_pts_rep_type_node))
256 == 2 * POINTER_SIZE);
257 pts_mode = mode_for_size_tree (TYPE_SIZE (upc_pts_rep_type_node),
258 MODE_INT, 0);
259 gcc_assert (pts_mode != BLKmode);
260 SET_TYPE_MODE(upc_pts_rep_type_node, pts_mode);
261 record_builtin_type (RID_SHARED, "upc_shared_ptr_t",
262 upc_pts_rep_type_node);
265 /* Build a function that will be called by the UPC runtime
266 to initialize UPC shared variables. STMT_LIST is a
267 list of initialization statements. */
269 void
270 upc_build_init_func (tree stmt_list)
272 tree init_func_id = get_identifier (UPC_INIT_DECLS_FUNC);
273 struct c_declspecs *specs;
274 struct c_typespec void_spec;
275 struct c_declarator *init_func_decl;
276 struct c_arg_info args;
277 tree init_func, fn_body;
278 tree init_func_ptr_type, init_func_addr;
279 location_t loc = input_location;
280 int decl_ok;
281 memset (&void_spec, '\0', sizeof (struct c_typespec));
282 void_spec.kind = ctsk_typedef;
283 void_spec.spec = lookup_name (get_identifier ("void"));
284 specs = declspecs_add_type (loc, build_null_declspecs (), void_spec);
285 init_func_decl = build_id_declarator (init_func_id);
286 init_func_decl->id_loc = loc;
287 memset (&args, '\0', sizeof (struct c_arg_info));
288 args.types = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
289 init_func_decl = build_function_declarator (&args, init_func_decl);
290 decl_ok = start_function (specs, init_func_decl, NULL_TREE);
291 gcc_assert (decl_ok);
292 store_parm_decls ();
293 init_func = current_function_decl;
294 DECL_SOURCE_LOCATION (current_function_decl) = loc;
295 TREE_PUBLIC (current_function_decl) = 0;
296 TREE_USED (current_function_decl) = 1;
297 fn_body = c_begin_compound_stmt (true);
298 append_to_statement_list_force (stmt_list, &fn_body);
299 fn_body = c_end_compound_stmt (loc, fn_body, true);
300 add_stmt (fn_body);
301 finish_function ();
302 gcc_assert (DECL_RTL (init_func));
303 mark_decl_referenced (init_func);
304 DECL_PRESERVE_P (init_func) = 1;
305 init_func_ptr_type = build_pointer_type (TREE_TYPE (init_func));
306 init_func_addr = upc_create_static_var (init_func_ptr_type,
307 "__upc_init_func_addr");
308 DECL_INITIAL (init_func_addr) = build_unary_op (loc, ADDR_EXPR,
309 init_func, 0);
310 set_decl_section_name (init_func_addr, UPC_INIT_ARRAY_SECTION_NAME);
313 /* Enable/Disable UPC keywords.
314 If ENABLE is true, UPC keywords are enabled.
315 If ENABLE is false, UPC keywords are removed from consideration.
316 This routine is used by the implementation of
317 "#pragma upc upc_code" and "#pragma upc c_code" respectively. */
319 void
320 upc_toggle_keywords (bool enable)
322 unsigned int i;
323 tree id;
324 for (i = 0; i < num_c_common_reswords; i++)
326 if (UPC_IS_KEYWORD (c_common_reswords[i].rid))
328 id = get_identifier (c_common_reswords[i].word);
329 C_IS_RESERVED_WORD (id) = enable;
334 /* UPC language-specific initialization. */
336 void
337 upc_lang_init (void)
339 gcc_assert (flag_upc);
340 if (!targetm_common.have_named_sections)
342 fatal_error ("UPC is not implemented on this target; "
343 "the target linker does not support separately "
344 "linked sections");
346 upc_parse_init ();
349 #include "gt-c-c-upc-lang.h"