diff --git a/lib/llvm-backend/cpp/object_loader.cpp b/lib/llvm-backend/cpp/object_loader.cpp index 5323505781c..bf034a30875 100644 --- a/lib/llvm-backend/cpp/object_loader.cpp +++ b/lib/llvm-backend/cpp/object_loader.cpp @@ -7,201 +7,214 @@ extern "C" void __deregister_frame(uint8_t *); struct MemoryManager : llvm::RuntimeDyld::MemoryManager { public: - MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} - - virtual ~MemoryManager() override { - deregisterEHFrames(); - // Deallocate all of the allocated memory. - callbacks.dealloc_memory(code_section.base, code_section.size); - callbacks.dealloc_memory(read_section.base, read_section.size); - callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); - } - - virtual uint8_t* allocateCodeSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name) override { - return allocate_bump(code_section, code_bump_ptr, size, alignment); - } - - virtual uint8_t* allocateDataSection(uintptr_t size, unsigned alignment, unsigned section_id, llvm::StringRef section_name, bool read_only) override { - // Allocate from the read-only section or the read-write section, depending on if this allocation - // should be read-only or not. - if (read_only) { - return allocate_bump(read_section, read_bump_ptr, size, alignment); - } else { - return allocate_bump(readwrite_section, readwrite_bump_ptr, size, alignment); - } - } - - virtual void reserveAllocationSpace( - uintptr_t code_size, - uint32_t code_align, - uintptr_t read_data_size, - uint32_t read_data_align, - uintptr_t read_write_data_size, - uint32_t read_write_data_align - ) override { - auto aligner = [](uintptr_t ptr, size_t align) { - if (ptr == 0) { - return align; - } - return (ptr + align - 1) & ~(align - 1); - }; - - - uint8_t *code_ptr_out = nullptr; - size_t code_size_out = 0; - auto code_result = callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, &code_ptr_out, &code_size_out); - assert(code_result == RESULT_OK); - code_section = Section { code_ptr_out, code_size_out }; - code_bump_ptr = (uintptr_t)code_ptr_out; - - uint8_t *read_ptr_out = nullptr; - size_t read_size_out = 0; - auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096), PROTECT_READ_WRITE, &read_ptr_out, &read_size_out); - assert(read_result == RESULT_OK); - read_section = Section { read_ptr_out, read_size_out }; - read_bump_ptr = (uintptr_t)read_ptr_out; - - uint8_t *readwrite_ptr_out = nullptr; - size_t readwrite_size_out = 0; - auto readwrite_result = callbacks.alloc_memory(aligner(read_write_data_size, 4096), PROTECT_READ_WRITE, &readwrite_ptr_out, &readwrite_size_out); - assert(readwrite_result == RESULT_OK); - readwrite_section = Section { readwrite_ptr_out, readwrite_size_out }; - readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; + MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {} + + virtual ~MemoryManager() override { + deregisterEHFrames(); + // Deallocate all of the allocated memory. + callbacks.dealloc_memory(code_section.base, code_section.size); + callbacks.dealloc_memory(read_section.base, read_section.size); + callbacks.dealloc_memory(readwrite_section.base, readwrite_section.size); + } + + virtual uint8_t *allocateCodeSection(uintptr_t size, unsigned alignment, + unsigned section_id, + llvm::StringRef section_name) override { + return allocate_bump(code_section, code_bump_ptr, size, alignment); + } + + virtual uint8_t *allocateDataSection(uintptr_t size, unsigned alignment, + unsigned section_id, + llvm::StringRef section_name, + bool read_only) override { + // Allocate from the read-only section or the read-write section, depending + // on if this allocation should be read-only or not. + if (read_only) { + return allocate_bump(read_section, read_bump_ptr, size, alignment); + } else { + return allocate_bump(readwrite_section, readwrite_bump_ptr, size, + alignment); } + } + + virtual void reserveAllocationSpace(uintptr_t code_size, uint32_t code_align, + uintptr_t read_data_size, + uint32_t read_data_align, + uintptr_t read_write_data_size, + uint32_t read_write_data_align) override { + auto aligner = [](uintptr_t ptr, size_t align) { + if (ptr == 0) { + return align; + } + return (ptr + align - 1) & ~(align - 1); + }; - /* Turn on the `reserveAllocationSpace` callback. */ - virtual bool needsToReserveAllocationSpace() override { - return true; + uint8_t *code_ptr_out = nullptr; + size_t code_size_out = 0; + auto code_result = + callbacks.alloc_memory(aligner(code_size, 4096), PROTECT_READ_WRITE, + &code_ptr_out, &code_size_out); + assert(code_result == RESULT_OK); + code_section = Section{code_ptr_out, code_size_out}; + code_bump_ptr = (uintptr_t)code_ptr_out; + + uint8_t *read_ptr_out = nullptr; + size_t read_size_out = 0; + auto read_result = callbacks.alloc_memory(aligner(read_data_size, 4096), + PROTECT_READ_WRITE, &read_ptr_out, + &read_size_out); + assert(read_result == RESULT_OK); + read_section = Section{read_ptr_out, read_size_out}; + read_bump_ptr = (uintptr_t)read_ptr_out; + + uint8_t *readwrite_ptr_out = nullptr; + size_t readwrite_size_out = 0; + auto readwrite_result = callbacks.alloc_memory( + aligner(read_write_data_size, 4096), PROTECT_READ_WRITE, + &readwrite_ptr_out, &readwrite_size_out); + assert(readwrite_result == RESULT_OK); + readwrite_section = Section{readwrite_ptr_out, readwrite_size_out}; + readwrite_bump_ptr = (uintptr_t)readwrite_ptr_out; + } + + /* Turn on the `reserveAllocationSpace` callback. */ + virtual bool needsToReserveAllocationSpace() override { return true; } + + virtual void registerEHFrames(uint8_t *addr, uint64_t LoadAddr, + size_t size) override { +// We don't know yet how to do this on Windows, so we hide this on compilation +// so we can compile and pass spectests on unix systems +#ifndef _WIN32 + eh_frame_ptr = addr; + eh_frame_size = size; + eh_frames_registered = true; + callbacks.visit_fde(addr, size, __register_frame); +#endif + } + + virtual void deregisterEHFrames() override { +// We don't know yet how to do this on Windows, so we hide this on compilation +// so we can compile and pass spectests on unix systems +#ifndef _WIN32 + if (eh_frames_registered) { + callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); } - - virtual void registerEHFrames(uint8_t* addr, uint64_t LoadAddr, size_t size) override { - // We don't know yet how to do this on Windows, so we hide this on compilation - // so we can compile and pass spectests on unix systems - #ifndef _WIN32 - eh_frame_ptr = addr; - eh_frame_size = size; - eh_frames_registered = true; - callbacks.visit_fde(addr, size, __register_frame); - #endif +#endif + } + + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { + auto code_result = + callbacks.protect_memory(code_section.base, code_section.size, + mem_protect_t::PROTECT_READ_EXECUTE); + if (code_result != RESULT_OK) { + return false; } - virtual void deregisterEHFrames() override { - // We don't know yet how to do this on Windows, so we hide this on compilation - // so we can compile and pass spectests on unix systems - #ifndef _WIN32 - if (eh_frames_registered) { - callbacks.visit_fde(eh_frame_ptr, eh_frame_size, __deregister_frame); - } - #endif + auto read_result = callbacks.protect_memory( + read_section.base, read_section.size, mem_protect_t::PROTECT_READ); + if (read_result != RESULT_OK) { + return false; } - virtual bool finalizeMemory(std::string *ErrMsg = nullptr) override { - auto code_result = callbacks.protect_memory(code_section.base, code_section.size, mem_protect_t::PROTECT_READ_EXECUTE); - if (code_result != RESULT_OK) { - return false; - } + // The readwrite section is already mapped as read-write. - auto read_result = callbacks.protect_memory(read_section.base, read_section.size, mem_protect_t::PROTECT_READ); - if (read_result != RESULT_OK) { - return false; - } + return false; + } - // The readwrite section is already mapped as read-write. - - return false; - } + virtual void + notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, + const llvm::object::ObjectFile &Obj) override {} - virtual void notifyObjectLoaded(llvm::RuntimeDyld &RTDyld, const llvm::object::ObjectFile &Obj) override {} private: - struct Section { - uint8_t* base; - size_t size; + struct Section { + uint8_t *base; + size_t size; + }; + + uint8_t *allocate_bump(Section §ion, uintptr_t &bump_ptr, size_t size, + size_t align) { + auto aligner = [](uintptr_t &ptr, size_t align) { + ptr = (ptr + align - 1) & ~(align - 1); }; - uint8_t* allocate_bump(Section& section, uintptr_t& bump_ptr, size_t size, size_t align) { - auto aligner = [](uintptr_t& ptr, size_t align) { - ptr = (ptr + align - 1) & ~(align - 1); - }; + // Align the bump pointer to the requires alignment. + aligner(bump_ptr, align); - // Align the bump pointer to the requires alignment. - aligner(bump_ptr, align); + auto ret_ptr = bump_ptr; + bump_ptr += size; - auto ret_ptr = bump_ptr; - bump_ptr += size; + assert(bump_ptr <= (uintptr_t)section.base + section.size); - assert(bump_ptr <= (uintptr_t)section.base + section.size); + return (uint8_t *)ret_ptr; + } - return (uint8_t*)ret_ptr; - } - - Section code_section, read_section, readwrite_section; - uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; - uint8_t* eh_frame_ptr; - size_t eh_frame_size; - bool eh_frames_registered = false; + Section code_section, read_section, readwrite_section; + uintptr_t code_bump_ptr, read_bump_ptr, readwrite_bump_ptr; + uint8_t *eh_frame_ptr; + size_t eh_frame_size; + bool eh_frames_registered = false; - callbacks_t callbacks; + callbacks_t callbacks; }; struct SymbolLookup : llvm::JITSymbolResolver { public: - SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {} - - void lookup(const LookupSet& symbols, OnResolvedFunction OnResolved) { - LookupResult result; + SymbolLookup(callbacks_t callbacks) : callbacks(callbacks) {} - for (auto symbol : symbols) { - result.emplace(symbol, symbol_lookup(symbol)); - } + void lookup(const LookupSet &symbols, OnResolvedFunction OnResolved) { + LookupResult result; - OnResolved(result); + for (auto symbol : symbols) { + result.emplace(symbol, symbol_lookup(symbol)); } - llvm::Expected getResponsibilitySet(const LookupSet &Symbols) { - const std::set empty; - return empty; - } + OnResolved(result); + } + + llvm::Expected getResponsibilitySet(const LookupSet &Symbols) { + const std::set empty; + return empty; + } private: - llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { - uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); + llvm::JITEvaluatedSymbol symbol_lookup(llvm::StringRef name) { + uint64_t addr = callbacks.lookup_vm_symbol(name.data(), name.size()); - return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); - } + return llvm::JITEvaluatedSymbol(addr, llvm::JITSymbolFlags::None); + } - callbacks_t callbacks; + callbacks_t callbacks; }; -WasmModule::WasmModule( - const uint8_t *object_start, - size_t object_size, - callbacks_t callbacks -) : memory_manager(std::unique_ptr(new MemoryManager(callbacks))) -{ - - - if (auto created_object_file = llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( - llvm::StringRef((const char *)object_start, object_size), "object" - ))) { - object_file = cantFail(std::move(created_object_file)); - SymbolLookup symbol_resolver(callbacks); - runtime_dyld = std::unique_ptr(new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); - - runtime_dyld->setProcessAllSections(true); - - runtime_dyld->loadObject(*object_file); - runtime_dyld->finalizeWithMemoryManagerLocking(); - - if (runtime_dyld->hasError()) { - _init_failed = true; - return; - } - } else { - _init_failed = true; +WasmModule::WasmModule(const uint8_t *object_start, size_t object_size, + callbacks_t callbacks) + : memory_manager( + std::unique_ptr(new MemoryManager(callbacks))) { + + if (auto created_object_file = + llvm::object::ObjectFile::createObjectFile(llvm::MemoryBufferRef( + llvm::StringRef((const char *)object_start, object_size), + "object"))) { + object_file = cantFail(std::move(created_object_file)); + SymbolLookup symbol_resolver(callbacks); + runtime_dyld = std::unique_ptr( + new llvm::RuntimeDyld(*memory_manager, symbol_resolver)); + + runtime_dyld->setProcessAllSections(true); + + runtime_dyld->loadObject(*object_file); + runtime_dyld->finalizeWithMemoryManagerLocking(); + + if (runtime_dyld->hasError()) { + _init_failed = true; + return; } + } else { + _init_failed = true; + } } -void* WasmModule::get_func(llvm::StringRef name) const { - auto symbol = runtime_dyld->getSymbol(name); - return (void*)symbol.getAddress(); +void *WasmModule::get_func(llvm::StringRef name) const { + auto symbol = runtime_dyld->getSymbol(name); + return (void *)symbol.getAddress(); } diff --git a/lib/llvm-backend/cpp/object_loader.hh b/lib/llvm-backend/cpp/object_loader.hh index 2952835de0b..7a410b2dc07 100644 --- a/lib/llvm-backend/cpp/object_loader.hh +++ b/lib/llvm-backend/cpp/object_loader.hh @@ -6,257 +6,215 @@ #include -typedef enum -{ - PROTECT_NONE, - PROTECT_READ, - PROTECT_READ_WRITE, - PROTECT_READ_EXECUTE, +typedef enum { + PROTECT_NONE, + PROTECT_READ, + PROTECT_READ_WRITE, + PROTECT_READ_EXECUTE, } mem_protect_t; -typedef enum -{ - RESULT_OK, - RESULT_ALLOCATE_FAILURE, - RESULT_PROTECT_FAILURE, - RESULT_DEALLOC_FAILURE, - RESULT_OBJECT_LOAD_FAILURE, +typedef enum { + RESULT_OK, + RESULT_ALLOCATE_FAILURE, + RESULT_PROTECT_FAILURE, + RESULT_DEALLOC_FAILURE, + RESULT_OBJECT_LOAD_FAILURE, } result_t; -typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, uint8_t **ptr_out, size_t *size_out); -typedef result_t (*protect_memory_t)(uint8_t *ptr, size_t size, mem_protect_t protect); +typedef result_t (*alloc_memory_t)(size_t size, mem_protect_t protect, + uint8_t **ptr_out, size_t *size_out); +typedef result_t (*protect_memory_t)(uint8_t *ptr, size_t size, + mem_protect_t protect); typedef result_t (*dealloc_memory_t)(uint8_t *ptr, size_t size); typedef uintptr_t (*lookup_vm_symbol_t)(const char *name_ptr, size_t length); typedef void (*fde_visitor_t)(uint8_t *fde); -typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, fde_visitor_t visitor); +typedef result_t (*visit_fde_t)(uint8_t *fde, size_t size, + fde_visitor_t visitor); typedef void (*trampoline_t)(void *, void *, void *, void *); -typedef struct -{ - /* Memory management. */ - alloc_memory_t alloc_memory; - protect_memory_t protect_memory; - dealloc_memory_t dealloc_memory; +typedef struct { + /* Memory management. */ + alloc_memory_t alloc_memory; + protect_memory_t protect_memory; + dealloc_memory_t dealloc_memory; - lookup_vm_symbol_t lookup_vm_symbol; + lookup_vm_symbol_t lookup_vm_symbol; - visit_fde_t visit_fde; + visit_fde_t visit_fde; } callbacks_t; -typedef struct -{ - size_t data, vtable; +typedef struct { + size_t data, vtable; } box_any_t; -struct WasmException -{ - public: - virtual std::string description() const noexcept = 0; +struct WasmException { +public: + virtual std::string description() const noexcept = 0; }; -struct UncatchableException : WasmException -{ - public: - virtual std::string description() const noexcept override - { - return "Uncatchable exception"; - } +struct UncatchableException : WasmException { +public: + virtual std::string description() const noexcept override { + return "Uncatchable exception"; + } }; -struct UserException : UncatchableException -{ - public: - UserException(size_t data, size_t vtable) : error_data({ data, vtable }) {} +struct UserException : UncatchableException { +public: + UserException(size_t data, size_t vtable) : error_data({data, vtable}) {} - virtual std::string description() const noexcept override - { - return "user exception"; - } + virtual std::string description() const noexcept override { + return "user exception"; + } - // The parts of a `Box`. - box_any_t error_data; + // The parts of a `Box`. + box_any_t error_data; }; -struct BreakpointException : UncatchableException -{ - public: - BreakpointException(uintptr_t callback) : callback(callback) {} +struct BreakpointException : UncatchableException { +public: + BreakpointException(uintptr_t callback) : callback(callback) {} - virtual std::string description() const noexcept override - { - return "breakpoint exception"; - } + virtual std::string description() const noexcept override { + return "breakpoint exception"; + } - uintptr_t callback; + uintptr_t callback; }; -struct WasmTrap : UncatchableException -{ - public: - enum Type - { - Unreachable = 0, - IncorrectCallIndirectSignature = 1, - MemoryOutOfBounds = 2, - CallIndirectOOB = 3, - IllegalArithmetic = 4, - Unknown, - }; - - WasmTrap(Type type) : type(type) {} - - virtual std::string description() const noexcept override - { - std::ostringstream ss; - ss - << "WebAssembly trap:" << '\n' - << " - type: " << type << '\n'; - - return ss.str(); - } - - Type type; - - private: - friend std::ostream &operator<<(std::ostream &out, const Type &ty) - { - switch (ty) - { - case Type::Unreachable: - out << "unreachable"; - break; - case Type::IncorrectCallIndirectSignature: - out << "incorrect call_indirect signature"; - break; - case Type::MemoryOutOfBounds: - out << "memory access out-of-bounds"; - break; - case Type::CallIndirectOOB: - out << "call_indirect out-of-bounds"; - break; - case Type::IllegalArithmetic: - out << "illegal arithmetic operation"; - break; - case Type::Unknown: - default: - out << "unknown"; - break; - } - return out; +struct WasmTrap : UncatchableException { +public: + enum Type { + Unreachable = 0, + IncorrectCallIndirectSignature = 1, + MemoryOutOfBounds = 2, + CallIndirectOOB = 3, + IllegalArithmetic = 4, + Unknown, + }; + + WasmTrap(Type type) : type(type) {} + + virtual std::string description() const noexcept override { + std::ostringstream ss; + ss << "WebAssembly trap:" << '\n' << " - type: " << type << '\n'; + + return ss.str(); + } + + Type type; + +private: + friend std::ostream &operator<<(std::ostream &out, const Type &ty) { + switch (ty) { + case Type::Unreachable: + out << "unreachable"; + break; + case Type::IncorrectCallIndirectSignature: + out << "incorrect call_indirect signature"; + break; + case Type::MemoryOutOfBounds: + out << "memory access out-of-bounds"; + break; + case Type::CallIndirectOOB: + out << "call_indirect out-of-bounds"; + break; + case Type::IllegalArithmetic: + out << "illegal arithmetic operation"; + break; + case Type::Unknown: + default: + out << "unknown"; + break; } + return out; + } }; -struct CatchableException : WasmException -{ - public: - CatchableException(uint32_t type_id, uint32_t value_num) : type_id(type_id), value_num(value_num) {} +struct CatchableException : WasmException { +public: + CatchableException(uint32_t type_id, uint32_t value_num) + : type_id(type_id), value_num(value_num) {} - virtual std::string description() const noexcept override - { - return "catchable exception"; - } + virtual std::string description() const noexcept override { + return "catchable exception"; + } - uint32_t type_id, value_num; - uint64_t values[1]; + uint32_t type_id, value_num; + uint64_t values[1]; }; -struct WasmModule -{ - public: - WasmModule( - const uint8_t *object_start, - size_t object_size, - callbacks_t callbacks); - - void *get_func(llvm::StringRef name) const; - - bool _init_failed = false; - private: - std::unique_ptr memory_manager; - std::unique_ptr object_file; - std::unique_ptr runtime_dyld; +struct WasmModule { +public: + WasmModule(const uint8_t *object_start, size_t object_size, + callbacks_t callbacks); + + void *get_func(llvm::StringRef name) const; + + bool _init_failed = false; + +private: + std::unique_ptr memory_manager; + std::unique_ptr object_file; + std::unique_ptr runtime_dyld; }; -extern "C" -{ - void callback_trampoline(void *, void *); +extern "C" { +void callback_trampoline(void *, void *); - result_t module_load(const uint8_t *mem_ptr, size_t mem_size, callbacks_t callbacks, WasmModule **module_out) - { - *module_out = new WasmModule(mem_ptr, mem_size, callbacks); +result_t module_load(const uint8_t *mem_ptr, size_t mem_size, + callbacks_t callbacks, WasmModule **module_out) { + *module_out = new WasmModule(mem_ptr, mem_size, callbacks); - if ((*module_out)->_init_failed) { - return RESULT_OBJECT_LOAD_FAILURE; - } + if ((*module_out)->_init_failed) { + return RESULT_OBJECT_LOAD_FAILURE; + } - return RESULT_OK; - } + return RESULT_OK; +} - [[noreturn]] void throw_trap(WasmTrap::Type ty) { - throw WasmTrap(ty); - } +[[noreturn]] void throw_trap(WasmTrap::Type ty) { throw WasmTrap(ty); } - void module_delete(WasmModule *module) - { - delete module; - } +void module_delete(WasmModule *module) { delete module; } - // Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust - // side. - [[noreturn]] void throw_any(size_t data, size_t vtable) { - throw UserException(data, vtable); - } +// Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust +// side. +[[noreturn]] void throw_any(size_t data, size_t vtable) { + throw UserException(data, vtable); +} - // Throw a pointer that's assumed to be codegen::BreakpointHandler on the - // rust side. - [[noreturn]] void throw_breakpoint(uintptr_t callback) { - throw BreakpointException(callback); - } +// Throw a pointer that's assumed to be codegen::BreakpointHandler on the +// rust side. +[[noreturn]] void throw_breakpoint(uintptr_t callback) { + throw BreakpointException(callback); +} - bool invoke_trampoline( - trampoline_t trampoline, - void *ctx, - void *func, - void *params, - void *results, - WasmTrap::Type *trap_out, - box_any_t *user_error, - void *invoke_env) throw() - { - try - { - trampoline(ctx, func, params, results); - return true; - } - catch (const WasmTrap &e) - { - *trap_out = e.type; - return false; - } - catch (const UserException &e) - { - *user_error = e.error_data; - return false; - } - catch (const BreakpointException &e) { - callback_trampoline(user_error, (void *)e.callback); - return false; - } - catch (const WasmException &e) - { - *trap_out = WasmTrap::Type::Unknown; - return false; - } - catch (...) - { - *trap_out = WasmTrap::Type::Unknown; - return false; - } - } +bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func, + void *params, void *results, WasmTrap::Type *trap_out, + box_any_t *user_error, void *invoke_env) noexcept { + try { + trampoline(ctx, func, params, results); + return true; + } catch (const WasmTrap &e) { + *trap_out = e.type; + return false; + } catch (const UserException &e) { + *user_error = e.error_data; + return false; + } catch (const BreakpointException &e) { + callback_trampoline(user_error, (void *)e.callback); + return false; + } catch (const WasmException &e) { + *trap_out = WasmTrap::Type::Unknown; + return false; + } catch (...) { + *trap_out = WasmTrap::Type::Unknown; + return false; + } +} - void *get_func_symbol(WasmModule *module, const char *name) - { - return module->get_func(llvm::StringRef(name)); - } +void *get_func_symbol(WasmModule *module, const char *name) { + return module->get_func(llvm::StringRef(name)); +} }