]> gcc.gnu.org Git - gcc.git/blame - gcc/c-omp.c
re PR c++/34513 (static variable not found for C++ OpenMP)
[gcc.git] / gcc / c-omp.c
CommitLineData
953ff289
DN
1/* This file contains routines to construct GNU OpenMP constructs,
2 called from parsing in the C and C++ front ends.
3
9dcd6f09 4 Copyright (C) 2005, 2007 Free Software Foundation, Inc.
953ff289
DN
5 Contributed by Richard Henderson <rth@redhat.com>,
6 Diego Novillo <dnovillo@redhat.com>.
7
8This file is part of GCC.
9
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
9dcd6f09 12Software Foundation; either version 3, or (at your option) any later
953ff289
DN
13version.
14
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License
9dcd6f09
NC
21along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
953ff289
DN
23
24#include "config.h"
25#include "system.h"
26#include "coretypes.h"
27#include "tm.h"
28#include "tree.h"
29#include "function.h"
30#include "c-common.h"
31#include "toplev.h"
32#include "tree-gimple.h"
33#include "bitmap.h"
34#include "langhooks.h"
35
36
37/* Complete a #pragma omp master construct. STMT is the structured-block
38 that follows the pragma. */
39
40tree
41c_finish_omp_master (tree stmt)
42{
43 return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
44}
45
46/* Complete a #pragma omp critical construct. STMT is the structured-block
47 that follows the pragma, NAME is the identifier in the pragma, or null
48 if it was omitted. */
49
50tree
51c_finish_omp_critical (tree body, tree name)
52{
53 tree stmt = make_node (OMP_CRITICAL);
54 TREE_TYPE (stmt) = void_type_node;
55 OMP_CRITICAL_BODY (stmt) = body;
56 OMP_CRITICAL_NAME (stmt) = name;
57 return add_stmt (stmt);
58}
59
60/* Complete a #pragma omp ordered construct. STMT is the structured-block
61 that follows the pragma. */
62
63tree
64c_finish_omp_ordered (tree stmt)
65{
66 return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
67}
68
69
70/* Complete a #pragma omp barrier construct. */
71
72void
73c_finish_omp_barrier (void)
74{
75 tree x;
76
77 x = built_in_decls[BUILT_IN_GOMP_BARRIER];
5039610b 78 x = build_call_expr (x, 0);
953ff289
DN
79 add_stmt (x);
80}
81
82
83/* Complete a #pragma omp atomic construct. The expression to be
fe89d797
MM
84 implemented atomically is LHS code= RHS. The value returned is
85 either error_mark_node (if the construct was erroneous) or an
86 OMP_ATOMIC node which should be added to the current statement tree
87 with add_stmt. */
953ff289 88
fe89d797 89tree
953ff289
DN
90c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
91{
92 tree x, type, addr;
93
94 if (lhs == error_mark_node || rhs == error_mark_node)
fe89d797 95 return error_mark_node;
953ff289
DN
96
97 /* ??? According to one reading of the OpenMP spec, complex type are
98 supported, but there are no atomic stores for any architecture.
99 But at least icc 9.0 doesn't support complex types here either.
100 And lets not even talk about vector types... */
101 type = TREE_TYPE (lhs);
102 if (!INTEGRAL_TYPE_P (type)
103 && !POINTER_TYPE_P (type)
104 && !SCALAR_FLOAT_TYPE_P (type))
105 {
106 error ("invalid expression type for %<#pragma omp atomic%>");
fe89d797 107 return error_mark_node;
953ff289
DN
108 }
109
110 /* ??? Validate that rhs does not overlap lhs. */
111
112 /* Take and save the address of the lhs. From then on we'll reference it
113 via indirection. */
114 addr = build_unary_op (ADDR_EXPR, lhs, 0);
115 if (addr == error_mark_node)
fe89d797 116 return error_mark_node;
953ff289 117 addr = save_expr (addr);
66bb4f32
JJ
118 if (TREE_CODE (addr) != SAVE_EXPR
119 && (TREE_CODE (addr) != ADDR_EXPR
120 || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
121 {
122 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
123 it even after unsharing function body. */
124 tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
125 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
126 }
953ff289
DN
127 lhs = build_indirect_ref (addr, NULL);
128
129 /* There are lots of warnings, errors, and conversions that need to happen
130 in the course of interpreting a statement. Use the normal mechanisms
131 to do this, and then take it apart again. */
132 x = build_modify_expr (lhs, code, rhs);
133 if (x == error_mark_node)
fe89d797 134 return error_mark_node;
953ff289
DN
135 gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
136 rhs = TREE_OPERAND (x, 1);
137
138 /* Punt the actual generation of atomic operations to common code. */
fe89d797 139 return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
953ff289
DN
140}
141
142
143/* Complete a #pragma omp flush construct. We don't do anything with the
144 variable list that the syntax allows. */
145
146void
147c_finish_omp_flush (void)
148{
149 tree x;
150
151 x = built_in_decls[BUILT_IN_SYNCHRONIZE];
5039610b 152 x = build_call_expr (x, 0);
953ff289
DN
153 add_stmt (x);
154}
155
156
157/* Check and canonicalize #pragma omp for increment expression.
158 Helper function for c_finish_omp_for. */
159
160static tree
161check_omp_for_incr_expr (tree exp, tree decl)
162{
163 tree t;
164
165 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
166 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
167 return error_mark_node;
168
169 if (exp == decl)
170 return build_int_cst (TREE_TYPE (exp), 0);
171
172 switch (TREE_CODE (exp))
173 {
174 case NOP_EXPR:
175 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
176 if (t != error_mark_node)
177 return fold_convert (TREE_TYPE (exp), t);
178 break;
179 case MINUS_EXPR:
180 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
181 if (t != error_mark_node)
182 return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
183 break;
184 case PLUS_EXPR:
185 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
186 if (t != error_mark_node)
187 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
188 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
189 if (t != error_mark_node)
190 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
191 break;
192 default:
193 break;
194 }
195
196 return error_mark_node;
197}
198
199/* Validate and emit code for the OpenMP directive #pragma omp for.
200 INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
201 of the loop (initialization expression, controlling predicate, increment
202 expression, body of the loop and statements to go before the loop).
203 DECL is the iteration variable. */
204
205tree
206c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
207 tree incr, tree body, tree pre_body)
208{
209 location_t elocus = locus;
210 bool fail = false;
211
212 if (EXPR_HAS_LOCATION (init))
213 elocus = EXPR_LOCATION (init);
214
215 /* Validate the iteration variable. */
216 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
217 {
218 error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
219 fail = true;
220 }
221 if (TYPE_UNSIGNED (TREE_TYPE (decl)))
222 warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
223
224 /* In the case of "for (int i = 0...)", init will be a decl. It should
225 have a DECL_INITIAL that we can turn into an assignment. */
226 if (init == decl)
227 {
228 elocus = DECL_SOURCE_LOCATION (decl);
229
230 init = DECL_INITIAL (decl);
231 if (init == NULL)
232 {
233 error ("%H%qE is not initialized", &elocus, decl);
234 init = integer_zero_node;
235 fail = true;
236 }
237
238 init = build_modify_expr (decl, NOP_EXPR, init);
239 SET_EXPR_LOCATION (init, elocus);
240 }
241 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
242 gcc_assert (TREE_OPERAND (init, 0) == decl);
243
244 if (cond == NULL_TREE)
245 {
246 error ("%Hmissing controlling predicate", &elocus);
247 fail = true;
248 }
249 else
250 {
251 bool cond_ok = false;
252
253 if (EXPR_HAS_LOCATION (cond))
254 elocus = EXPR_LOCATION (cond);
255
256 if (TREE_CODE (cond) == LT_EXPR
257 || TREE_CODE (cond) == LE_EXPR
258 || TREE_CODE (cond) == GT_EXPR
259 || TREE_CODE (cond) == GE_EXPR)
260 {
261 tree op0 = TREE_OPERAND (cond, 0);
262 tree op1 = TREE_OPERAND (cond, 1);
263
264 /* 2.5.1. The comparison in the condition is computed in the type
265 of DECL, otherwise the behavior is undefined.
266
267 For example:
268 long n; int i;
269 i < n;
270
271 according to ISO will be evaluated as:
272 (long)i < n;
273
274 We want to force:
275 i < (int)n; */
276 if (TREE_CODE (op0) == NOP_EXPR
277 && decl == TREE_OPERAND (op0, 0))
278 {
279 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
280 TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
281 TREE_OPERAND (cond, 1));
282 }
283 else if (TREE_CODE (op1) == NOP_EXPR
284 && decl == TREE_OPERAND (op1, 0))
285 {
286 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
287 TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
288 TREE_OPERAND (cond, 0));
289 }
290
291 if (decl == TREE_OPERAND (cond, 0))
292 cond_ok = true;
293 else if (decl == TREE_OPERAND (cond, 1))
294 {
295 TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
296 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
297 TREE_OPERAND (cond, 0) = decl;
298 cond_ok = true;
299 }
300 }
301
302 if (!cond_ok)
303 {
304 error ("%Hinvalid controlling predicate", &elocus);
305 fail = true;
306 }
307 }
308
309 if (incr == NULL_TREE)
310 {
311 error ("%Hmissing increment expression", &elocus);
312 fail = true;
313 }
314 else
315 {
316 bool incr_ok = false;
317
318 if (EXPR_HAS_LOCATION (incr))
319 elocus = EXPR_LOCATION (incr);
320
321 /* Check all the valid increment expressions: v++, v--, ++v, --v,
322 v = v + incr, v = incr + v and v = v - incr. */
323 switch (TREE_CODE (incr))
324 {
325 case POSTINCREMENT_EXPR:
326 case PREINCREMENT_EXPR:
327 case POSTDECREMENT_EXPR:
328 case PREDECREMENT_EXPR:
329 incr_ok = (TREE_OPERAND (incr, 0) == decl);
330 break;
331
332 case MODIFY_EXPR:
333 if (TREE_OPERAND (incr, 0) != decl)
334 break;
335 if (TREE_OPERAND (incr, 1) == decl)
336 break;
337 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
338 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
339 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
340 incr_ok = true;
341 else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
342 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
343 incr_ok = true;
344 else
345 {
346 tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
347 if (t != error_mark_node)
348 {
349 incr_ok = true;
350 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
351 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
352 }
353 }
354 break;
355
356 default:
357 break;
358 }
359 if (!incr_ok)
360 {
361 error ("%Hinvalid increment expression", &elocus);
362 fail = true;
363 }
364 }
365
366 if (fail)
367 return NULL;
368 else
369 {
370 tree t = make_node (OMP_FOR);
371
372 TREE_TYPE (t) = void_type_node;
373 OMP_FOR_INIT (t) = init;
374 OMP_FOR_COND (t) = cond;
375 OMP_FOR_INCR (t) = incr;
376 OMP_FOR_BODY (t) = body;
377 OMP_FOR_PRE_BODY (t) = pre_body;
378
379 SET_EXPR_LOCATION (t, locus);
380 return add_stmt (t);
381 }
382}
383
384
385/* Divide CLAUSES into two lists: those that apply to a parallel construct,
386 and those that apply to a work-sharing construct. Place the results in
387 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
388 clause to the work-sharing list. */
389
390void
391c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
392{
393 tree next;
394
395 *par_clauses = NULL;
aaf46ef9 396 *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
953ff289
DN
397
398 for (; clauses ; clauses = next)
399 {
400 next = OMP_CLAUSE_CHAIN (clauses);
401
aaf46ef9 402 switch (OMP_CLAUSE_CODE (clauses))
953ff289
DN
403 {
404 case OMP_CLAUSE_PRIVATE:
405 case OMP_CLAUSE_SHARED:
406 case OMP_CLAUSE_FIRSTPRIVATE:
407 case OMP_CLAUSE_LASTPRIVATE:
408 case OMP_CLAUSE_REDUCTION:
409 case OMP_CLAUSE_COPYIN:
410 case OMP_CLAUSE_IF:
411 case OMP_CLAUSE_NUM_THREADS:
412 case OMP_CLAUSE_DEFAULT:
413 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
414 *par_clauses = clauses;
415 break;
416
417 case OMP_CLAUSE_SCHEDULE:
418 case OMP_CLAUSE_ORDERED:
419 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
420 *ws_clauses = clauses;
421 break;
422
423 default:
424 gcc_unreachable ();
425 }
426 }
427}
428
429/* True if OpenMP sharing attribute of DECL is predetermined. */
430
431enum omp_clause_default_kind
432c_omp_predetermined_sharing (tree decl)
433{
434 /* Variables with const-qualified type having no mutable member
435 are predetermined shared. */
436 if (TREE_READONLY (decl))
437 return OMP_CLAUSE_DEFAULT_SHARED;
438
439 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
440}
This page took 0.423601 seconds and 5 git commands to generate.