#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"
};
}
+static tree
+try_handler (Context *ctx, TyTy::FnType *fntype);
+
inline tree
sorry_handler (Context *ctx, TyTy::FnType *fntype)
{
{"likely", expect_handler (true)},
{"unlikely", expect_handler (false)},
{"assume", assume_handler},
+ {"try", try_handler},
};
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
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