// // Dis VM // File: builtin_module.h // Author: arr // #ifndef _DISVM_SRC_INCLUDE_BUILTIN_MODULE_H_ #define _DISVM_SRC_INCLUDE_BUILTIN_MODULE_H_ #include #include #include "runtime.h" #define BUILTIN_MODULE_PREFIX_STR "$" #define BUILTIN_MODULE_PREFIX_CHAR '$' namespace disvm { namespace runtime { namespace builtin { // Called to initialize built-in modules. // This will be called once per process hosting a VM. void initialize_builtin_modules(); // Defined as 'Runtab' in Inferno (limbo/stubs.c) struct vm_runtab_t { // Function identification const char *name; uint32_t sig; // Function pointer vm_exec_t fn; // Function frame type word_t frame_size; word_t frame_pointer_count; byte_t frame_pointer_map[16]; }; // Called by the built-in module during initialization void register_module_exports(const char *name, word_t table_length, const vm_runtab_t *module_runtime_table); // Get the supplied built-in module. std::shared_ptr get_builtin_module(const char *name); } // [SPEC] All allocated frames have the following base layout. // See 'struct Frame' in Inferno (include/interp.h) // The base frame does not include the return register since that // is typed on the generated function frame type. struct vm_frame_base_alloc_t { vm_pc_t p_pc; // Previous PC vm_frame_t *p_fp; // Previous frame pointer vm_module_ref_t *p_mr; // Previous module ref pointer_t reserved; // Reserved for VM }; struct vm_frame_constants { static constexpr auto register_size_in_bytes() { return sizeof(word_t); } // Includes registers on base frame plus the implied return register static constexpr auto default_register_count() { return (sizeof(vm_frame_base_alloc_t) / register_size_in_bytes()) + 1; } // [SPEC] The fixed point registers are defined by their usage in the // Inferno implementation. They rely on the 'temp' registers defined below. // See fixed point opcodes in Inferno (libinterp/xec.c). static constexpr auto fixed_point_register_1_offset() { return default_register_count() * register_size_in_bytes(); } static constexpr auto fixed_point_register_2_offset() { return fixed_point_register_1_offset() + (2 * register_size_in_bytes()); } // [SPEC] The official Limbo compiler allocates additional 'temp' registers on all call frames. // See 'STemp', 'RTemp', and 'DTemp' in Inferno (limbo/limbo.h) static constexpr auto limbo_temp_register_count() { return 3; } // Define the first argument offset in a Limbo compiler generated call frame. static constexpr auto limbo_first_arg_register_offset() { return (default_register_count() + limbo_temp_register_count()) * register_size_in_bytes(); } }; // // Helpers for accessing VM types // // Get value-type reference template ValueType& vt_ref(pointer_t vt) { assert(vt != nullptr); return *reinterpret_cast(vt); } // Get allocation type value template typename std::enable_if::value, AllocType *>::type at_val(pointer_t at) { assert(at != nullptr); return vm_alloc_t::from_allocation(*reinterpret_cast(at)); } // Get allocation type value - base alloc type template<> inline vm_alloc_t *at_val(pointer_t at) { assert(at != nullptr); return vm_alloc_t::from_allocation(*reinterpret_cast(at)); } // Get pointer type reference inline pointer_t &pt_ref(pointer_t pt) { assert(pt != nullptr); return *reinterpret_cast(pt); } } } #endif // _DISVM_SRC_INCLUDE_BUILTIN_MODULE_H_