diff options
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 72 |
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, ¶m_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 |