diff --git a/src/library/compiler/ir_interpreter.cpp b/src/library/compiler/ir_interpreter.cpp index 2aa1accc3e..03b3c48146 100644 --- a/src/library/compiler/ir_interpreter.cpp +++ b/src/library/compiler/ir_interpreter.cpp @@ -172,6 +172,7 @@ option_ref find_ir_decl(environment const & env, name const & n) { } static string_ref * g_mangle_prefix = nullptr; +static string_ref * g_boxed_suffix = nullptr; static string_ref * g_boxed_mangled_suffix = nullptr; // reuse the compiler's name mangling to compute native symbol names @@ -826,6 +827,7 @@ public: } object * call_boxed(name const & fn, object ** args) { + /** Like `call`, but taking (owned) `object *`s instead of `arg`s. */ symbol_cache_entry e = lookup_symbol(fn); unsigned n = decl_params(e.m_decl).size(); object * r; @@ -834,26 +836,17 @@ public: // directly call boxed function, nothing more to do r = curry(e.m_addr, n, args); } else { - // equivalent code to boxed stubs generated by the compiler: unbox args, box result, decrement borrowed args - - if (decl_tag(e.m_decl) == decl_kind::Extern) { - throw exception(sstream() << "unexpected external declaration '" << fn << "'"); + decl d = e.m_decl; + if (option_ref d_boxed = find_ir_decl(m_env, fn + *g_boxed_suffix)) { + d = *d_boxed.get(); } + // `d` now has a boxed signature // evaluate args in old stack frame for (unsigned i = 0; i < n; i++) { - type t = param_type(decl_params(e.m_decl)[i]); - m_arg_stack.push_back(unbox_t(args[i], t)); - if (type_is_scalar(t)) { - dec(args[i]); - } + m_arg_stack.push_back(args[i]); } push_frame(e.m_decl, 0); - r = box_t(eval_body(decl_fun_body(e.m_decl)), decl_type(e.m_decl)); - for (size_t i = 0; i < n; i++) { - if (param_borrow(decl_params(e.m_decl)[i])) { - dec(args[i]); - } - } + r = eval_body(decl_fun_body(e.m_decl)).m_obj; } pop_frame(r, decl_type(e.m_decl)); return r; @@ -905,6 +898,7 @@ uint32 run_main(environment const & env, int argv, char * argc[]) { void initialize_ir_interpreter() { ir::g_mangle_prefix = new string_ref("l_"); + ir::g_boxed_suffix = new string_ref("_boxed"); ir::g_boxed_mangled_suffix = new string_ref("___boxed"); DEBUG_CODE({ register_trace_class({"interpreter"}); @@ -915,6 +909,7 @@ void initialize_ir_interpreter() { void finalize_ir_interpreter() { delete ir::g_boxed_mangled_suffix; + delete ir::g_boxed_suffix; delete ir::g_mangle_prefix; } }