diff options
author | liushuyu <liushuyu011@gmail.com> | 2023-09-09 14:19:06 -0600 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2025-03-21 12:56:56 +0100 |
commit | 165e7575a96af9ba901af199fa525f069efef574 (patch) | |
tree | 74b32a9ee4ad496246c8f8ea223d45f660f0d507 | |
parent | 8ce8781f29b425bb20dd4fcdd3981de9aa57131b (diff) | |
download | gcc-165e7575a96af9ba901af199fa525f069efef574.zip gcc-165e7575a96af9ba901af199fa525f069efef574.tar.gz gcc-165e7575a96af9ba901af199fa525f069efef574.tar.bz2 |
gccrs: rust/intrinsic: add try intrinsic and panic strategy options
gcc/rust/ChangeLog:
* backend/rust-compile-intrinsic.cc: add `try` intrinsic handler.
* lang.opt: add `-frust-panic` option.
* rust-lang.cc: enable exception handler code generation.
* rust-session-manager.cc: add getter and setter for panic
strategy option.
* rust-session-manager.h: Likewise.
Signed-off-by: Zixing Liu <liushuyu011@gmail.com>
-rw-r--r-- | gcc/rust/backend/rust-compile-intrinsic.cc | 72 | ||||
-rw-r--r-- | gcc/rust/lang.opt | 13 | ||||
-rw-r--r-- | gcc/rust/rust-lang.cc | 2 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 3 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.h | 14 |
5 files changed, 104 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 diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index ae601eb..0e9aab4 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -212,4 +212,17 @@ frust-borrowcheck Rust Var(flag_borrowcheck) Use the WIP borrow checker. +frust-panic= +Rust Joined RejectNegative Enum(frust_panic) Var(flag_rust_panic) +-frust-edition=[unwind|abort] Panic strategy to compile crate with + +Enum +Name(frust_panic) Type(int) UnknownError(unknown panic strategy %qs) + +EnumValue +Enum(frust_panic) String(unwind) Value(0) + +EnumValue +Enum(frust_panic) String(abort) Value(1) + ; This comment is to ensure we retain the blank line above. diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index b84e114..f3a155d 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -143,6 +143,8 @@ grs_langhook_init_options_struct (struct gcc_options *opts) opts->x_warn_unused_result = 1; /* lets warn for infinite recursion*/ opts->x_warn_infinite_recursion = 1; + /* Enable exception handling (aka `panic!` in Rust) */ + opts->x_flag_exceptions = 1; // nothing yet - used by frontends to change specific options for the language Rust::Session::get_instance ().init_options (); diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index c0b4796c..1039fdf 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -266,6 +266,9 @@ Session::handle_option ( case OPT_frust_metadata_output_: options.set_metadata_output (arg); break; + case OPT_frust_panic_: + options.set_panic_strategy (flag_rust_panic); + break; default: break; diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index b5a715c..73a85b3 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -264,6 +264,13 @@ struct CompileOptions } compile_until = CompileStep::End; + enum class PanicStrategy + { + Unwind, + Abort, + } panic_strategy + = PanicStrategy::Unwind; + bool dump_option_enabled (DumpOption option) const { return dump_options.find (option) != dump_options.end (); @@ -320,6 +327,13 @@ struct CompileOptions const CompileStep &get_compile_until () const { return compile_until; } + void set_panic_strategy (int strategy) + { + panic_strategy = static_cast<PanicStrategy> (strategy); + } + + const PanicStrategy &get_panic_strategy () const { return panic_strategy; } + void set_metadata_output (const std::string &path) { metadata_output_path = path; |