Mercurial > hg > CbC > CbC_gcc
comparison gcc/cp/cp-cilkplus.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* This file is part of the Intel(R) Cilk(TM) Plus support | |
2 This file contains routines to handle Cilk Plus specific | |
3 routines for the C++ Compiler. | |
4 Copyright (C) 2013-2017 Free Software Foundation, Inc. | |
5 Contributed by Aldy Hernandez <aldyh@redhat.com>. | |
6 | |
7 This file is part of GCC. | |
8 | |
9 GCC is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by | |
11 the Free Software Foundation; either version 3, or (at your option) | |
12 any later version. | |
13 | |
14 GCC is distributed in the hope that it will be useful, but | |
15 WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 General Public License for more details. | |
18 | |
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/>. */ | |
22 | |
23 #include "config.h" | |
24 #include "system.h" | |
25 #include "coretypes.h" | |
26 #include "cp-tree.h" | |
27 #include "tree-iterator.h" | |
28 #include "cilk.h" | |
29 #include "c-family/c-common.h" | |
30 | |
31 /* Return TRUE if T is a FUNCTION_DECL for a type-conversion operator. */ | |
32 | |
33 static bool | |
34 is_conversion_operator_function_decl_p (tree t) | |
35 { | |
36 if (TREE_CODE (t) != FUNCTION_DECL) | |
37 return false; | |
38 | |
39 return DECL_CONV_FN_P (t); | |
40 } | |
41 | |
42 /* Recursively traverse EXP to search for a CILK_SPAWN_STMT subtree. | |
43 Return the CILK_SPAWN_STMT subtree if found; otherwise, the last subtree | |
44 searched. */ | |
45 | |
46 static tree | |
47 find_spawn (tree exp) | |
48 { | |
49 /* Happens with C++ TARGET_EXPR. */ | |
50 if (exp == NULL_TREE) | |
51 return exp; | |
52 | |
53 if (cilk_ignorable_spawn_rhs_op (exp)) | |
54 return find_spawn (TREE_OPERAND (exp, 0)); | |
55 | |
56 switch (TREE_CODE (exp)) | |
57 { | |
58 case AGGR_INIT_EXPR: | |
59 { | |
60 /* Check for initialization via a constructor call that represents | |
61 implicit conversion. */ | |
62 if (AGGR_INIT_VIA_CTOR_P (exp) && aggr_init_expr_nargs (exp) == 2) | |
63 return find_spawn (AGGR_INIT_EXPR_ARG (exp, 1)); | |
64 | |
65 /* Check for initialization via a call to a type-conversion | |
66 operator. */ | |
67 tree fn = AGGR_INIT_EXPR_FN (exp); | |
68 if (TREE_CODE (fn) == ADDR_EXPR | |
69 && is_conversion_operator_function_decl_p (TREE_OPERAND (fn, 0)) | |
70 && aggr_init_expr_nargs (exp) == 1) | |
71 return find_spawn (AGGR_INIT_EXPR_ARG (exp, 0)); | |
72 } | |
73 break; | |
74 | |
75 case CALL_EXPR: | |
76 { | |
77 /* Check for a call to a type-conversion operator. */ | |
78 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); | |
79 if (is_conversion_operator_function_decl_p (fndecl) | |
80 && call_expr_nargs (exp) == 1) | |
81 return find_spawn (CALL_EXPR_ARG (exp, 0)); | |
82 } | |
83 break; | |
84 | |
85 case TARGET_EXPR: | |
86 return find_spawn (TARGET_EXPR_INITIAL (exp)); | |
87 | |
88 case CLEANUP_POINT_EXPR: | |
89 case COMPOUND_EXPR: | |
90 case EXPR_STMT: | |
91 return find_spawn (TREE_OPERAND (exp, 0)); | |
92 | |
93 default: | |
94 break; | |
95 } | |
96 | |
97 return exp; | |
98 } | |
99 | |
100 /* Return true if *EXP0 is a recognized form of spawn. Recognized forms | |
101 are, after conversion to void, a call expression at outer level or an | |
102 assignment at outer level with the right hand side being a spawned call. | |
103 In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the | |
104 CALL_EXPR that is being spawned. | |
105 | |
106 Note that `=' in C++ may turn into a CALL_EXPR rather than a | |
107 MODIFY_EXPR. */ | |
108 | |
109 bool | |
110 cilk_cp_detect_spawn_and_unwrap (tree *exp0) | |
111 { | |
112 tree exp = *exp0; | |
113 | |
114 if (!TREE_SIDE_EFFECTS (exp)) | |
115 return false; | |
116 | |
117 /* Strip off any conversion to void. It does not affect whether spawn | |
118 is supported here. */ | |
119 if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp))) | |
120 exp = TREE_OPERAND (exp, 0); | |
121 | |
122 if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR) | |
123 exp = TREE_OPERAND (exp, 1); | |
124 | |
125 exp = find_spawn (exp); | |
126 if (exp == NULL_TREE) | |
127 return false; | |
128 | |
129 /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around | |
130 it, or return false. */ | |
131 return cilk_recognize_spawn (exp, exp0); | |
132 } | |
133 | |
134 /* Callback for cp_walk_tree to validate the body of a pragma simd loop | |
135 or _cilk_for loop. | |
136 | |
137 This function is passed in as a function pointer to walk_tree. *TP is | |
138 the current tree pointer, *WALK_SUBTREES is set to 0 by this function if | |
139 recursing into TP's subtrees is unnecessary. *DATA is a bool variable that | |
140 is set to false if an error has occurred. */ | |
141 | |
142 static tree | |
143 cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data) | |
144 { | |
145 bool *valid = (bool *) data; | |
146 | |
147 if (!tp || !*tp) | |
148 return NULL_TREE; | |
149 | |
150 location_t loc = EXPR_LOCATION (*tp); | |
151 if (TREE_CODE (*tp) == THROW_EXPR) | |
152 { | |
153 error_at (loc, "throw expressions are not allowed inside loops " | |
154 "marked with pragma simd"); | |
155 *walk_subtrees = 0; | |
156 *valid = false; | |
157 } | |
158 else if (TREE_CODE (*tp) == TRY_BLOCK) | |
159 { | |
160 error_at (loc, "try statements are not allowed inside loops marked " | |
161 "with #pragma simd"); | |
162 *valid = false; | |
163 *walk_subtrees = 0; | |
164 } | |
165 return NULL_TREE; | |
166 } | |
167 | |
168 | |
169 /* Walks through all the subtrees of BODY using walk_tree to make sure | |
170 invalid statements/expressions are not found inside BODY. Returns | |
171 false if any invalid statements are found. */ | |
172 | |
173 bool | |
174 cpp_validate_cilk_plus_loop (tree body) | |
175 { | |
176 bool valid = true; | |
177 cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux, | |
178 (void *) &valid, NULL); | |
179 return valid; | |
180 } | |
181 | |
182 /* Sets the EXCEPTION bit (0x10) in the FRAME.flags field. */ | |
183 | |
184 static tree | |
185 set_cilk_except_flag (tree frame) | |
186 { | |
187 tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0); | |
188 | |
189 flags = build2 (MODIFY_EXPR, void_type_node, flags, | |
190 build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags, | |
191 build_int_cst (TREE_TYPE (flags), | |
192 CILK_FRAME_EXCEPTING))); | |
193 return flags; | |
194 } | |
195 | |
196 /* Sets the frame.EXCEPT_DATA field to the head of the exception pointer. */ | |
197 | |
198 static tree | |
199 set_cilk_except_data (tree frame) | |
200 { | |
201 tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0); | |
202 tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER); | |
203 tree ret_expr; | |
204 uresume_fn = build_call_expr (uresume_fn, 1, | |
205 build_int_cst (integer_type_node, 0)); | |
206 ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn); | |
207 return ret_expr; | |
208 } | |
209 | |
210 /* Installs BODY into function FNDECL with appropriate exception handling | |
211 code. WD holds information of wrapper function used to pass into the | |
212 outlining function, cilk_outline. */ | |
213 | |
214 void | |
215 cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd) | |
216 { | |
217 tree frame = make_cilk_frame (fndecl); | |
218 tree dtor = create_cilk_function_exit (frame, false, false); | |
219 add_local_decl (cfun, frame); | |
220 | |
221 cfun->language = ggc_cleared_alloc<language_function> (); | |
222 | |
223 location_t loc = EXPR_LOCATION (orig_body); | |
224 tree list = alloc_stmt_list (); | |
225 DECL_SAVED_TREE (fndecl) = list; | |
226 tree body = alloc_stmt_list (); | |
227 cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd); | |
228 append_to_statement_list (orig_body, &body); | |
229 if (flag_exceptions) | |
230 { | |
231 tree except_flag = set_cilk_except_flag (frame); | |
232 tree except_data = set_cilk_except_data (frame); | |
233 tree catch_list = alloc_stmt_list (); | |
234 append_to_statement_list (except_flag, &catch_list); | |
235 append_to_statement_list (except_data, &catch_list); | |
236 body = create_try_catch_expr (body, catch_list); | |
237 } | |
238 append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor), | |
239 &list); | |
240 } |