aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorliushuyu <liushuyu011@gmail.com>2023-09-09 14:19:06 -0600
committerArthur Cohen <arthur.cohen@embecosm.com>2025-03-21 12:56:56 +0100
commit165e7575a96af9ba901af199fa525f069efef574 (patch)
tree74b32a9ee4ad496246c8f8ea223d45f660f0d507
parent8ce8781f29b425bb20dd4fcdd3981de9aa57131b (diff)
downloadgcc-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.cc72
-rw-r--r--gcc/rust/lang.opt13
-rw-r--r--gcc/rust/rust-lang.cc2
-rw-r--r--gcc/rust/rust-session-manager.cc3
-rw-r--r--gcc/rust/rust-session-manager.h14
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, &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
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;