Merge branch 'vendor/GCC50' - gcc 5.0 snapshot 1 FEB 2015
[dragonfly.git] / contrib / gcc-5.0 / gcc / cp / cp-cilkplus.c
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-2015 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 "diagnostic-core.h"
28 #include "tree-iterator.h"
29 #include "tree-inline.h"  /* for copy_tree_body_r.  */
30 #include "ggc.h"
31 #include "cilk.h"
32
33 /* Callback for cp_walk_tree to validate the body of a pragma simd loop
34    or _cilk_for loop.
35
36    This function is passed in as a function pointer to walk_tree.  *TP is
37    the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
38    recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
39    is set to false if an error has occured.  */
40
41 static tree
42 cpp_validate_cilk_plus_loop_aux (tree *tp, int *walk_subtrees, void *data)
43 {
44   bool *valid = (bool *) data;
45
46   if (!tp || !*tp)
47     return NULL_TREE;
48
49   location_t loc = EXPR_LOCATION (*tp);
50   if (TREE_CODE (*tp) == THROW_EXPR)
51     {
52       error_at (loc, "throw expressions are not allowed inside loops "
53                 "marked with pragma simd");
54       *walk_subtrees = 0;
55       *valid = false;
56     }
57   else if (TREE_CODE (*tp) == TRY_BLOCK)
58     {
59       error_at (loc, "try statements are not allowed inside loops marked "
60                 "with #pragma simd");
61       *valid = false;
62       *walk_subtrees = 0;
63     }
64   return NULL_TREE;
65 }  
66
67
68 /* Walks through all the subtrees of BODY using walk_tree to make sure
69    invalid statements/expressions are not found inside BODY.  Returns
70    false if any invalid statements are found.  */
71
72 bool
73 cpp_validate_cilk_plus_loop (tree body)
74 {
75   bool valid = true;
76   cp_walk_tree (&body, cpp_validate_cilk_plus_loop_aux,
77                 (void *) &valid, NULL);
78   return valid;
79 }
80
81 /* Sets the EXCEPTION bit (0x10) in the FRAME.flags field.  */
82
83 static tree
84 set_cilk_except_flag (tree frame)
85 {
86   tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, 0);
87
88   flags = build2 (MODIFY_EXPR, void_type_node, flags,
89                   build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
90                           build_int_cst (TREE_TYPE (flags),
91                                          CILK_FRAME_EXCEPTING)));
92   return flags;
93 }
94
95 /* Sets the frame.EXCEPT_DATA field to the head of the exception pointer.  */
96
97 static tree
98 set_cilk_except_data (tree frame)
99 {
100   tree except_data = cilk_dot (frame, CILK_TI_FRAME_EXCEPTION, 0);
101   tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
102   tree ret_expr;
103   uresume_fn  = build_call_expr (uresume_fn, 1,
104                                  build_int_cst (integer_type_node, 0));
105   ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn);
106   return ret_expr;
107 }
108
109 /* Installs BODY into function FNDECL with appropriate exception handling
110    code.  WD holds information of wrapper function used to pass into the
111    outlining function, cilk_outline.  */
112
113 void
114 cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
115 {
116   tree frame = make_cilk_frame (fndecl);
117   tree dtor = create_cilk_function_exit (frame, false, false);
118   add_local_decl (cfun, frame);
119
120   cfun->language = ggc_cleared_alloc<language_function> ();
121   
122   location_t loc = EXPR_LOCATION (orig_body);
123   tree list = alloc_stmt_list ();
124   DECL_SAVED_TREE (fndecl) = list;
125   tree fptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), frame);
126   tree body = cilk_install_body_pedigree_operations (fptr);
127   gcc_assert (TREE_CODE (body) == STATEMENT_LIST);
128   tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, fptr);
129   append_to_statement_list (detach_expr, &body);
130   cilk_outline (fndecl, &orig_body, (struct wrapper_data *) wd);
131   append_to_statement_list (orig_body, &body);
132   if (flag_exceptions)
133     {
134       tree except_flag = set_cilk_except_flag (frame);
135       tree except_data = set_cilk_except_data (frame);
136       tree catch_list = alloc_stmt_list ();
137       append_to_statement_list (except_flag, &catch_list);
138       append_to_statement_list (except_data, &catch_list);
139       body = create_try_catch_expr (body, catch_list);
140     }
141   append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, body, dtor),
142                             &list);
143 }