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 41static tree 42cpp_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 72bool 73cpp_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 83static tree 84set_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 97static tree 98set_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 113void 114cilk_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} 144