diff --git a/lib/Interpreter/CppInterOpInterpreter.h b/lib/Interpreter/CppInterOpInterpreter.h index 06da263bd..e83069519 100644 --- a/lib/Interpreter/CppInterOpInterpreter.h +++ b/lib/Interpreter/CppInterOpInterpreter.h @@ -412,6 +412,18 @@ class Interpreter { } CompilationResult loadLibrary(const std::string& filename, bool lookup) { +#ifdef __EMSCRIPTEN__ + if (lookup) { + llvm::errs() << "[cppinterop] Warning: 'lookup' has no effect on WASM.\n"; + } + // In WASM: directly use Interpreter's LoadDynamicLibrary + if (auto Err = inner->LoadDynamicLibrary(filename.c_str())) { + llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), + "loadLibrary: "); + return kFailure; + } + return kSuccess; +#endif DynamicLibraryManager* DLM = getDynamicLibraryManager(); std::string canonicalLib; if (lookup) diff --git a/unittests/CppInterOp/CMakeLists.txt b/unittests/CppInterOp/CMakeLists.txt index 4cd66e5f2..3aabb05a9 100644 --- a/unittests/CppInterOp/CMakeLists.txt +++ b/unittests/CppInterOp/CMakeLists.txt @@ -97,6 +97,7 @@ if(EMSCRIPTEN) PUBLIC "SHELL: -s STACK_SIZE=32mb" PUBLIC "SHELL: -s INITIAL_MEMORY=128mb" PUBLIC "SHELL: --preload-file ${SYSROOT_PATH}/include@/include" + PUBLIC "SHELL: --preload-file ${CMAKE_CURRENT_BINARY_DIR}/TestSharedLib/unittests/bin/Release/libTestSharedLib.so@/libTestSharedLib.so" ) endif() diff --git a/unittests/CppInterOp/DynamicLibraryManagerTest.cpp b/unittests/CppInterOp/DynamicLibraryManagerTest.cpp index c881d9fdd..5f6499fd9 100644 --- a/unittests/CppInterOp/DynamicLibraryManagerTest.cpp +++ b/unittests/CppInterOp/DynamicLibraryManagerTest.cpp @@ -1,5 +1,6 @@ #include "gtest/gtest.h" +#include "clang/Basic/Version.h" #include "clang/Interpreter/CppInterOp.h" #include "llvm/Support/FileSystem.h" @@ -57,3 +58,29 @@ TEST(DynamicLibraryManagerTest, Sanity) { // invalidated... // EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero")); } + +TEST(DynamicLibraryManagerTest, BasicSymbolLookup) { +#ifndef EMSCRIPTEN + GTEST_SKIP() << "This test is only intended for Emscripten builds."; +#else + #if CLANG_VERSION_MAJOR < 20 + GTEST_SKIP() << "Support for loading shared libraries was added in LLVM 20."; + #endif +#endif + + ASSERT_TRUE(Cpp::CreateInterpreter()); + EXPECT_FALSE(Cpp::GetFunctionAddress("ret_zero")); + + // Load the library manually. Use known preload path (MEMFS path) + const char* wasmLibPath = "libTestSharedLib.so"; // Preloaded path in MEMFS + EXPECT_TRUE(Cpp::LoadLibrary(wasmLibPath, false)); + + Cpp::Process(""); + + void* Addr = Cpp::GetFunctionAddress("ret_zero"); + EXPECT_NE(Addr, nullptr) << "Symbol 'ret_zero' not found after dlopen."; + + using RetZeroFn = int (*)(); + auto Fn = reinterpret_cast(Addr); + EXPECT_EQ(Fn(), 0); +}