3#include <sysio/vm/allocator.hpp> 
    4#include <sysio/vm/constants.hpp> 
    5#include <sysio/vm/exceptions.hpp> 
    6#include <sysio/vm/execution_interface.hpp> 
    7#include <sysio/vm/host_function.hpp> 
    8#include <sysio/vm/opcodes.hpp> 
    9#include <sysio/vm/signals.hpp> 
   10#include <sysio/vm/types.hpp> 
   11#include <sysio/vm/utils.hpp> 
   12#include <sysio/vm/wasm_stack.hpp> 
   24#include <system_error> 
   30#define _XOPEN_SOURCE 700 
   35namespace sysio { 
namespace vm {
 
   37   struct null_host_functions {
 
   38      template<
typename... 
A>
 
   41                       "Should never get here because it's impossible to link a module " 
   42                       "that imports any host functions, when no host functions are available");
 
 
   47      template <
typename HostFunctions>
 
   49         using type = 
typename HostFunctions::host_type_t;
 
   53         using type = std::nullptr_t;
 
   56      template <
typename HF>
 
   59      template <
typename HostFunctions>
 
   61         using type = 
typename HostFunctions::type_converter_t;
 
   68      template <
typename HF>
 
   71      template <
typename HostFunctions>
 
   73         using type = HostFunctions;
 
   79      template <
typename HF>
 
   83   template<
typename Derived, 
typename Host>
 
   87      Derived& 
derived() { 
return static_cast<Derived&
>(*this); }
 
  106      inline void    exit(std::error_code err = std::error_code()) {
 
  109         throw wasm_exit_exception{
"Exiting"};
 
 
  112      inline module&     get_module() { return _mod; }
 
  124         SYS_VM_ASSERT(_mod.error == 
nullptr, wasm_interpreter_exception, _mod.error);
 
  126         _linear_memory = _wasm_alloc->get_base_ptr<
char>();
 
  127         if(_mod.memories.size()) {
 
  128            SYS_VM_ASSERT(_mod.memories[0].limits.initial <= _max_pages, wasm_bad_alloc, 
"Cannot allocate initial linear memory.");
 
  129            _wasm_alloc->reset(_mod.memories[0].limits.initial);
 
  131            _wasm_alloc->reset();
 
  133         for (
uint32_t i = 0; i < _mod.data.size(); i++) {
 
  134            const auto& data_seg = _mod.data[i];
 
  135            uint32_t offset = data_seg.offset.value.i32; 
 
  136            auto available_memory =  _mod.memories[0].limits.initial * 
static_cast<uint64_t>(
page_size);
 
  137            auto required_memory = 
static_cast<uint64_t>(offset) + data_seg.data.size();
 
  138            SYS_VM_ASSERT(required_memory <= available_memory, wasm_memory_exception, 
"data out of range");
 
  139            auto addr = _linear_memory + offset;
 
  140            memcpy((
char*)(addr), data_seg.data.raw(), data_seg.data.size());
 
  144         for (
uint32_t i = 0; i < _mod.globals.size(); i++) {
 
  145            if (_mod.globals[i].type.mutability)
 
  146               _mod.globals[i].current = _mod.globals[i].init;
 
 
  150      template <
typename Visitor, 
typename... Args>
 
  151      inline std::optional<operand_stack_elem> 
execute(host_type* host, Visitor&& 
visitor, 
const std::string_view 
func,
 
  154         return derived().execute(host, std::forward<Visitor>(
visitor), func_index, std::forward<Args>(args)...);
 
 
  157      template <
typename Visitor, 
typename... Args>
 
  159         if (_mod.start != std::numeric_limits<uint32_t>::max())
 
  160            derived().execute(host, std::forward<Visitor>(
visitor), _mod.start);
 
 
  165      template<
typename... Args>
 
  182         throw wasm_memory_exception{ 
"wasm memory out-of-bounds" };
 
 
  185      char*                           _linear_memory    = 
nullptr;
 
  196   template<
typename Host>
 
  203   template<
bool EnableBacktrace>
 
  204   struct frame_info_holder {};
 
  206   struct frame_info_holder<true> {
 
  207      void* 
volatile _bottom_frame = 
nullptr;
 
  208      void* 
volatile _top_frame = 
nullptr;
 
  211   template<
typename Host, 
bool EnableBacktrace = false>
 
  216      using base_type::execute;
 
  217      using base_type::base_type;
 
  218      using base_type::_mod;
 
  219      using base_type::_rhf;
 
  220      using base_type::_error_code;
 
  221      using base_type::handle_signal;
 
  222      using base_type::get_operand_stack;
 
  223      using base_type::linear_memory;
 
  224      using base_type::get_interface;
 
  233         const auto& ft = _mod.get_function_type(index);
 
  234         uint32_t num_params = ft.param_types.size();
 
  236         uint32_t original_operands = get_operand_stack().size();
 
  238         for(
uint32_t i = 0; i < ft.param_types.size(); ++i) {
 
  239            switch(ft.param_types[i]) {
 
  240             case i32: get_operand_stack().push(i32_const_t{
stack[num_params - i - 1].i32}); 
break;
 
  241             case i64: get_operand_stack().push(i64_const_t{
stack[num_params - i - 1].i64}); 
break;
 
  242             case f32: get_operand_stack().push(f32_const_t{
stack[num_params - i - 1].f32}); 
break;
 
  243             case f64: get_operand_stack().push(f64_const_t{
stack[num_params - i - 1].f64}); 
break;
 
  244             default: assert(!
"Unexpected type in param_types.");
 
  247         _rhf(_host, get_interface(), _mod.import_functions[index]);
 
  250         auto set_result = [&result](
auto val) { std::memcpy(&result, &val, 
sizeof(val)); };
 
  251         if(ft.return_count) {
 
  253            switch(ft.return_type) {
 
  254             case i32: set_result(el.
to_ui32()); 
break;
 
  255             case i64: set_result(el.
to_ui64()); 
break;
 
  256             case f32: set_result(el.
to_f32()); 
break;
 
  257             case f64: set_result(el.
to_f64()); 
break;
 
  258             default: assert(!
"Unexpected function return type.");
 
  262         assert(get_operand_stack().size() == original_operands);
 
 
  268         get_operand_stack().eat(0);
 
 
  271      template <
typename... Args>
 
  273         auto saved_host = _host;
 
  274         auto saved_os_size = get_operand_stack().size();
 
  275         auto g = 
scope_guard([&](){ _host = saved_host; get_operand_stack().eat(saved_os_size); });
 
  279         const func_type& ft = _mod.get_function_type(func_index);
 
  280         this->type_check_args(ft, 
static_cast<Args&&
>(args)...);
 
  282         native_value args_raw[] = { transform_arg(
static_cast<Args&&
>(args))... };
 
  285            if (func_index < _mod.get_imported_functions_size()) {
 
  286               std::reverse(args_raw + 0, args_raw + 
sizeof...(Args));
 
  287               result = call_host_function(args_raw, func_index);
 
  289               std::size_t maximum_stack_usage =
 
  290                  (_mod.maximum_stack + 2 ) * (_remaining_call_depth + 1) +
 
  291                 sizeof...(Args) + 4 ;
 
  298               auto fn = 
reinterpret_cast<native_value (*)(
void*, 
void*)
>(_mod.code[func_index - _mod.get_imported_functions_size()].jit_code_offset + _mod.allocator._code_base);
 
  300               if constexpr(EnableBacktrace) {
 
  302                  sigemptyset(&block_mask);
 
  303                  sigaddset(&block_mask, SIGPROF);
 
  304                  pthread_sigmask(SIG_BLOCK, &block_mask, nullptr);
 
  305                  auto restore = scope_guard{[this, &block_mask] {
 
  306                     this->_top_frame = nullptr;
 
  307                     this->_bottom_frame = nullptr;
 
  308                     pthread_sigmask(SIG_UNBLOCK, &block_mask, nullptr);
 
  311                  vm::invoke_with_signal_handler([&]() {
 
  312                     result = execute<sizeof...(Args)>(args_raw, fn, this, base_type::linear_memory(), stack);
 
  315                  vm::invoke_with_signal_handler([&]() {
 
  316                     result = execute<
sizeof...(Args)>(args_raw, fn, 
this, base_type::linear_memory(), 
stack);
 
  320         } 
catch(wasm_exit_exception&) {
 
  326         else switch (ft.return_type) {
 
  327            case i32: 
return {i32_const_t{result.i32}};
 
  328            case i64: 
return {i64_const_t{result.i64}};
 
  329            case f32: 
return {f32_const_t{result.f32}};
 
  330            case f64: 
return {f64_const_t{result.f64}};
 
  331            default: assert(!
"Unexpected function return type");
 
  333         __builtin_unreachable();
 
 
  337      int backtrace(
void** out, 
int count, 
void* uc)
 const {
 
  338         static_assert(EnableBacktrace);
 
  339         void* end = this->_top_frame;
 
  340         if(end == 
nullptr) 
return 0;
 
  343         if(this->_bottom_frame) {
 
  344            rbp = this->_bottom_frame;
 
  345         } 
else if(
count != 0) {
 
  348               auto rip = 
reinterpret_cast<unsigned char*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext->__ss.__rip);
 
  349               rbp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext->__ss.__rbp);
 
  350               auto rsp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext->__ss.__rsp);
 
  351#elif defined __FreeBSD__ 
  352               auto rip = 
reinterpret_cast<unsigned char*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.mc_rip);
 
  353               rbp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.mc_rbp);
 
  354               auto rsp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.mc_rsp);
 
  356               auto rip = 
reinterpret_cast<unsigned char*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.gregs[REG_RIP]);
 
  357               rbp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.gregs[REG_RBP]);
 
  358               auto rsp = 
reinterpret_cast<void*
>(
static_cast<ucontext_t*
>(uc)->uc_mcontext.gregs[REG_RSP]);
 
  363               auto code_base = 
reinterpret_cast<const unsigned char*
>(_mod.allocator.get_code_start());
 
  364               auto code_end = code_base + _mod.allocator._code_size;
 
  365               if(rip >= code_base && rip < code_end && count > 1) {
 
  367                  if(*
reinterpret_cast<const unsigned char*
>(rip) == 0x55) {
 
  368                     if(rip != *
static_cast<void**
>(rsp)) { 
 
  369                        out[i++] = *
static_cast<void**
>(rsp);
 
  371                  } 
else if(rip[0] == 0x48 && rip[1] == 0x89 && (rip[2] == 0xe5 || rip[2] == 0x27)) {
 
  372                     if((rip - 1) != 
static_cast<void**
>(rsp)[1]) { 
 
  373                        out[i++] = 
static_cast<void**
>(rsp)[1];
 
  377                  else if(rip[0] == 0xc3) {
 
  378                     out[i++] = *
static_cast<void**
>(rsp);
 
  382               rbp = __builtin_frame_address(0);
 
  386            void* rip = 
static_cast<void**
>(rbp)[1];
 
  387            if(rbp == end) 
break;
 
  389            rbp = *
static_cast<void**
>(rbp);
 
  394      static constexpr bool async_backtrace() { 
return EnableBacktrace; }
 
  403         std::memset(&result, 0, 
sizeof(result));
 
  405         auto transformed_value = detail::resolve_result(tc, 
static_cast<T&&
>(
value)).data;
 
  406         std::memcpy(&result, &transformed_value, 
sizeof(transformed_value));
 
 
  414         static_assert(
sizeof(
native_value) == 8, 
"8-bytes expected for native_value");
 
  416         unsigned stack_check = 
context->_remaining_call_depth;
 
  419         register void* stack_top 
asm (
"r12") = 
stack;
 
  421#define ASM_CODE(before, after)                                         \ 
  423            "test %[stack_top], %[stack_top]; "                          \ 
  425            "mov %%rsp, %[stack_top]; "                                  \ 
  426            "sub $0x98, %%rsp; "                 \ 
  427            "mov %[stack_top], (%%rsp); "                                \ 
  430            "mov %%rsp, (%[stack_top]); "                                \ 
  431            "mov %[stack_top], %%rsp; "                                  \ 
  433            "stmxcsr 16(%%rsp); "                                        \ 
  434            "mov $0x1f80, %%rax; "                                       \ 
  435            "mov %%rax, 8(%%rsp); "                                      \ 
  436            "ldmxcsr 8(%%rsp); "                                         \ 
  437            "mov %[Count], %%rax; "                                      \ 
  438            "test %%rax, %%rax; "                                        \ 
  441            "movq (%[data]), %%r8; "                                     \ 
  442            "lea 8(%[data]), %[data]; "                                  \ 
  450            "add %[StackOffset], %%rsp; "                                \ 
  451            "ldmxcsr 16(%%rsp); "                                        \ 
  452            "mov (%%rsp), %%rsp; "                                       \ 
  454            : [result] "=&a" (result),  \ 
  455              [data] "+d" (data), [fun] "+c" (fun), [stack_top] "+r" (stack_top)  \ 
  456            : [context] "D" (context), [linear_memory] "S" (linear_memory), \ 
  457              [StackOffset] "n" (Count*8), [Count] "n" (Count), "b" (stack_check)  \ 
  460               "r8", "r9", "r10", "r11", \ 
  461              "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", \ 
  462              "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", \ 
  463              "mm0","mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm6",       \ 
  464              "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" \ 
  466         if constexpr (!EnableBacktrace) {
 
  469            ASM_CODE(
"movq %%rbp, 8(%[context]); ",
 
  470                     "xor %[fun], %[fun]; " 
  471                     "mov %[fun], 8(%[context]); ");
 
  478      host_type * _host = 
nullptr;
 
  482   template <
typename Host>
 
  487      using base_type::_mod;
 
  488      using base_type::_rhf;
 
  489      using base_type::_error_code;
 
  490      using base_type::handle_signal;
 
  491      using base_type::get_operand_stack;
 
  492      using base_type::linear_memory;
 
  493      using base_type::get_interface;
 
  500         static_assert(std::is_trivially_move_assignable_v<call_stack>, 
"This is seriously broken if call_stack move assignment might use the existing memory");
 
  502         if(mem_size > _base_allocator.mem_size) {
 
  506            _base_allocator.index = 0;
 
 
  513         if (index < _mod.get_imported_functions_size()) {
 
  515            const auto& ft = _mod.types[_mod.imports[index].type.func_t];
 
  519            _rhf(_state.host, get_interface(), _mod.import_functions[index]);
 
  526            set_pc( _mod.get_function_pc(index) );
 
 
  531         std::cout << 
"STACK { ";
 
  532         for (
int i = 0; i < get_operand_stack().size(); i++) {
 
  533            std::cout << 
"(" << i << 
")";
 
  534            visit(
overloaded { [&](i32_const_t el) { std::cout << 
"i32:" << el.data.ui << 
", "; },
 
  535                               [&](i64_const_t el) { std::cout << 
"i64:" << el.data.ui << 
", "; },
 
  536                               [&](f32_const_t el) { std::cout << 
"f32:" << el.data.f << 
", "; },
 
  537                               [&](f64_const_t el) { std::cout << 
"f64:" << el.data.f << 
", "; },
 
  538                               [&](
auto el) { std::cout << 
"(INDEX " << el.index() << 
"), "; } }, get_operand_stack().get(i));
 
 
  553      template <
bool Should_Exit=false>
 
  556         if constexpr (!Should_Exit)
 
  557            return_pc = _state.pc + 1;
 
  560         _last_op_index = get_operand_stack().size() - _mod.get_function_type(index).param_types.size();
 
 
  564         const auto& af = _as.pop();
 
  566         _last_op_index = af.last_op_index;
 
  568            compact_operand(get_operand_stack().size() - num_locals - 1);
 
  570            eat_operands(get_operand_stack().size() - num_locals);
 
 
  575         SYS_VM_ASSERT(index < _mod.globals.size(), wasm_interpreter_exception, 
"global index out of range");
 
  576         const auto& gl = _mod.globals[index];
 
  577         switch (gl.type.content_type) {
 
  578            case types::i32: 
return i32_const_t{ *(
uint32_t*)&gl.current.value.i32 };
 
  579            case types::i64: 
return i64_const_t{ *(
uint64_t*)&gl.current.value.i64 };
 
  580            case types::f32: 
return f32_const_t{ gl.current.value.f32 };
 
  581            case types::f64: 
return f64_const_t{ gl.current.value.f64 };
 
  582            default: 
throw wasm_interpreter_exception{ 
"invalid global type" };
 
 
  587         SYS_VM_ASSERT(index < _mod.globals.size(), wasm_interpreter_exception, 
"global index out of range");
 
  588         auto& gl = _mod.globals[index];
 
  589         SYS_VM_ASSERT(gl.type.mutability, wasm_interpreter_exception, 
"global is not mutable");
 
  591                                  SYS_VM_ASSERT(gl.type.content_type == types::i32, wasm_interpreter_exception,
 
  592                                                "expected i32 global type");
 
  593                                  gl.current.value.i32 = i.data.ui;
 
  595                                [&](
const i64_const_t& i) {
 
  596                                   SYS_VM_ASSERT(gl.type.content_type == types::i64, wasm_interpreter_exception,
 
  597                                                 "expected i64 global type");
 
  598                                   gl.current.value.i64 = i.data.ui;
 
  600                                [&](
const f32_const_t& 
f) {
 
  601                                   SYS_VM_ASSERT(gl.type.content_type == types::f32, wasm_interpreter_exception,
 
  602                                                 "expected f32 global type");
 
  603                                   gl.current.value.f32 = 
f.data.ui;
 
  605                                [&](
const f64_const_t& 
f) {
 
  606                                   SYS_VM_ASSERT(gl.type.content_type == types::f64, wasm_interpreter_exception,
 
  607                                                 "expected f64 global type");
 
  608                                   gl.current.value.f64 = 
f.data.ui;
 
  610                                [](
auto) { 
throw wasm_interpreter_exception{ 
"invalid global type" }; } },
 
 
  615         bool ret_val = 
false;
 
  616         visit(
overloaded{ [&](
const i32_const_t& i32) { ret_val = i32.data.ui; },
 
  617                           [&](
auto) { 
throw wasm_invalid_element{ 
"should be an i32 type" }; } },
 
 
  624            const auto& 
op = peek_operand((ft.
param_types.size() - 1) - i);
 
  627                                                   "function param type mismatch");
 
  629                                   [&](
const f32_const_t&) {
 
  631                                                    "function param type mismatch");
 
  633                                   [&](
const i64_const_t&) {
 
  635                                                    "function param type mismatch");
 
  637                                   [&](
const f64_const_t&) {
 
  639                                                    "function param type mismatch");
 
  641                                   [&](
auto) { 
throw wasm_interpreter_exception{ 
"function param invalid type" }; } },
 
 
  648         _state.pc = _mod.code[0].code + pc_offset;
 
 
  652      inline void     exit(std::error_code err = std::error_code()) {
 
  655         _state.exiting = 
true;
 
 
  660         _state = execution_state{};
 
  661         get_operand_stack().eat(_state.os_index);
 
  662         _as.eat(_state.as_index);
 
 
  665      template <
typename Visitor, 
typename... Args>
 
  668         return execute(host, std::forward<Visitor>(
visitor), table_elem(table_index), std::forward<Args>(args)...);
 
 
  671      template <
typename Visitor, 
typename... Args>
 
  672      inline std::optional<operand_stack_elem> 
execute(host_type* host, Visitor&& 
visitor, 
const std::string_view func,
 
  675         return execute(host, std::forward<Visitor>(
visitor), func_index, std::forward<Args>(args)...);
 
 
  678      template <
typename Visitor, 
typename... Args>
 
  680         if (_mod.start != std::numeric_limits<uint32_t>::max())
 
  681            execute(host, std::forward<Visitor>(
visitor), _mod.start);
 
 
  684      template <
typename Visitor, 
typename... Args>
 
  685      inline std::optional<operand_stack_elem> 
execute(host_type* host, Visitor&& 
visitor, 
uint32_t func_index, Args... args) {
 
  686         SYS_VM_ASSERT(func_index < std::numeric_limits<uint32_t>::max(), wasm_interpreter_exception,
 
  687                       "cannot execute function, function not found");
 
  689         auto last_last_op_index = _last_op_index;
 
  692         execution_state saved_state = _state;
 
  695         _state.as_index         = _as.size();
 
  696         _state.os_index         = get_operand_stack().size();
 
  699            get_operand_stack().eat(_state.os_index);
 
  700            _as.eat(_state.as_index);
 
  701            _state = saved_state;
 
  703            _last_op_index = last_last_op_index;
 
  706         this->type_check_args(_mod.get_function_type(func_index), 
static_cast<Args&&
>(args)...);
 
  708         push_call<true>(func_index);
 
  710         if (func_index < _mod.get_imported_functions_size()) {
 
  711            _rhf(_state.host, get_interface(), _mod.import_functions[func_index]);
 
  713            _state.pc = _mod.get_function_pc(func_index);
 
  714            setup_locals(func_index);
 
  715            vm::invoke_with_signal_handler([&]() {
 
  720         if (_mod.get_function_type(func_index).return_count && !_state.exiting) {
 
  721            return pop_operand();
 
 
  728         set_relative_pc(new_pc);
 
  729         if ((pop_info & 0x80000000u)) {
 
  730            const auto& 
op = pop_operand();
 
  731            eat_operands(get_operand_stack().size() - ((pop_info & 0x7FFFFFFFu) - 1));
 
  734            eat_operands(get_operand_stack().size() - pop_info);
 
 
  743            data[out++] = _state.pc;
 
  745         for(
int i = 0; out < limit && i < _as.size(); ++i) {
 
  746            data[out++] = _as.get_back(i).pc;
 
 
  753      template <
typename... Args>
 
  754      void push_args(Args&&... args) {
 
  757         (... , push_operand(detail::resolve_result(tc, std::move(args))));
 
  760      inline void setup_locals(
uint32_t index) {
 
  761         const auto& fn = _mod.code[index - _mod.get_imported_functions_size()];
 
  762         for (
uint32_t i = 0; i < fn.locals.size(); i++) {
 
  764               switch (fn.locals[i].type) {
 
  765                  case types::i32: push_operand(i32_const_t{ (
uint32_t)0 }); 
break;
 
  766                  case types::i64: push_operand(i64_const_t{ (
uint64_t)0 }); 
break;
 
  767                  case types::f32: push_operand(f32_const_t{ (
uint32_t)0 }); 
break;
 
  768                  case types::f64: push_operand(f64_const_t{ (
uint64_t)0 }); 
break;
 
  769                  default: 
throw wasm_interpreter_exception{ 
"invalid function param type" };
 
  774#define CREATE_TABLE_ENTRY(NAME, CODE) &&ev_label_##NAME, 
  775#define CREATE_LABEL(NAME, CODE)                                                                                  \ 
  776      ev_label_##NAME : visitor(ev_variant->template get<sysio::vm::SYS_VM_OPCODE_T(NAME)>());                    \ 
  777      ev_variant = _state.pc; \ 
  778      goto* dispatch_table[ev_variant->index()]; 
 
  779#define CREATE_EXIT_LABEL(NAME, CODE) ev_label_##NAME : \ 
 
  781#define CREATE_EMPTY_LABEL(NAME, CODE) ev_label_##NAME :  \ 
  782      throw wasm_interpreter_exception{"empty operand"}; 
 
  784      template <
typename Visitor>
 
  785      void execute(Visitor&& visitor) {
 
  786         static void* dispatch_table[] = {
 
  807         auto* ev_variant = _state.pc;
 
  808         goto *dispatch_table[ev_variant->index()];
 
  829                throw wasm_interpreter_exception{
"should never reach here"};
 
  833#undef CREATE_EMPTY_LABEL 
  835#undef CREATE_TABLE_ENTRY 
  837      struct execution_state {
 
  838         host_type* host           = 
nullptr;
 
  842         bool     exiting          = 
false;
 
  845      bounded_allocator _base_allocator = {
 
  846         (constants::max_call_depth + 1) * 
sizeof(activation_frame)
 
  848      execution_state _state;
 
  852      host_type*                      _host = 
nullptr;
 
auto & get_operand_stack()
execution_context_base(module &m)
static void type_check_args(const func_type &ft, Args &&...)
int32_t grow_linear_memory(int32_t pages)
std::error_code _error_code
std::error_code get_error_code() const
auto get_wasm_allocator()
void set_wasm_allocator(wasm_allocator *alloc)
void execute_start(host_type *host, Visitor &&visitor)
const auto & get_operand_stack() const
std::optional< operand_stack_elem > execute(host_type *host, Visitor &&visitor, const std::string_view func, Args... args)
static void handle_signal(int sig)
void set_max_pages(std::uint32_t max_pages)
wasm_allocator * _wasm_alloc
int32_t current_linear_memory() const
void exit(std::error_code err=std::error_code())
detail::host_invoker_t< Host > _rhf
void type_check(const func_type &ft)
void apply_pop_call(uint32_t num_locals, uint16_t return_count)
operand_stack_elem get_global(uint32_t index)
void push_call(uint32_t index)
activation_frame pop_call()
void execute_start(host_type *host, Visitor &&visitor)
uint32_t current_operands_index() const
bool is_true(const operand_stack_elem &el)
operand_stack_elem get_operand(uint32_t index) const
void eat_operands(uint32_t index)
void set_operand(uint32_t index, const operand_stack_elem &el)
uint32_t call_depth() const
void call(uint32_t index)
void push_call(activation_frame &&el)
std::optional< operand_stack_elem > execute(host_type *host, Visitor &&visitor, uint32_t func_index, Args... args)
uint32_t table_elem(uint32_t i)
void set_max_call_depth(uint32_t max_call_depth)
int backtrace(void **data, int limit, void *uc) const
std::optional< operand_stack_elem > execute_func_table(host_type *host, Visitor &&visitor, uint32_t table_index, Args... args)
void jump(uint32_t pop_info, uint32_t new_pc)
void exit(std::error_code err=std::error_code())
execution_context(module &m, uint32_t max_call_depth)
void set_global(uint32_t index, const operand_stack_elem &el)
operand_stack_elem & peek_operand(size_t i=0)
void inc_pc(uint32_t offset=1)
std::optional< operand_stack_elem > execute(host_type *host, Visitor &&visitor, const std::string_view func, Args... args)
operand_stack_elem pop_operand()
void push_operand(operand_stack_elem el)
void set_relative_pc(uint32_t pc_offset)
void compact_operand(uint32_t index)
std::optional< operand_stack_elem > execute(host_type *host, jit_visitor, uint32_t func_index, Args... args)
void set_max_call_depth(std::uint32_t max_call_depth)
native_value call_host_function(native_value *stack, uint32_t index)
native_value transform_arg(T &&value)
jit_execution_context(module &m, std::uint32_t max_call_depth)
uint32_t _remaining_call_depth
null_execution_context(module &m, std::uint32_t max_call_depth)
constexpr const auto & get() const &
void free(std::size_t size)
void alloc(size_t size=1)
int32_t get_current_page() const
typename type_converter< HF >::type type_converter_t
typename host_type< HF >::type host_type_t
typename host_invoker< HF >::type host_invoker_t
constexpr auto visit(Visitor &&vis, Variant &&var)
stack< activation_frame, constants::max_call_depth+1, bounded_allocator > call_stack
constexpr auto to_wasm_type_v
#define T(meth, val, expected)
schedule config_dir_name data_dir_name p2p_port http_port file_size name host(p2p_endpoint)) FC_REFLECT(tn_node_def
unsigned __int64 uint64_t
typename HostFunctions::host_type_t type
typename HostFunctions::type_converter_t type
guarded_vector< value_type > param_types
guarded_vector< memory_type > memories
void operator()(A &&...) const
#define SYS_VM_ASSERT(expr, exc_type, msg)
#define CREATE_EMPTY_LABEL(NAME, CODE)
#define CREATE_LABEL(NAME, CODE)
#define CREATE_EXIT_LABEL(NAME, CODE)
#define CREATE_TABLE_ENTRY(NAME, CODE)
#define SYS_VM_F64_CONSTANT_OPS(opcode_macro)
#define SYS_VM_RETURN_OP(opcode_macro)
#define SYS_VM_EXIT_OP(opcode_macro)
#define SYS_VM_COMPARISON_OPS(opcode_macro)
#define SYS_VM_MEMORY_OPS(opcode_macro)
#define SYS_VM_I64_CONSTANT_OPS(opcode_macro)
#define SYS_VM_I32_CONSTANT_OPS(opcode_macro)
#define SYS_VM_CALL_OPS(opcode_macro)
#define SYS_VM_NUMERIC_OPS(opcode_macro)
#define SYS_VM_CONVERSION_OPS(opcode_macro)
#define SYS_VM_VARIABLE_ACCESS_OPS(opcode_macro)
#define SYS_VM_EMPTY_OPS(opcode_macro)
#define SYS_VM_CALL_IMM_OPS(opcode_macro)
#define SYS_VM_CONTROL_FLOW_OPS(opcode_macro)
#define SYS_VM_ERROR_OPS(opcode_macro)
#define SYS_VM_PARAMETRIC_OPS(opcode_macro)
#define SYS_VM_F32_CONSTANT_OPS(opcode_macro)
#define SYS_VM_BR_TABLE_OP(opcode_macro)
memcpy((char *) pInfo->slotDescription, s, l)
c_gkp_out sizeof(template))