Skip to content

Commit

Permalink
rust/intrinsic: add try intrinsic and panic strategy options
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
liushuyu committed Dec 2, 2024
1 parent fa93e28 commit 873aaac
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 0 deletions.
72 changes: 72 additions & 0 deletions gcc/rust/backend/rust-compile-intrinsic.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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) {}
Expand Down Expand Up @@ -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
13 changes: 13 additions & 0 deletions gcc/rust/lang.opt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
2 changes: 2 additions & 0 deletions gcc/rust/rust-lang.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,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 ();
Expand Down
3 changes: 3 additions & 0 deletions gcc/rust/rust-session-manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,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;
Expand Down
14 changes: 14 additions & 0 deletions gcc/rust/rust-session-manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 873aaac

Please sign in to comment.