]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/c-omp.c
c-decl.c (finish_decl): Pass input_location to build_unary_op.
[thirdparty/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
a68ab351 4 Copyright (C) 2005, 2007, 2008 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"
726a989a 32#include "gimple.h"
953ff289
DN
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
a68ab351
JJ
83/* Complete a #pragma omp taskwait construct. */
84
85void
86c_finish_omp_taskwait (void)
87{
88 tree x;
89
90 x = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
91 x = build_call_expr (x, 0);
92 add_stmt (x);
93}
94
95
953ff289 96/* Complete a #pragma omp atomic construct. The expression to be
fe89d797
MM
97 implemented atomically is LHS code= RHS. The value returned is
98 either error_mark_node (if the construct was erroneous) or an
99 OMP_ATOMIC node which should be added to the current statement tree
100 with add_stmt. */
953ff289 101
fe89d797 102tree
953ff289
DN
103c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
104{
105 tree x, type, addr;
106
107 if (lhs == error_mark_node || rhs == error_mark_node)
fe89d797 108 return error_mark_node;
953ff289
DN
109
110 /* ??? According to one reading of the OpenMP spec, complex type are
111 supported, but there are no atomic stores for any architecture.
112 But at least icc 9.0 doesn't support complex types here either.
113 And lets not even talk about vector types... */
114 type = TREE_TYPE (lhs);
115 if (!INTEGRAL_TYPE_P (type)
116 && !POINTER_TYPE_P (type)
117 && !SCALAR_FLOAT_TYPE_P (type))
118 {
119 error ("invalid expression type for %<#pragma omp atomic%>");
fe89d797 120 return error_mark_node;
953ff289
DN
121 }
122
123 /* ??? Validate that rhs does not overlap lhs. */
124
125 /* Take and save the address of the lhs. From then on we'll reference it
126 via indirection. */
c9f9eb5d 127 addr = build_unary_op (input_location, ADDR_EXPR, lhs, 0);
953ff289 128 if (addr == error_mark_node)
fe89d797 129 return error_mark_node;
953ff289 130 addr = save_expr (addr);
66bb4f32
JJ
131 if (TREE_CODE (addr) != SAVE_EXPR
132 && (TREE_CODE (addr) != ADDR_EXPR
133 || TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
134 {
135 /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
136 it even after unsharing function body. */
137 tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
138 addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
139 }
c9f9eb5d 140 lhs = build_indirect_ref (input_location, addr, NULL);
953ff289
DN
141
142 /* There are lots of warnings, errors, and conversions that need to happen
143 in the course of interpreting a statement. Use the normal mechanisms
144 to do this, and then take it apart again. */
c9f9eb5d 145 x = build_modify_expr (input_location, lhs, code, rhs);
953ff289 146 if (x == error_mark_node)
fe89d797 147 return error_mark_node;
953ff289
DN
148 gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
149 rhs = TREE_OPERAND (x, 1);
150
151 /* Punt the actual generation of atomic operations to common code. */
fe89d797 152 return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
953ff289
DN
153}
154
155
156/* Complete a #pragma omp flush construct. We don't do anything with the
157 variable list that the syntax allows. */
158
159void
160c_finish_omp_flush (void)
161{
162 tree x;
163
164 x = built_in_decls[BUILT_IN_SYNCHRONIZE];
5039610b 165 x = build_call_expr (x, 0);
953ff289
DN
166 add_stmt (x);
167}
168
169
170/* Check and canonicalize #pragma omp for increment expression.
171 Helper function for c_finish_omp_for. */
172
173static tree
174check_omp_for_incr_expr (tree exp, tree decl)
175{
176 tree t;
177
178 if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
179 || TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
180 return error_mark_node;
181
182 if (exp == decl)
183 return build_int_cst (TREE_TYPE (exp), 0);
184
185 switch (TREE_CODE (exp))
186 {
1043771b 187 CASE_CONVERT:
953ff289
DN
188 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
189 if (t != error_mark_node)
190 return fold_convert (TREE_TYPE (exp), t);
191 break;
192 case MINUS_EXPR:
193 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
194 if (t != error_mark_node)
195 return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
196 break;
197 case PLUS_EXPR:
198 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
199 if (t != error_mark_node)
200 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
201 t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
202 if (t != error_mark_node)
203 return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
204 break;
205 default:
206 break;
207 }
208
209 return error_mark_node;
210}
211
212/* Validate and emit code for the OpenMP directive #pragma omp for.
a68ab351
JJ
213 DECLV is a vector of iteration variables, for each collapsed loop.
214 INITV, CONDV and INCRV are vectors containing initialization
215 expressions, controlling predicates and increment expressions.
216 BODY is the body of the loop and PRE_BODY statements that go before
217 the loop. */
953ff289
DN
218
219tree
a68ab351
JJ
220c_finish_omp_for (location_t locus, tree declv, tree initv, tree condv,
221 tree incrv, tree body, tree pre_body)
953ff289 222{
a68ab351 223 location_t elocus;
953ff289 224 bool fail = false;
a68ab351 225 int i;
953ff289 226
a68ab351
JJ
227 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
228 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
229 gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
230 for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
953ff289 231 {
a68ab351
JJ
232 tree decl = TREE_VEC_ELT (declv, i);
233 tree init = TREE_VEC_ELT (initv, i);
234 tree cond = TREE_VEC_ELT (condv, i);
235 tree incr = TREE_VEC_ELT (incrv, i);
236
237 elocus = locus;
238 if (EXPR_HAS_LOCATION (init))
239 elocus = EXPR_LOCATION (init);
240
241 /* Validate the iteration variable. */
242 if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
243 && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
244 {
c9f9eb5d 245 error_at (elocus, "invalid type for iteration variable %qE", decl);
a68ab351
JJ
246 fail = true;
247 }
953ff289 248
a68ab351
JJ
249 /* In the case of "for (int i = 0...)", init will be a decl. It should
250 have a DECL_INITIAL that we can turn into an assignment. */
251 if (init == decl)
252 {
253 elocus = DECL_SOURCE_LOCATION (decl);
254
255 init = DECL_INITIAL (decl);
256 if (init == NULL)
257 {
c9f9eb5d 258 error_at (elocus, "%qE is not initialized", decl);
a68ab351
JJ
259 init = integer_zero_node;
260 fail = true;
261 }
953ff289 262
c9f9eb5d 263 init = build_modify_expr (elocus, decl, NOP_EXPR, init);
a68ab351
JJ
264 }
265 gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
266 gcc_assert (TREE_OPERAND (init, 0) == decl);
267
268 if (cond == NULL_TREE)
953ff289 269 {
c9f9eb5d 270 error_at (elocus, "missing controlling predicate");
953ff289
DN
271 fail = true;
272 }
a68ab351
JJ
273 else
274 {
275 bool cond_ok = false;
953ff289 276
a68ab351
JJ
277 if (EXPR_HAS_LOCATION (cond))
278 elocus = EXPR_LOCATION (cond);
953ff289 279
a68ab351
JJ
280 if (TREE_CODE (cond) == LT_EXPR
281 || TREE_CODE (cond) == LE_EXPR
282 || TREE_CODE (cond) == GT_EXPR
283 || TREE_CODE (cond) == GE_EXPR)
284 {
285 tree op0 = TREE_OPERAND (cond, 0);
286 tree op1 = TREE_OPERAND (cond, 1);
953ff289 287
a68ab351
JJ
288 /* 2.5.1. The comparison in the condition is computed in
289 the type of DECL, otherwise the behavior is undefined.
953ff289 290
a68ab351
JJ
291 For example:
292 long n; int i;
293 i < n;
953ff289 294
a68ab351
JJ
295 according to ISO will be evaluated as:
296 (long)i < n;
953ff289 297
a68ab351
JJ
298 We want to force:
299 i < (int)n; */
300 if (TREE_CODE (op0) == NOP_EXPR
301 && decl == TREE_OPERAND (op0, 0))
302 {
303 TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
304 TREE_OPERAND (cond, 1)
305 = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
306 TREE_OPERAND (cond, 1));
307 }
308 else if (TREE_CODE (op1) == NOP_EXPR
309 && decl == TREE_OPERAND (op1, 0))
310 {
311 TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
312 TREE_OPERAND (cond, 0)
313 = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
314 TREE_OPERAND (cond, 0));
315 }
953ff289 316
a68ab351
JJ
317 if (decl == TREE_OPERAND (cond, 0))
318 cond_ok = true;
319 else if (decl == TREE_OPERAND (cond, 1))
320 {
321 TREE_SET_CODE (cond,
322 swap_tree_comparison (TREE_CODE (cond)));
323 TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
324 TREE_OPERAND (cond, 0) = decl;
325 cond_ok = true;
326 }
953ff289
DN
327 }
328
a68ab351 329 if (!cond_ok)
953ff289 330 {
c9f9eb5d 331 error_at (elocus, "invalid controlling predicate");
a68ab351 332 fail = true;
953ff289
DN
333 }
334 }
335
a68ab351 336 if (incr == NULL_TREE)
953ff289 337 {
c9f9eb5d 338 error_at (elocus, "missing increment expression");
953ff289
DN
339 fail = true;
340 }
a68ab351 341 else
953ff289 342 {
a68ab351 343 bool incr_ok = false;
953ff289 344
a68ab351
JJ
345 if (EXPR_HAS_LOCATION (incr))
346 elocus = EXPR_LOCATION (incr);
347
348 /* Check all the valid increment expressions: v++, v--, ++v, --v,
349 v = v + incr, v = incr + v and v = v - incr. */
350 switch (TREE_CODE (incr))
953ff289 351 {
a68ab351
JJ
352 case POSTINCREMENT_EXPR:
353 case PREINCREMENT_EXPR:
354 case POSTDECREMENT_EXPR:
355 case PREDECREMENT_EXPR:
356 if (TREE_OPERAND (incr, 0) != decl)
357 break;
358
359 incr_ok = true;
360 if (POINTER_TYPE_P (TREE_TYPE (decl)))
953ff289 361 {
a68ab351
JJ
362 tree t = fold_convert (sizetype, TREE_OPERAND (incr, 1));
363
364 if (TREE_CODE (incr) == POSTDECREMENT_EXPR
365 || TREE_CODE (incr) == PREDECREMENT_EXPR)
366 t = fold_build1 (NEGATE_EXPR, sizetype, t);
367 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (decl), decl, t);
953ff289
DN
368 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
369 }
a68ab351
JJ
370 break;
371
372 case MODIFY_EXPR:
373 if (TREE_OPERAND (incr, 0) != decl)
374 break;
375 if (TREE_OPERAND (incr, 1) == decl)
376 break;
377 if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
378 && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
379 || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
380 incr_ok = true;
381 else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
382 || (TREE_CODE (TREE_OPERAND (incr, 1))
383 == POINTER_PLUS_EXPR))
384 && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
385 incr_ok = true;
386 else
387 {
388 tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1),
389 decl);
390 if (t != error_mark_node)
391 {
392 incr_ok = true;
393 t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
394 incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
395 }
396 }
397 break;
953ff289 398
a68ab351
JJ
399 default:
400 break;
401 }
402 if (!incr_ok)
403 {
c9f9eb5d 404 error_at (elocus, "invalid increment expression");
a68ab351
JJ
405 fail = true;
406 }
953ff289 407 }
a68ab351
JJ
408
409 TREE_VEC_ELT (initv, i) = init;
410 TREE_VEC_ELT (incrv, i) = incr;
953ff289
DN
411 }
412
413 if (fail)
414 return NULL;
415 else
416 {
417 tree t = make_node (OMP_FOR);
418
419 TREE_TYPE (t) = void_type_node;
a68ab351
JJ
420 OMP_FOR_INIT (t) = initv;
421 OMP_FOR_COND (t) = condv;
422 OMP_FOR_INCR (t) = incrv;
953ff289
DN
423 OMP_FOR_BODY (t) = body;
424 OMP_FOR_PRE_BODY (t) = pre_body;
425
426 SET_EXPR_LOCATION (t, locus);
427 return add_stmt (t);
428 }
429}
430
431
432/* Divide CLAUSES into two lists: those that apply to a parallel construct,
433 and those that apply to a work-sharing construct. Place the results in
434 *PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
435 clause to the work-sharing list. */
436
437void
438c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
439{
440 tree next;
441
442 *par_clauses = NULL;
aaf46ef9 443 *ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
953ff289
DN
444
445 for (; clauses ; clauses = next)
446 {
447 next = OMP_CLAUSE_CHAIN (clauses);
448
aaf46ef9 449 switch (OMP_CLAUSE_CODE (clauses))
953ff289
DN
450 {
451 case OMP_CLAUSE_PRIVATE:
452 case OMP_CLAUSE_SHARED:
453 case OMP_CLAUSE_FIRSTPRIVATE:
454 case OMP_CLAUSE_LASTPRIVATE:
455 case OMP_CLAUSE_REDUCTION:
456 case OMP_CLAUSE_COPYIN:
457 case OMP_CLAUSE_IF:
458 case OMP_CLAUSE_NUM_THREADS:
459 case OMP_CLAUSE_DEFAULT:
460 OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
461 *par_clauses = clauses;
462 break;
463
464 case OMP_CLAUSE_SCHEDULE:
465 case OMP_CLAUSE_ORDERED:
a68ab351 466 case OMP_CLAUSE_COLLAPSE:
953ff289
DN
467 OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
468 *ws_clauses = clauses;
469 break;
470
471 default:
472 gcc_unreachable ();
473 }
474 }
475}
476
477/* True if OpenMP sharing attribute of DECL is predetermined. */
478
479enum omp_clause_default_kind
480c_omp_predetermined_sharing (tree decl)
481{
482 /* Variables with const-qualified type having no mutable member
483 are predetermined shared. */
484 if (TREE_READONLY (decl))
485 return OMP_CLAUSE_DEFAULT_SHARED;
486
487 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
488}