aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-intrinsic.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 16447b2..77b67c3 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -23,6 +23,7 @@
#include "rust-diagnostics.h"
#include "rust-location.h"
#include "rust-constexpr.h"
+#include "rust-session-manager.h"
#include "rust-tree.h"
#include "tree-core.h"
#include "rust-gcc.h"
@@ -194,6 +195,9 @@ expect_handler (bool likely)
};
}
+static tree
+try_handler (Context *ctx, TyTy::FnType *fntype);
+
inline tree
sorry_handler (Context *ctx, TyTy::FnType *fntype)
{
@@ -241,6 +245,7 @@ static const std::map<std::string,
{"likely", expect_handler (true)},
{"unlikely", expect_handler (false)},
{"assume", assume_handler},
+ {"try", try_handler},
};
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
@@ -1266,5 +1271,72 @@ assume_handler (Context *ctx, TyTy::FnType *fntype)
return fndecl;
}
+static tree
+try_handler (Context *ctx, TyTy::FnType *fntype)
+{
+ rust_assert (fntype->get_params ().size () == 3);
+
+ tree lookup = NULL_TREE;
+ if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+ return lookup;
+ auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+ enter_intrinsic_block (ctx, fndecl);
+
+ // BUILTIN try_handler FN BODY BEGIN
+ // setup the params
+ std::vector<Bvariable *> param_vars;
+ compile_fn_params (ctx, fntype, fndecl, &param_vars);
+ if (!Backend::function_set_parameters (fndecl, param_vars))
+ return error_mark_node;
+ tree enclosing_scope = NULL_TREE;
+
+ bool panic_is_abort = Session::get_instance ().options.get_panic_strategy ()
+ == CompileOptions::PanicStrategy::Abort;
+ 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 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);
+ Backend::block_add_statements (try_block,
+ std::vector<tree>{try_call,
+ normal_return_stmt});
+ if (panic_is_abort)
+ {
+ // skip building the try-catch construct
+ ctx->add_statement (try_block);
+ finalize_intrinsic_block (ctx, fndecl);
+ return fndecl;
+ }
+
+ tree eh_pointer
+ = 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);
+
+ 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});
+ // 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);
+ ctx->add_statement (eh_construct);
+ // BUILTIN try_handler FN BODY END
+ finalize_intrinsic_block (ctx, fndecl);
+
+ return fndecl;
+}
+
} // namespace Compile
} // namespace Rust