diff mbox

[Cilkplus] Exceptions in a spawning function

Message ID BF230D13CA30DD48930C31D40993300016D1D3C2@FMSMSX102.amr.corp.intel.com
State New
Headers show

Commit Message

Iyer, Balaji V Feb. 4, 2013, 5:27 p.m. UTC
Hello Everyone,
	This patch is for the Cilk Plus branch mainly affecting the C++ compiler. This patch will handle exceptions thrown by the spawning function (a function called with _Cilk_spawn). 

Thanks,

Balaji V. Iyer.
diff mbox

Patch

diff --git gcc/ChangeLog.cilkplus gcc/ChangeLog.cilkplus
old mode 100644
new mode 100755
index 97975d8..0cae431
--- gcc/ChangeLog.cilkplus
+++ gcc/ChangeLog.cilkplus
@@ -1,3 +1,22 @@ 
+2013-02-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cilk.c (cilk_init_builtins): Defined __cilkrts_rethrow builtin
+	function.
+	(build_cilk_sync): Added code to set exception flag and exception data
+	in the stack frame.  Also added code to call __cilkrts_rethrow function.
+	Finally, inserted this code in the appropriate location of if-stmt.
+	(set_cilk_except_flag): New function.
+	(clear_cilk_except_flag): Likewise.
+	(set_cilk_except_data): Likewise.
+	(build_cilk_catch_sync): Likewise.
+	* cilk-builtins.def (BUILT_IN_CILK_RETHROW): New builtin function.
+	* c/c-objc-common.h (LANG_HOOKS_FRAME_CLEANUP): Set this hook to
+	c_install_body_with_frame_cleanup.
+	* langhooks-def.h (LANG_HOOKS_FRAME_CLEANUP): New #define.
+	(lhd_install_body_with_frame_cleanup): New function.
+	* langhooks.h (lang_hooks_for_cilkplus): New struct field called
+	"install_body_with_frame_cleanup."
+
 2013-01-24  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* cgraphunit.c (cgraph_finalize_function): If cilkplus is enabled and
diff --git gcc/builtins.def gcc/builtins.def
old mode 100644
new mode 100755
diff --git gcc/c-family/ChangeLog.cilkplus gcc/c-family/ChangeLog.cilkplus
old mode 100644
new mode 100755
index 9a720b8..8bc0a17
--- gcc/c-family/ChangeLog.cilkplus
+++ gcc/c-family/ChangeLog.cilkplus
@@ -1,3 +1,11 @@ 
+2013-02-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* c-cilk.c (build_cilk_wrapper_body): Replaced the function call for
+	install_body_with_frame_cleanup with the one from langhooks.
+	(build_cilk_for_body): Likewise.
+	(install_body_with_frame_cleanup): Renamed this function to
+	c_install_body_with_frame_cleanup.
+
 2013-01-24  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* c-cpp-elem-function.c (elem_fn_create_fn): Set the assembler name and
diff --git gcc/c-family/c-cilk.c gcc/c-family/c-cilk.c
old mode 100644
new mode 100755
index f1bace5..dee4579
--- gcc/c-family/c-cilk.c
+++ gcc/c-family/c-cilk.c
@@ -99,7 +99,6 @@  static void cilk_outline (tree inner_fn, tree *, struct wrapper_data *);
 static tree copy_decl_for_cilk (tree decl, copy_body_data *id);
 static tree check_outlined_calls (tree *, int *, void *);
 static tree build_cilk_wrapper (tree, tree *);
-static void install_body_with_frame_cleanup (tree, tree);
 static bool var_mentioned_p (tree exp, tree var);
 
 extern tree build_unary_op (location_t location, enum tree_code code,
@@ -135,7 +134,6 @@  call_graph_add_fn (tree fndecl, struct wrapper_data *wd)
     tree_cons (NULL_TREE, fndecl, cilk_trees[CILK_TI_PENDING_FUNCTIONS]);
   
   f->curr_properties = cfun->curr_properties;
-
   gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer)); 
   gcc_assert (cfun->decl == outer);
 
@@ -1407,7 +1405,7 @@  build_cilk_wrapper_body (tree stmt,
   cilk_outline (fndecl, &stmt, wd);
   stmt = fold_build_cleanup_point_expr (void_type_node, stmt);
   gcc_assert (!DECL_SAVED_TREE (fndecl));
-  install_body_with_frame_cleanup (fndecl, stmt);
+  lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt);
   gcc_assert (DECL_SAVED_TREE (fndecl));
 
   pop_cfun_to (outer);
@@ -1553,8 +1551,8 @@  check_outlined_calls (tree *tp,
 
 /* This function installs the internal functions of spawn helper and parent.  */
 
-static void
-install_body_with_frame_cleanup (tree fndecl, tree body)
+void
+c_install_body_with_frame_cleanup (tree fndecl, tree body)
 {
   tree list;
   tree frame = make_cilk_frame (fndecl);
@@ -2455,7 +2453,7 @@  build_cilk_for_body (struct cilk_for_desc *cfd)
   body = build3 (BIND_EXPR, void_type_node, loop_var, body, block);
   TREE_CHAIN (loop_var) = cfd->var2;
   if (contains_spawn (body))
-    install_body_with_frame_cleanup (fndecl, body);
+    lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, body);
   else
     DECL_SAVED_TREE (fndecl) = body;
 
diff --git gcc/c/c-objc-common.h gcc/c/c-objc-common.h
index 8053c53..08ad087 100644
--- gcc/c/c-objc-common.h
+++ gcc/c/c-objc-common.h
@@ -122,4 +122,8 @@  along with GCC; see the file COPYING3.  If not see
 
 #undef LANG_HOOKS_CILK_CHECK_CTRL_FLOW
 #define LANG_HOOKS_CILK_CHECK_CTRL_FLOW cilk_check_ctrl_flow
+
+#undef LANG_HOOKS_FRAME_CLEANUP
+#define LANG_HOOKS_FRAME_CLEANUP c_install_body_with_frame_cleanup
+
 #endif /* GCC_C_OBJC_COMMON */
diff --git gcc/cilk-builtins.def gcc/cilk-builtins.def
old mode 100644
new mode 100755
index 5de740a..e483dd8
--- gcc/cilk-builtins.def
+++ gcc/cilk-builtins.def
@@ -24,6 +24,7 @@  along with GCC; see the file COPYING3.  If not see
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_WORKER_ID, "__cilkrts_current_worker_id")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_WORKER_PTR, "__cilkrts_current_worker")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_DETACH, "__cilkrts_detach")
+DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_RETHROW, "__cilkrts_rethrow")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNCHED, "__cilkrts_synched")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_STOLEN, "__cilkrts_was_stolen")
 DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME, "__cilkrts_enter_frame")
diff --git gcc/cilk.c gcc/cilk.c
old mode 100644
new mode 100755
index 7387c4c..c444025
--- gcc/cilk.c
+++ gcc/cilk.c
@@ -282,7 +282,10 @@  cilk_init_builtins (void)
 
   cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun,
 				     BUILT_IN_CILK_POP_FRAME, false);
- 
+
+  cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun,
+					 BUILT_IN_CILK_RETHROW, false);
+  
   cilk_leave_fndecl = build_fn_decl ("__cilkrts_leave_frame", fptr_fun);
   mark_cold (cilk_leave_fndecl);
   cilk_leave_fndecl = lang_hooks.decls.pushdecl (cilk_leave_fndecl);
@@ -701,7 +704,7 @@  make_cilk_frame (tree fn)
   return decl;
 }
 
-/*This function will expand a cilk_sync call.  */
+/* This function will expand a cilk_sync call.  */
 
 tree
 build_cilk_sync (void)
@@ -714,15 +717,17 @@  build_cilk_sync (void)
   tree setjmp_expr;
   tree sync_list, frame_addr;
   tree sync_begin, sync_end;
+  tree except_flag, except_cond;
 
   /* Cilk_sync becomes the following code:
      if (frame.flags & CILK_FRAME_UNSYNCHED)
       if (!builtin_setjmp (frame.ctx)
-            // cilk_enter_begin();
+            // cilk_sync_begin();
           __cilkrts_sync(&frame);
-            // cilk_enter_end();
+            // cilk_sync_end();
        else
-          <NOTHING> ;
+          if (sf.flags & CILK_FRAME_EXCEPTING)
+	    __cilkrts_rethrow (&sf);
     else
           <NOTHING> ;
   */
@@ -736,14 +741,27 @@  build_cilk_sync (void)
 			   build_int_cst (TREE_TYPE (unsynched), 0));
 
   frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+
+  /* Check if exception (0x10) bit is set in the sf->flags.  */
+  except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+			     build_int_cst (TREE_TYPE (flags),
+					    CILK_FRAME_EXCEPTING));
+  except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag,
+			     build_int_cst (TREE_TYPE (except_flag), 0));
+
+  /* If the exception flag is set then call the __cilkrts_rethrow (&sf).  */
+  except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag,
+			     build_call_expr (cilk_rethrow_fndecl, 1,
+					      frame_addr),
+			     build_empty_stmt (EXPR_LOCATION (unsynched)));
+  
   sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
   setjmp_expr = cilk_call_setjmp (frame);
   setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
 			     build_int_cst (TREE_TYPE (setjmp_expr), 0));
   
   setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
-			     sync_expr,
-			     build_empty_stmt (EXPR_LOCATION (unsynched)));
+			     sync_expr, except_cond);
   
   sync = fold_build3 (COND_EXPR, void_type_node, unsynched, setjmp_expr,
 		      build_empty_stmt (EXPR_LOCATION (unsynched)));
@@ -1563,3 +1581,132 @@  cilk_check_ctrl_flow (tree *fnbody)
   walk_tree (fnbody, check_gotos_outside_cilk_for, (void *) &label_list, NULL);
   return;
 }
+
+/* Sets the EXCEPTION bit (0x10) in the FRAME.flags field.  */
+
+tree
+set_cilk_except_flag (tree frame)
+{
+  tree flags = dot (frame, CILK_TI_FRAME_FLAGS, 0);
+
+  flags = build2 (MODIFY_EXPR, void_type_node, flags,
+		 build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags,
+			 build_int_cst (TREE_TYPE (flags),
+					CILK_FRAME_EXCEPTING)));
+  return flags;
+}
+
+/* Clears the EXCEPTION bit (0x10) in the FRAME.flags field.  */
+
+tree
+clear_cilk_except_flag (tree frame)
+{
+  tree flags = dot (frame, CILK_TI_FRAME_FLAGS, 0);
+
+  flags = build2 (MODIFY_EXPR, void_type_node, flags,
+		 build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+			 build_int_cst (TREE_TYPE (flags),
+					~CILK_FRAME_EXCEPTING)));
+  return flags;
+}
+
+/* Sets the frame.EXCEPT_DATA field to the head of the exception pointer.  */
+
+tree
+set_cilk_except_data (tree frame)
+{
+  tree except_data = dot (frame, CILK_TI_FRAME_EXCEPTION, 0);
+  tree uresume_fn = builtin_decl_implicit (BUILT_IN_EH_POINTER);
+  tree ret_expr;
+  uresume_fn  = build_call_expr (uresume_fn, 1,
+				 build_int_cst (integer_type_node, 0));
+  ret_expr = build2 (MODIFY_EXPR, void_type_node, except_data, uresume_fn);
+  return ret_expr;
+}
+
+/* This function will insert the code for a _Cilk_sync with the exception
+   related flags and fields set.  This is created seperate because C does not
+   have exceptions and setting and checking these fields could trigger
+   seg-faults.  */
+
+tree
+build_cilk_catch_sync (void)
+{
+  tree frame = cfun->cilk_frame_decl;
+  tree flags;
+  tree unsynched;
+  tree sync;
+  tree sync_expr;
+  tree setjmp_expr;
+  tree sync_list, frame_addr;
+  tree sync_begin, sync_end;
+  tree set_except_flag, except_data, sync_expr_list;
+  tree clear_except_flag, clear_except_cond_list;
+
+  /* We insert the following code:
+     
+     if (frame.flags & CILK_FRAME_UNSYNCHED)
+       {
+         if (!builtin_setjmp (frame.ctx)
+           {
+             frame.except_data = __builtin_eh_pointer(0);
+	     frame.flags |= CILK_FRAME_EXCEPTING;
+	     // cilk_sync_begin();
+             __cilkrts_sync(&frame);
+             // cilk_sync_end();
+	   }
+          else
+	    frame.flags &= ~CILK_FRAME_EXCEPTING.
+       }  
+  */
+  flags = dot (frame, CILK_TI_FRAME_FLAGS, false);
+  
+  unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags,
+			   build_int_cst (TREE_TYPE (flags),
+					  CILK_FRAME_UNSYNCHED));
+
+  unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched,
+			   build_int_cst (TREE_TYPE (unsynched), 0));
+
+  frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame);
+
+  sync_expr_list = alloc_stmt_list ();
+  sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr);
+
+  /* Sets the sf->except_data = __builtin_eh_pointer (0);  */
+  except_data = set_cilk_except_data (frame);
+
+  /* Sets sf->flags to sf->flags | CILK_FRAME_EXCEPTING.  */
+  set_except_flag = set_cilk_except_flag (frame);
+  append_to_statement_list (sync_expr, &sync_expr_list);
+  append_to_statement_list (except_data, &sync_expr_list);
+  append_to_statement_list (set_except_flag, &sync_expr_list);
+
+  clear_except_cond_list = alloc_stmt_list ();
+
+  /* Sets sf->flags to sf->flags & ~CILK_FRAME_EXCEPTING.  */
+  clear_except_flag = clear_cilk_except_flag (frame);
+  append_to_statement_list (clear_except_flag, &clear_except_cond_list);
+  
+  setjmp_expr = cilk_call_setjmp (frame);
+
+  setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr,
+			     build_int_cst (TREE_TYPE (setjmp_expr), 0));
+  
+  /* Checks of __builtin_setjmp (frame.ctx) == 0.  IF so, then we jump to
+     sync_list otherwise, we just jump to the clear_except_cond_list.  */
+  setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr,
+			     sync_expr_list, clear_except_cond_list);
+  
+  sync = fold_build3 (COND_EXPR, void_type_node, unsynched, setjmp_expr,
+		      build_empty_stmt (EXPR_LOCATION (unsynched)));
+  
+  sync_begin = build_call_expr (cilk_sync_begin_fndecl, 1, frame_addr);
+  sync_end = build_call_expr (cilk_sync_end_fndecl, 1, frame_addr);
+  sync_list = alloc_stmt_list ();
+  append_to_statement_list_force (sync_begin, &sync_list);
+  append_to_statement_list_force (sync, &sync_list);  
+  append_to_statement_list_force (sync_end, &sync_list);
+
+  return sync_list;
+}
diff --git gcc/cilk.h gcc/cilk.h
old mode 100644
new mode 100755
index 275b8b8..41ec273
--- gcc/cilk.h
+++ gcc/cilk.h
@@ -323,5 +323,10 @@  extern bool is_cilk_must_expand_fn (enum built_in_function);
 extern bool is_elem_fn_attribute_p (tree);
 extern bool is_cilk_function_decl (tree, tree);
 extern void clear_pragma_simd_list (void);
+extern tree set_cilk_except_flag (tree);
+extern tree clear_cilk_except_flag (tree);
+extern tree set_cilk_except_data (tree);
+extern void c_install_body_with_frame_cleanup (tree, tree);
+tree build_cilk_catch_sync (void);
 
 #endif /* GCC_CILK_H */
diff --git gcc/cp/ChangeLog.cilkplus gcc/cp/ChangeLog.cilkplus
old mode 100644
new mode 100755
index 9de4d57..b86af85
--- gcc/cp/ChangeLog.cilkplus
+++ gcc/cp/ChangeLog.cilkplus
@@ -1,3 +1,13 @@ 
+2013-02-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cp-cilk.c (insert_sync_stmt_after_catch): New function.
+	(cp_install_body_with_frame_cleanup): Likewise.
+	(cp_make_cilk_frame): called walk_tree with insert_sync_stmt_after_catch
+	as a function call parameter.
+	* cp-objcp-common.h (LANG_HOOKS_FRAME_CLEANUP): New define.
+	* except.c (do_begin_catch): Made this routine non-static.
+	(do_end_catch): Likewise.
+
 2013-01-09  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* semantics.c (finish_call_expr): Added a check for lambda expression 
diff --git gcc/cp/cp-cilk.c gcc/cp/cp-cilk.c
old mode 100644
new mode 100755
index 9df24ce..9a18180
--- gcc/cp/cp-cilk.c
+++ gcc/cp/cp-cilk.c
@@ -131,6 +131,7 @@  struct cilk_for_desc
   struct pointer_map_t *decl_map;
 };
 
+void cp_install_body_with_frame_cleanup (tree fndecl, tree body);
 void gimplify_cilk_for_stmt (tree *for_p, gimple_seq *pre_p);
 static tree compute_loop_var (struct cilk_for_desc *, tree, tree);
 static bool cp_extract_for_fields (struct cilk_for_desc *cfd, tree for_stmt);
@@ -815,6 +816,32 @@  in_cilk_block (void)
 /* This function will insert a _Cilk_sync right before a try block.  */
 
 static tree
+insert_sync_before_catch (tree *tp, int *walk_subtrees,
+			  void *data ATTRIBUTE_UNUSED)
+{
+  tree new_sync_stmt = NULL_TREE, synced_stmt_list = NULL_TREE;
+
+  synced_stmt_list = alloc_stmt_list ();
+  if (TREE_CODE (*tp) == HANDLER)
+    {
+      new_sync_stmt = build_cilk_catch_sync ();
+      gcc_assert (new_sync_stmt && new_sync_stmt != error_mark_node);
+      append_to_statement_list_force (new_sync_stmt, &synced_stmt_list);
+      append_to_statement_list_force (HANDLER_BODY (*tp), &synced_stmt_list);
+      HANDLER_BODY (*tp) = synced_stmt_list;
+      
+      /* We don't need to go any deeper.  */
+      *walk_subtrees = 0;
+      
+      /* We are finished here.  We only need to find the first catch block.  */
+      return *tp;
+    }
+  return NULL;
+}
+
+/* This function will insert a _Cilk_sync right before a try block.  */
+
+static tree
 insert_sync_stmt (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 {
   tree new_sync_stmt = NULL_TREE, synced_stmt_list = NULL_TREE;
@@ -895,6 +922,7 @@  cp_make_cilk_frame (tree compstmt)
       /* Here we talk through all the subtrees of compstmt and as soon as
 	 we find a try block, we insert a _Cilk_sync right before it.  */
       cp_walk_tree (&compstmt, insert_sync_stmt, NULL, NULL);
+      cp_walk_tree (&compstmt, insert_sync_before_catch, NULL, NULL);
     }
 
   return decl;
@@ -2898,3 +2926,41 @@  cilk_lambda_fn_temp (tree lambda_fn)
   add_local_decl (cfun, return_var);
   return return_var;
 }
+
+/* This function installs the internal functions of spawn helper and parent.  */
+
+void
+cp_install_body_with_frame_cleanup (tree fndecl, tree body)
+{
+  tree list, catch_tf_expr;
+  tree try_catch_expr, catch_list, try_finally_expr, except_flag, except_data;
+  tree frame = make_cilk_frame (fndecl);
+  tree dtor = build_cilk_function_exit (frame, false, false);
+  extern tree do_begin_catch (void);
+  extern tree do_end_catch (tree);
+  add_local_decl (cfun, frame);
+
+  DECL_SAVED_TREE (fndecl) = (list = alloc_stmt_list ());
+
+  catch_list = alloc_stmt_list ();
+  except_flag = set_cilk_except_flag (frame);
+  except_data = set_cilk_except_data (frame);
+  append_to_statement_list (except_flag, &catch_list);
+  append_to_statement_list (except_data, &catch_list);
+  append_to_statement_list (do_begin_catch (), &catch_list);
+  append_to_statement_list (build_throw (NULL_TREE), &catch_list);
+  #if 1
+  append_to_statement_list (build_cilk_function_exit (frame, false, false),
+			    &catch_list);
+  #endif
+  catch_tf_expr = build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
+			      catch_list, do_end_catch (NULL_TREE));
+  catch_list = build2 (CATCH_EXPR, void_type_node, NULL_TREE, catch_tf_expr);
+
+  try_catch_expr = build_stmt (EXPR_LOCATION (body), TRY_CATCH_EXPR, body,
+			       catch_list);
+  try_finally_expr = build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR,
+				 try_catch_expr, dtor);
+  append_to_statement_list_force (try_finally_expr, &list);
+}
+
diff --git gcc/cp/cp-objcp-common.h gcc/cp/cp-objcp-common.h
index bcd42d9..4b96b43 100644
--- gcc/cp/cp-objcp-common.h
+++ gcc/cp/cp-objcp-common.h
@@ -166,4 +166,8 @@  extern void cp_common_init_ts (void);
 
 #undef LANG_HOOKS_ELEM_FN_CREATE_FN
 #define LANG_HOOKS_ELEM_FN_CREATE_FN elem_fn_create_fn
+
+#undef LANG_HOOKS_FRAME_CLEANUP
+#define LANG_HOOKS_FRAME_CLEANUP cp_install_body_with_frame_cleanup
+
 #endif /* GCC_CP_OBJCP_COMMON */
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
old mode 100644
new mode 100755
index 26e8c0f..031bb43
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -6107,6 +6107,7 @@  extern void warn_unimplemented_cilk             (bool fatal);
 extern void build_cilk_types                    (void);
 extern void cilk_gimplify_for_stmt             (tree *, tree *);
 extern void gimplify_cilk_for_stmt             (tree *, gimple_seq *);
+extern void cp_install_body_with_frame_cleanup (tree, tree);
 extern tree build_cilk_run                     (tree);
 extern bool cilk_valid_spawn                   (tree);
 extern void cilk_init_frame_descriptor         (struct function *, bool);
diff --git gcc/cp/except.c gcc/cp/except.c
index 16a7c45..9a5b64a 100644
--- gcc/cp/except.c
+++ gcc/cp/except.c
@@ -35,9 +35,9 @@  along with GCC; see the file COPYING3.  If not see
 
 static void push_eh_cleanup (tree);
 static tree prepare_eh_type (tree);
-static tree do_begin_catch (void);
+tree do_begin_catch (void);
 static int dtor_nothrow (tree);
-static tree do_end_catch (tree);
+tree do_end_catch (tree);
 static bool decl_is_java_type (tree decl, int err);
 static void initialize_handler_parm (tree, tree);
 static tree do_allocate_exception (tree);
@@ -182,7 +182,7 @@  do_get_exception_ptr (void)
 /* Build up a call to __cxa_begin_catch, to tell the runtime that the
    exception has been handled.  */
 
-static tree
+tree
 do_begin_catch (void)
 {
   tree fn;
@@ -230,7 +230,7 @@  dtor_nothrow (tree type)
 /* Build up a call to __cxa_end_catch, to destroy the exception object
    for the current catch block if no others are currently using it.  */
 
-static tree
+tree
 do_end_catch (tree type)
 {
   tree fn, cleanup;
diff --git gcc/langhooks-def.h gcc/langhooks-def.h
old mode 100644
new mode 100755
index 8c0af7f..3085a02
--- gcc/langhooks-def.h
+++ gcc/langhooks-def.h
@@ -217,9 +217,11 @@  void lhd_gimplify_cilk_for (tree *, gimple_seq *, gimple_seq *);
 void lhd_gimplify_cilk_sync (tree *, gimple_seq *);
 void lhd_elem_fn_create_fn (tree);
 void lhd_cilk_check_ctrl_flow (tree *);
+void lhd_install_body_with_frame_cleanup (tree, tree);
 #define LANG_HOOKS_CILK_RECOGNIZE_SPAWN hook_bool_tree_false
 #define LANG_HOOKS_CILK_VALID_CTOR hook_bool_tree_false
 #define LANG_HOOKS_CILK_VALID_SPAWN lhd_cilk_valid_spawn
+#define LANG_HOOKS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup
 #define LANG_HOOKS_GIMPLIFY_CILK_SPAWN lhd_gimplify_cilk_spawn
 #define LANG_HOOKS_GIMPLIFY_CILK_FOR   lhd_gimplify_cilk_for
 #define LANG_HOOKS_GIMPLIFY_CILK_SYNC  lhd_gimplify_cilk_sync
@@ -229,7 +231,8 @@  void lhd_cilk_check_ctrl_flow (tree *);
   LANG_HOOKS_CILK_RECOGNIZE_SPAWN,	\
   LANG_HOOKS_CILK_VALID_CTOR,		\
   LANG_HOOKS_CILK_VALID_SPAWN,		\
-  LANG_HOOKS_GIMPLIFY_CILK_SPAWN,      	\
+  LANG_HOOKS_FRAME_CLEANUP,     	\
+  LANG_HOOKS_GIMPLIFY_CILK_SPAWN,	\
   LANG_HOOKS_GIMPLIFY_CILK_FOR,		\
   LANG_HOOKS_GIMPLIFY_CILK_SYNC,	\
   LANG_HOOKS_CILK_CHECK_CTRL_FLOW,      \
diff --git gcc/langhooks.c gcc/langhooks.c
old mode 100644
new mode 100755
index bcd4284..1e53465
--- gcc/langhooks.c
+++ gcc/langhooks.c
@@ -730,7 +730,17 @@  lhd_elem_fn_create_fn (tree x ATTRIBUTE_UNUSED)
   return;
 }
 
-void lhd_cilk_check_ctrl_flow (tree *x ATTRIBUTE_UNUSED)
+void
+lhd_cilk_check_ctrl_flow (tree *x ATTRIBUTE_UNUSED)
+{
+  return;
+}
+
+/* Empty function for install that will cleanup the frame in spawn helper.  */
+
+void
+lhd_install_body_with_frame_cleanup (tree x ATTRIBUTE_UNUSED,
+				     tree y ATTRIBUTE_UNUSED)
 {
   return;
 }
diff --git gcc/langhooks.h gcc/langhooks.h
old mode 100644
new mode 100755
index 76c0975..c375596
--- gcc/langhooks.h
+++ gcc/langhooks.h
@@ -231,6 +231,7 @@  struct lang_hooks_for_cilkplus
   bool (*recognize_spawn) (tree);
   bool (*spawnable_constructor) (tree);
   bool (*cilk_valid_spawn) (tree);
+  void (*install_body_with_frame_cleanup) (tree, tree);
   void (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *);
   void (*gimplify_cilk_for) (tree *, gimple_seq *, gimple_seq *);
   void (*gimplify_cilk_sync) (tree *, gimple_seq *);
diff --git gcc/testsuite/ChangeLog.cilkplus gcc/testsuite/ChangeLog.cilkplus
old mode 100644
new mode 100755
index 47b85ba..ac965b9
--- gcc/testsuite/ChangeLog.cilkplus
+++ gcc/testsuite/ChangeLog.cilkplus
@@ -1,3 +1,7 @@ 
+2013-02-04  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* g++.dg/cilk-plus/cilk_keywords_test/execute/catch_exc.cc: New test.
+
 2013-01-22  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* gcc.dg/cilk-plus/cilk_keywords_test/errors/grainsize_error1.c: New
diff --git gcc/testsuite/g++.dg/cilk-plus/cilk_keywords_test/execute/catch_exc.cc gcc/testsuite/g++.dg/cilk-plus/cilk_keywords_test/execute/catch_exc.cc
new file mode 100755
index 0000000..c48d89b
--- /dev/null
+++ gcc/testsuite/g++.dg/cilk-plus/cilk_keywords_test/execute/catch_exc.cc
@@ -0,0 +1,63 @@ 
+#include <assert.h>
+#include <unistd.h>
+#if HAVE_IO
+#include <cstdio>
+#include <cilk/cilk_api.h>
+#endif
+#include <cstdlib>
+
+
+void func(int volatile* steal_me) 
+{
+  while (! (*steal_me)) 
+    {
+      usleep(2000);
+    }
+#if HAVE_IO
+  printf("Foo executing on %d\n", __cilkrts_get_worker_number());
+#endif
+  throw 5;
+}
+
+void my_test() 
+{
+  volatile int steal_me = 0;
+
+  try 
+    {
+      _Cilk_spawn func(&steal_me);
+#if HAVE_IO
+      printf("Continuation executing on %d\n",
+	     __cilkrts_get_worker_number());
+#endif
+      steal_me = 1;
+      _Cilk_sync;
+      goto bad;
+    }
+
+  catch (int x) 
+    {
+#if HAVE_IO
+      printf("We caught x = %d\n", x);
+#endif
+      assert(x == 5);
+    }
+  if (0) 
+    {
+    bad:
+#if HAVE_IO
+      printf("We should not be here!\n");
+#endif
+      assert(0);
+    }
+}
+
+
+int main() 
+{
+  my_test();
+#if HAVE_IO
+  printf("PASSED\n");
+#endif
+  return 0;
+}