From: liushuyu <liushuyu...@gmail.com>

gcc/rust/ChangeLog:
        * backend/rust-compile-intrinsic.cc: add the new `catch_unwind` variant
        of the `try` intrinsic: this variant can be seen on Rust 1.78+
        and returns `()` instead of `i32`.
---
 gcc/rust/backend/rust-compile-intrinsic.cc | 57 ++++++++++++++++++----
 1 file changed, 47 insertions(+), 10 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 77b67c36c3e..0f054588220 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -196,7 +196,15 @@ expect_handler (bool likely)
 }
 
 static tree
-try_handler (Context *ctx, TyTy::FnType *fntype);
+try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api);
+
+const static std::function<tree (Context *, TyTy::FnType *)>
+try_handler (bool is_new_api)
+{
+  return [is_new_api] (Context *ctx, TyTy::FnType *fntype) {
+    return try_handler_inner (ctx, fntype, is_new_api);
+  };
+}
 
 inline tree
 sorry_handler (Context *ctx, TyTy::FnType *fntype)
@@ -245,7 +253,8 @@ static const std::map<std::string,
     {"likely", expect_handler (true)},
     {"unlikely", expect_handler (false)},
     {"assume", assume_handler},
-    {"try", try_handler},
+    {"try", try_handler (false)},
+    {"catch_unwind", try_handler (true)},
 };
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
@@ -1272,7 +1281,7 @@ assume_handler (Context *ctx, TyTy::FnType *fntype)
 }
 
 static tree
-try_handler (Context *ctx, TyTy::FnType *fntype)
+try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api)
 {
   rust_assert (fntype->get_params ().size () == 3);
 
@@ -1283,6 +1292,13 @@ try_handler (Context *ctx, TyTy::FnType *fntype)
 
   enter_intrinsic_block (ctx, fndecl);
 
+  // The following tricks are needed to make sure the try-catch blocks are not
+  // optimized away
+  TREE_READONLY (fndecl) = 0;
+  DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1;
+  DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"),
+                                       NULL_TREE, DECL_ATTRIBUTES (fndecl));
+
   // BUILTIN try_handler FN BODY BEGIN
   // setup the params
   std::vector<Bvariable *> param_vars;
@@ -1296,15 +1312,31 @@ try_handler (Context *ctx, TyTy::FnType *fntype)
   tree try_fn = Backend::var_expression (param_vars[0], UNDEF_LOCATION);
   tree user_data = Backend::var_expression (param_vars[1], UNDEF_LOCATION);
   tree catch_fn = Backend::var_expression (param_vars[2], UNDEF_LOCATION);
-  tree normal_return_stmt
-    = Backend::return_statement (fndecl, integer_zero_node, BUILTINS_LOCATION);
-  tree error_return_stmt
-    = Backend::return_statement (fndecl, integer_one_node, BUILTINS_LOCATION);
+  tree normal_return_stmt = NULL_TREE;
+  tree error_return_stmt = NULL_TREE;
   tree try_call = Backend::call_expression (try_fn, {user_data}, nullptr,
                                            BUILTINS_LOCATION);
   tree catch_call = NULL_TREE;
   tree try_block = Backend::block (fndecl, enclosing_scope, {}, UNDEF_LOCATION,
                                   UNDEF_LOCATION);
+
+  if (is_new_api)
+    {
+      auto ret_type = TyTyResolveCompile::get_unit_type ();
+      auto ret_expr = Backend::constructor_expression (ret_type, false, {}, -1,
+                                                      UNDEF_LOCATION);
+      normal_return_stmt
+       = Backend::return_statement (fndecl, ret_expr, BUILTINS_LOCATION);
+      error_return_stmt
+       = Backend::return_statement (fndecl, ret_expr, BUILTINS_LOCATION);
+    }
+  else
+    {
+      normal_return_stmt = Backend::return_statement (fndecl, 
integer_zero_node,
+                                                     BUILTINS_LOCATION);
+      error_return_stmt = Backend::return_statement (fndecl, integer_one_node,
+                                                    BUILTINS_LOCATION);
+    }
   Backend::block_add_statements (try_block,
                                 std::vector<tree>{try_call,
                                                   normal_return_stmt});
@@ -1320,17 +1352,22 @@ try_handler (Context *ctx, TyTy::FnType *fntype)
     = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER), 1,
                       integer_zero_node);
   catch_call = Backend::call_expression (catch_fn, {user_data, eh_pointer},
-                                        nullptr, BUILTINS_LOCATION);
+                                        NULL_TREE, BUILTINS_LOCATION);
 
   tree catch_block = Backend::block (fndecl, enclosing_scope, {},
                                     UNDEF_LOCATION, UNDEF_LOCATION);
   Backend::block_add_statements (catch_block,
                                 std::vector<tree>{catch_call,
                                                   error_return_stmt});
+  // emulate what cc1plus is doing for C++ try-catch
+  tree inner_eh_construct
+    = Backend::exception_handler_statement (catch_call, NULL_TREE,
+                                           error_return_stmt,
+                                           BUILTINS_LOCATION);
   // TODO(liushuyu): eh_personality needs to be implemented as a runtime thing
   auto eh_construct
-    = Backend::exception_handler_statement (try_block, catch_block, NULL_TREE,
-                                           BUILTINS_LOCATION);
+    = Backend::exception_handler_statement (try_block, inner_eh_construct,
+                                           NULL_TREE, BUILTINS_LOCATION);
   ctx->add_statement (eh_construct);
   // BUILTIN try_handler FN BODY END
   finalize_intrinsic_block (ctx, fndecl);
-- 
2.45.2

Reply via email to