Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to resolve undefined symbol error related to emscripten_longjmp #23731

Open
anutosh491 opened this issue Feb 24, 2025 · 11 comments
Open

Comments

@anutosh491
Copy link

anutosh491 commented Feb 24, 2025

Continuation on #23442 (comment)

I am trying to run clang-repl in the browser and run a code block having a try-catch block.

  1. For that I have llvm compiled against emscripten (we technically just need libclangInterpreter.a)
  2. I have a toy project that I am trying to make use of

i) CompilerModule.cpp : Simply creates a interpreter and run the Parse and Excute functions.

#include "llvm/Support/raw_ostream.h"
#include <clang/Basic/TargetOptions.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Interpreter/Interpreter.h>
#include <clang/Interpreter/Value.h>

#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/TargetRegistry.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Target/TargetMachine.h>

#include <iostream>

#include <dlfcn.h>
#include <unistd.h>

#include <emscripten.h>

llvm::SmallString<1024> OutputModule;
std::unique_ptr<clang::Interpreter> Interp;

extern "C" EMSCRIPTEN_KEEPALIVE void *get_last_module_addr() {
  return OutputModule.data();
}
extern "C" EMSCRIPTEN_KEEPALIVE uint32_t get_last_module_size() {
  return OutputModule.size_in_bytes();
}

int module_count = 0;

extern "C" EMSCRIPTEN_KEEPALIVE int init() {
  LLVMInitializeWebAssemblyTargetInfo();
  LLVMInitializeWebAssemblyTarget();
  LLVMInitializeWebAssemblyTargetMC();
  LLVMInitializeWebAssemblyAsmPrinter();

  clang::IncrementalCompilerBuilder CB;
  CB.SetCompilerArgs({"-target", "wasm32-unknown-emscripten", "-pie", "-shared",
                      "-std=c++20", "-xc++", "-resource-dir", "/lib/clang/19", "-v ", "-fwasm-exceptions"});
  auto CI = CB.CreateCpp();
  if (!CI) {
    std::cerr << "Failed to create compiler instance!" << std::endl;
    return -1;
  }

  assert((*CI)->hasDiagnostics() && "1 Compiler has no diagnostics !!");

  auto Interpreter = clang::Interpreter::create(std::move(*CI));
  if (!Interpreter) {
    std::cerr << "Failed to create interpreter!" << std::endl;
    return -2;
  }

  Interp = std::move(*Interpreter);

  return 0;
}

clang::PartialTranslationUnit *currentPTU;

extern "C" EMSCRIPTEN_KEEPALIVE int parse(const char *code) {
  auto PTU = Interp->Parse(code);
  if (!PTU) {
    std::cerr << "Failed to generate PTU" << std::endl;
    return -1;
  }
  currentPTU = &*PTU;

  if (currentPTU->TheModule) {
    llvm::errs() << "Generated LLVM IR:\n";
    currentPTU->TheModule->print(llvm::errs(), nullptr);
  } else {
    std::cerr << "No LLVM Module generated!" << std::endl;
  }

  return 0;
}
extern "C" EMSCRIPTEN_KEEPALIVE int execute() {
  auto error = Interp->Execute(*currentPTU);
  if (error) {
    std::cerr << "Failed to execute PTU" << std::endl;

    currentPTU->TheModule->print(llvm::errs(), nullptr);
    return -2;
  }

  return 0;
}
extern "C" EMSCRIPTEN_KEEPALIVE int parseandexecute(const char *code) {
  clang::Value V;
  auto error = Interp->ParseAndExecute(code, &V);

  llvm::errs() << "Generated LLVM IR:\n";
  currentPTU->TheModule->print(llvm::errs(), nullptr);
  //auto error = Interp->Execute(*currentPTU);
  if (error) {
    std::cerr << "doesn't work like we thought" << std::endl;
    return -2;
  }

  return 0;
}
  1. CMakeLists.txt
cmake_minimum_required(VERSION 3.20.0)
project(clang-wasm-repl)

find_package(LLVM REQUIRED CONFIG)
find_package(LLD REQUIRED CONFIG)
find_package(Clang REQUIRED CONFIG)

set (CMAKE_CXX_STANDARD 20)
add_compile_options(-Wall -pedantic -fPIC)

include_directories(${LLVM_INCLUDE_DIRS})
include_directories(${CLANG_INCLUDE_DIRS})

add_executable(Compiler CompilerModule.cpp)

# Link against LLVM libraries
target_link_libraries(Compiler embind)
target_link_libraries(Compiler clangInterpreter)

target_link_options(Compiler PUBLIC
    -O1
    -fwasm-exceptions
    #-fexceptions
    #-sSUPPORT_LONGJMP=wasm
    -sERROR_ON_UNDEFINED_SYMBOLS=0
    -sMODULARIZE
    -sEXPORT_ES6=1
    -sASSERTIONS=1
    -sALLOW_MEMORY_GROWTH=1
    -sINITIAL_MEMORY=128MB
    -sTOTAL_STACK=32MB
    -sMAIN_MODULE=1
    -sUSE_SDL=2
    -sEXPORTED_RUNTIME_METHODS=ccall,cwrap,stringToNewUTF8,getValue,setValue
    -sEXPORTED_FUNCTIONS=_malloc,_free,__ZTIN10emscripten3valE,_emscripten_longjmp
    "-Wl,--export=__clang_Interpreter_SetValueNoAlloc"
    #"-Wl,--export=emscripten_longjmp"
    #"-Wl,--export-all"
    # add sysroot location here
    --preload-file /Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/cache/sysroot/@/
)
@hoodmane
Copy link
Collaborator

Maybe the problem is that you've commented out #-sSUPPORT_LONGJMP=wasm.

@anutosh491
Copy link
Author

anutosh491 commented Feb 24, 2025

Hey @hoodmane,

Thanks a lot for the reply. Please feel free to educate yourself with what I am working on here #23442 (comment). Might answer any doubts you have.

Now replying back .... Hmmm doesn't -fwasm-exceptions enable that by default ? From docs

"
If native Wasm exceptions are used, SUPPORT_LONGJMP defaults to wasm, and if JavaScript-based exceptions are used or no exception support is used, it defaults to emscripten.
"

Giving some more context.

  1. So as I am running clang-repl in the browser and I am trying to achieve EH support through WASM EH. I pass -fwasm-exceptions in the init function in CompilerModule.cpp as shown above
  CB.SetCompilerArgs({"-target", "wasm32-unknown-emscripten", "-pie", "-shared",
                      "-std=c++20", "-xc++", "-resource-dir", "/lib/clang/19", "-v",  "-fwasm-exceptions"});
  1. So this in the cc1 command I see in the browser.

"" -cc1 -triple wasm32-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -main-file-name "<<< inputs >>>" -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-feature +exception-handling -target-feature +multivalue -target-feature +reference-types -exception-model=wasm -mllvm -wasm-enable-eh -target-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/ -v -fcoverage-compilation-dir=/ -resource-dir /lib/clang/19 -internal-isystem /include/wasm32-emscripten/c++/v1 -internal-isystem /include/c++/v1 -internal-isystem /lib/clang/19/include -internal-isystem /include/wasm32-emscripten -internal-isystem /include -std=c++20 -fdeprecated-macro -ferror-limit 19 -fvisibility=default -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -exception-model=wasm -fincremental-extensions -o "<<< inputs >>>.o" -x c++ "<<< inputs >>>"

  1. And now if I try executing something like
int main() {
    try {
        throw 1;
    } catch (...) {
        0;
    }
}

I see the correct LLVM IR being generated

Generated LLVM IR:
; ModuleID = 'incr_module_1'
source_filename = "incr_module_1"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-f128:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-emscripten"
@_ZTIi = external constant ptr
@__main_void = hidden alias i32 (), ptr @main
; Function Attrs: mustprogress noinline norecurse optnone
define noundef i32 @main() #0 personality ptr @__gxx_wasm_personality_v0 {
entry:
  %exn.slot = alloca ptr, align 4
  %exception = call ptr @__cxa_allocate_exception(i32 4) #3
  store i32 1, ptr %exception, align 16
  invoke void @__cxa_throw(ptr %exception, ptr @_ZTIi, ptr null) #4
          to label %unreachable unwind label %catch.dispatch
catch.dispatch:                                   ; preds = %entry
  %0 = catchswitch within none [label %catch.start] unwind to caller
catch.start:                                      ; preds = %catch.dispatch
  %1 = catchpad within %0 [ptr null]
  %2 = call ptr @llvm.wasm.get.exception(token %1)
  store ptr %2, ptr %exn.slot, align 4
  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
  br label %catch
catch:                                            ; preds = %catch.start
  %exn = load ptr, ptr %exn.slot, align 4
  %4 = call ptr @__cxa_begin_catch(ptr %exn) #3 [ "funclet"(token %1) ]
  call void @__cxa_end_catch() [ "funclet"(token %1) ]
  catchret from %1 to label %catchret.dest
catchret.dest:                                    ; preds = %catch
  br label %try.cont
try.cont:                                         ; preds = %catchret.dest
  ret i32 0
unreachable:                                      ; preds = %entry
  unreachable
}
declare ptr @__cxa_allocate_exception(i32)
declare void @__cxa_throw(ptr, ptr, ptr)
declare i32 @__gxx_wasm_personality_v0(...)
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare ptr @llvm.wasm.get.exception(token) #1
; Function Attrs: nocallback nofree nosync nounwind willreturn
declare i32 @llvm.wasm.get.ehselector(token) #1
; Function Attrs: nounwind memory(none)
declare i32 @llvm.eh.typeid.for.p0(ptr) #2
declare ptr @__cxa_begin_catch(ptr)
declare void @__cxa_end_catch()

And I think the correct WASM file generated

(module $incr_module_1.wasm
  (memory $env.memory (;0;) (import "env" "memory") 0)
  (table $env.__indirect_function_table (;0;) (import "env" "__indirect_function_table") 0 funcref)
  (global $__stack_pointer (;0;) (import "env" "__stack_pointer") (mut i32))
  (global $__memory_base (;1;) (import "env" "__memory_base") i32)
  (global $__table_base (;2;) (import "env" "__table_base") i32)
  (func $__cxa_allocate_exception (;0;) (import "env" "__cxa_allocate_exception") (param i32) (result i32))
  (tag $env.__cpp_exception (;0;) (import "env" "__cpp_exception") (param i32))
  (func $__cxa_throw (;1;) (import "env" "__cxa_throw") (param i32 i32 i32))
  (func $__cxa_begin_catch (;2;) (import "env" "__cxa_begin_catch") (param i32) (result i32))
  (func $__cxa_end_catch (;3;) (import "env" "__cxa_end_catch"))
  (global $typeinfo for int (;3;) (import "GOT.mem" "_ZTIi") (mut i32))
  (func $__wasm_call_ctors (;4;) (export "__wasm_call_ctors")
  )
  (func $__original_main (;5;) (export "__original_main") (result i32)
    (local $var0 i32)
    (local $var1 i32)
    (local $var2 i32)
    (local $var3 i32)
    (local $var4 i32)
    (local $var5 i32)
    (local $var6 i32)
    (local $var7 i32)
    (local $var8 i32)
    (local $var9 i32)
    (local $var10 i32)
    (local $var11 i32)
    (local $var12 i32)
    global.get $__stack_pointer
    local.set $var0
    i32.const 16
    local.set $var1
    local.get $var0
    local.get $var1
    i32.sub
    local.set $var2
    local.get $var2
    global.set $__stack_pointer
    i32.const 4
    local.set $var3
    local.get $var3
    call $__cxa_allocate_exception
    local.set $var4
    i32.const 1
    local.set $var5
    local.get $var4
    local.get $var5
    i32.store
    global.get $typeinfo for int
    local.set $var6
    i32.const 0
    local.set $var7
    block $label1
      block $label0 (result i32)
        try_table catch $env.__cpp_exception $label0
          local.get $var4
          local.get $var6
          local.get $var7
          call $__cxa_throw
          br $label1
        end
        unreachable
      end $label0
      local.set $var8
      local.get $var2
      global.set $__stack_pointer
      local.get $var2
      local.get $var8
      i32.store offset=12
      local.get $var2
      i32.load offset=12
      local.set $var9
      local.get $var9
      call $__cxa_begin_catch
      drop
      call $__cxa_end_catch
      i32.const 0
      local.set $var10
      i32.const 16
      local.set $var11
      local.get $var2
      local.get $var11
      i32.add
      local.set $var12
      local.get $var12
      global.set $__stack_pointer
      local.get $var10
      return
    end $label1
    unreachable
  )
  (func $main (;6;) (export "main") (param $var0 i32) (param $var1 i32) (result i32)
    (local $var2 i32)
    call $__original_main
    local.set $var2
    local.get $var2
    return
  )
)

But the dlopen step fails and I see this error

Error in loading dynamic library /tmp/incr_module_1.wasm: LinkError: WebAssembly.Instance(): Import #6 "env" "__cpp_exception": tag import requires a WebAssembly.Tag
Could not load dynamic lib: /tmp/incr_module_1.wasm
LinkError: WebAssembly.Instance(): Import #6 "env" "__cpp_exception": tag import requires a WebAssembly.Tag
Failed to execute PTU

IMP: The above was the case when I was building my toy project with -fexceptions. And hence I thought that now that we pass the wasm exceptions flag to clang-repl we should do the same while linking . So it was then that I switched here from excpetions to wasm-exceptions

target_link_options(Compiler PUBLIC
    -O1
    -fwasm-exceptions
    #-fexceptions
    #-sSUPPORT_LONGJMP=wasm
    -sERROR_ON_UNDEFINED_SYMBOLS=0

@anutosh491
Copy link
Author

anutosh491 commented Feb 24, 2025

After the latest step when I realized that maybe Compiler.wasm doesn't have access to __cpp_exception .... I switched to using wasm-excpetions in my CMakelists.txt and since then I see this while building

(xeus-cpp-wasm-build) anutosh491@Anutoshs-MacBook-Air build3 % emmake make -j8
make: make -j8
[ 50%] Building CXX object CMakeFiles/Compiler.dir/CompilerModule.cpp.o
[100%] Linking CXX executable Compiler.js
em++: warning: EXPORTED_FUNCTIONS is not valid with LINKABLE set (normally due to SIDE_MODULE=1/MAIN_MODULE=1) since all functions are exported this mode.  To export only a subset use SIDE_MODULE=2/MAIN_MODULE=2 [-Wunused-command-line-argument]
error: undefined symbol: emscripten_longjmp (referenced by root reference (e.g. compiled C/C++ code))
warning: To disable errors for undefined symbols use `-sERROR_ON_UNDEFINED_SYMBOLS=0`
warning: _emscripten_longjmp may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
Error: Aborting compilation due to previous errors
em++: error: '/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/bin/node /Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/src/compiler.mjs /var/folders/m1/cdn74f917994jd99d_2cpf440000gn/T/tmpbinli6dh.json' failed (returned 1)
make[2]: *** [Compiler.js] Error 1
make[1]: *** [CMakeFiles/Compiler.dir/all] Error 2
make: *** [all] Error 2
emmake: error: 'make -j8' failed (returned 2)

Note that after I updated my CMakeLIsts.txt file .... I kinda trying to forecfully handle this variables. I tried

  1. -sSUPPORT_LONGJMP=wasm
  2. sEXPORTED_FUNCTIONS=_malloc,_free,__ZTIN10emscripten3valE,_emscripten_longjmp (added it here basically)
  3. "-Wl,--export=emscripten_longjmp" (tried this too)
  4. Also tried using it both at compile time and link time so added wasm excpetions here too

add_compile_options(-Wall -pedantic -fPIC -fwasm-exceptions)

@anutosh491
Copy link
Author

When I try to maybe ignore the symbol (using sERROR_ON_UNDEFINED_SYMBOLS=0) I see this

make: make -j8
[ 50%] Linking CXX executable Compiler.js
em++: warning: EXPORTED_FUNCTIONS is not valid with LINKABLE set (normally due to SIDE_MODULE=1/MAIN_MODULE=1) since all functions are exported this mode.  To export only a subset use SIDE_MODULE=2/MAIN_MODULE=2 [-Wunused-command-line-argument]
warning: undefined symbol: emscripten_longjmp (referenced by root reference (e.g. compiled C/C++ code))
em++: warning: warnings in JS library compilation [-Wjs-compiler]
Traceback (most recent call last):
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/em++.py", line 15, in <module>
    sys.exit(emcc.main(sys.argv))
             ~~~~~~~~~^^^^^^^^^^
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/emcc.py", line 1641, in main
    ret = run(args)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/emcc.py", line 681, in run
    return link.run(linker_inputs, options, state, newargs)
           ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/tools/link.py", line 3178, in run
    phase_post_link(options, state, wasm_target, wasm_target, target, js_syms, base_metadata, linker_inputs)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/tools/link.py", line 1914, in phase_post_link
    metadata = phase_emscript(in_wasm, wasm_target, js_syms, base_metadata)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/lib/python3.13/contextlib.py", line 85, in inner
    return func(*args, **kwds)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/tools/link.py", line 1944, in phase_emscript
    metadata = emscripten.emscript(in_wasm, wasm_target, final_js, js_syms, base_metadata=base_metadata)
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/tools/emscripten.py", line 468, in emscript
    module = create_module(receiving, metadata, global_exports, forwarded_json['librarySymbols'])
  File "/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/tools/emscripten.py", line 1002, in create_module
    assert not metadata.invoke_funcs, "invoke_ functions exported but exceptions and longjmp are both disabled"
           ^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: invoke_ functions exported but exceptions and longjmp are both disabled

@anutosh491
Copy link
Author

Maybe someone could educate me on what this symbol is ? Where is it excpected to come out of ?
And maybe if I am not linking something correctly.

When i build with EMCC_DEBUG=1 .... I see this happening during the link step.

So hopefully I am not missing any library that we need to link against !!!

-o
Compiler.wasm
-L/lib
--export=__clang_Interpreter_SetValueNoAlloc
--export=emscripten_longjmp
CMakeFiles/Compiler.dir/CompilerModule.cpp.o
-lembind-rtti
/Users/anutosh491/work/llvm-project/build2/lib/libclangInterpreter.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangFrontendTool.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangCodeGen.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCoverage.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMFrontendDriver.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangExtractAPI.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangIndex.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangFormat.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangToolingInclusions.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangToolingCore.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangInstallAPI.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMTextAPIBinaryReader.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangRewriteFrontend.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangFrontend.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangDriver.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangRewrite.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangParse.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangSerialization.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangSema.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangAnalysis.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangASTMatchers.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMFrontendHLSL.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangAPINotes.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangEdit.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangAST.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangLex.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangBasic.a
/Users/anutosh491/work/llvm-project/build2/lib/libclangSupport.a
/Users/anutosh491/work/llvm-project/build2/lib/liblldWasm.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMLTO.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMExtensions.a
/Users/anutosh491/work/llvm-project/build2/lib/liblldCommon.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMOrcDebugging.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMOrcJIT.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMPasses.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCoroutines.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMHipStdPar.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMipo.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMFrontendOpenMP.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMFrontendOffloading.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMObjectYAML.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMFrontendAtomic.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMLinker.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMIRPrinter.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMInstrumentation.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMVectorize.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMSandboxIR.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCFGuard.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWindowsDriver.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMExecutionEngine.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMRuntimeDyld.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMJITLink.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMOption.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMOrcTargetProcess.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMOrcShared.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyCodeGen.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMAsmPrinter.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMSelectionDAG.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyAsmParser.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyDisassembler.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMMCDisassembler.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyUtils.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyDesc.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyInfo.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCodeGen.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMTarget.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCodeGenTypes.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMObjCARCOpts.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMScalarOpts.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMAggressiveInstCombine.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMInstCombine.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMTransformUtils.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCGData.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMBitWriter.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMAnalysis.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMProfileData.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMSymbolize.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDebugInfoDWARF.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDebugInfoPDB.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDebugInfoCodeView.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDebugInfoMSF.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDebugInfoBTF.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMObject.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMIRReader.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMBitReader.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMAsmParser.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMCore.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMRemarks.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMBitstreamReader.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMMCParser.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMMC.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMTextAPI.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMBinaryFormat.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMTargetParser.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMSupport.a
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMDemangle.a
-L/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/pic
/Users/anutosh491/micromamba/envs/xeus-cpp-wasm-build/opt/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/pic/libSDL2.a
-lGL-getprocaddr
-lal
-lhtml5
-lbulkmemory
-lstubs-debug
-lnoexit
-lc-debug
-ldlmalloc
-lcompiler_rt-wasm-sjlj
-lc++-except
-lc++abi-debug-except
-lunwind-except
-lsockets
-mllvm
-combiner-global-alias-analysis=false
-mllvm
-wasm-enable-sjlj
-mllvm
-disable-lsr
-mllvm
-wasm-enable-eh
-mllvm
-exception-model=wasm
--export-if-defined=calloc
--export-if-defined=strerror
--export-if-defined=_emscripten_stack_alloc
--export-if-defined=_emscripten_stack_restore
--export-if-defined=emscripten_stack_get_current
--export-if-defined=malloc
--export-if-defined=_emscripten_tempret_get
--export-if-defined=_emscripten_tempret_set
--export-if-defined=htons
--export-if-defined=ntohs
--export-if-defined=htonl
--export-if-defined=_emscripten_timeout
--export-if-defined=__cxa_throw
--export-if-defined=emscripten_stack_get_base
--export-if-defined=emscripten_stack_get_end
--export-if-defined=free
--export-if-defined=__get_exception_message
--export-if-defined=__thrown_object_from_unwind_exception
--export-if-defined=__cxa_increment_exception_refcount
--export-if-defined=__cxa_decrement_exception_refcount
--export-if-defined=fileno
--export-if-defined=emscripten_builtin_memalign
--export-if-defined=__dl_seterr
--export-if-defined=memcmp
--export-if-defined=memcpy
--export-if-defined=__errno_location
--export-if-defined=__cxa_demangle
--export-if-defined=__getTypeName
--export-if-defined=_emval_coro_resume
--export-if-defined=__cxa_rethrow
/var/folders/m1/cdn74f917994jd99d_2cpf440000gn/T/emscripten_temp/tmpdp1kv6zglibemscripten_js_symbols.so
--import-undefined
--import-memory
--strip-debug
--export-if-defined=malloc
--export-if-defined=free
--export-if-defined=_ZTIN10emscripten3valE
--export-if-defined=emscripten_longjmp
--export-if-defined=emscripten_stack_get_end
--export-if-defined=emscripten_stack_get_free
--export-if-defined=emscripten_stack_get_base
--export-if-defined=emscripten_stack_get_current
--export-if-defined=emscripten_stack_set_limits
--export-if-defined=_emscripten_stack_alloc
--export-if-defined=__getTypeName
--export-if-defined=__trap
--export-if-defined=__cpp_exception
--export-if-defined=__wasm_call_ctors
--export-if-defined=calloc
--export-if-defined=strerror
--export-if-defined=_emscripten_stack_restore
--export-if-defined=malloc
--export-if-defined=_emscripten_tempret_get
--export-if-defined=_emscripten_tempret_set
--export-if-defined=htons
--export-if-defined=ntohs
--export-if-defined=htonl
--export-if-defined=_emscripten_timeout
--export-if-defined=__cxa_throw
--export-if-defined=free
--export-if-defined=__get_exception_message
--export-if-defined=__thrown_object_from_unwind_exception
--export-if-defined=__cxa_increment_exception_refcount
--export-if-defined=__cxa_decrement_exception_refcount
--export-if-defined=fileno
--export-if-defined=emscripten_builtin_memalign
--export-if-defined=__dl_seterr
--export-if-defined=memcmp
--export-if-defined=memcpy
--export-if-defined=__errno_location
--export-if-defined=__cxa_demangle
--export-if-defined=_emval_coro_resume
--export-if-defined=__cxa_rethrow
--export-if-defined=__start_em_asm
--export-if-defined=__stop_em_asm
--export-if-defined=__start_em_lib_deps
--export-if-defined=__stop_em_lib_deps
--export-if-defined=__start_em_js
--export-if-defined=__stop_em_js
--export-if-defined=main
--export-if-defined=__main_argc_argv
--export-if-defined=__wasm_apply_data_relocs
--export-if-defined=fflush
--experimental-pic
--unresolved-symbols=import-dynamic
-pie
--no-export-dynamic
-z
stack-size=33554432
--max-memory=2147483648
--initial-memory=134217728
--no-entry

@hoodmane
Copy link
Collaborator

hoodmane commented Feb 24, 2025

I think the emscripten_longjmp symbol you are missing is for the longjmp based on JavaScript exceptions not wasm exceptions. Since you want to use wasm exceptions it shouldn't exist. The fact that it is appearing in one of your object files means it was compiled incompatibly.

You need to pass -sSUPPORT_LONGJMP=wasm as both a cflag and a ldflag. If you are doing that it's possible that the problem is a library you are linking.

@hoodmane
Copy link
Collaborator

Opened an issue requesting a better error message here:
#23732

@anutosh491
Copy link
Author

Hmmm, unfortunately it didn't help :\

I just updated the cmake file to use

add_compile_options(
    -Wall
    -pedantic
    -fPIC
+   -fwasm-exceptions        # Ensure WebAssembly exception handling
+   -sSUPPORT_LONGJMP=wasm   # Compile-time longjmp support
)

And yeah for the linking I was already doing

target_link_options(Compiler PUBLIC
    -O1
    -fwasm-exceptions
    #-fexceptions
    -sSUPPORT_LONGJMP=wasm
   ......

But yeah I think you're correct. I wasn't sure if emscripten_longjmp is something that should play a role if we move to wasm-exceptions (or like if it should even be exported ?)

@hoodmane
Copy link
Collaborator

There should be no symbol called emscripten_longjmp when building with wasm exceptions. It's likely at this point that the problem comes from a library you are linking.

@hoodmane
Copy link
Collaborator

Can you do:

rg -uuu emscripten_longjmp /Users/anutosh491/work/llvm-project/build2/lib/

ripgrep should come back with no hits if it's been built correctly.

@anutosh491
Copy link
Author

anutosh491 commented Feb 24, 2025

Ahhh I see, thanks a lot for this (I need to educate myself with how ripgrep works) but yeah I see

anutosh491@Anutoshs-MacBook-Air llvm-project % rg -uuu emscripten_longjmp /Users/anutosh491/work/llvm-project/build2/lib/
/Users/anutosh491/work/llvm-project/build2/lib/libLLVMSupport.a: binary file matches (found "\0" byte around offset 68)

/Users/anutosh491/work/llvm-project/build2/lib/libLLVMWebAssemblyCodeGen.a: binary file matches (found "\0" byte around offset 68)

/Users/anutosh491/work/llvm-project/build2/lib/Target/WebAssembly/CMakeFiles/LLVMWebAssemblyCodeGen.dir/WebAssemblyLowerEmscriptenEHSjLj.cpp.o: binary file matches (found "\0" byte around offset 0)

/Users/anutosh491/work/llvm-project/build2/lib/Support/CMakeFiles/LLVMSupport.dir/CrashRecoveryContext.cpp.o: binary file matches (found "\0" byte around offset 0)

Which I think means that I need to build llvm with -fwasm-exceptions too which I have missed out on somewhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants