Skip to content

Function Pointers and dynamic linking (function signature mismatch) #9901

@gl84

Description

@gl84

I'm trying to use boost regex expressions with a custom build icu (and latest tot upstream emscripten). I always get an error

exception thrown: RuntimeError: function signature mismatch,RuntimeError: function signature mismatch
    at legalstub$dynCall_jiii (wasm-function[12507]:11)
    at Object.Module.dynCall_jiii (/Test.js:19640:40)
    at invoke_jiii (/Test.js:27738:34)
    at legalfunc$invoke_jiii (wasm-function[12528]:9)
    at boost::re_detail_106900::basic_regex_creator<int, boost::icu_regex_traits>::basic_regex_creator(boost::re_detail_106900::regex_data<int, boost::icu_regex_traits>*) (wasm-function[7314]:136)
....

In trying to reproduce above problem in a simpler setting I found that when using function pointers to functions in side modules that return int64_t values I get the same error message
RuntimeError: function signature mismatch. The failure seems to be similar (but still different) to #9850 which was fixed in PR #9855.

I created a small combined test case with 4 files (without the boost/icu clutter) that reproduce the problem with the function pointers:
side.hpp:

#ifdef __EMSCRIPTEN__
    #include <emscripten.h>
#else
    #define EMSCRIPTEN_KEEPALIVE
#endif
#include <cstdint>

EMSCRIPTEN_KEEPALIVE int32_t function_ret_32(int32_t i, int32_t j, int32_t k);
EMSCRIPTEN_KEEPALIVE int64_t function_ret_64(int32_t i, int32_t j, int32_t k);

side.cpp:

#include "side.hpp"
int32_t function_ret_32(int32_t i, int32_t j, int32_t k) {
    return 32;
}
int64_t function_ret_64(int32_t i, int32_t j, int32_t k) {
    return 64;
}

main.cpp:

#include <cstdio>
#include <cinttypes>
#include "side.hpp"

typedef int32_t (*fp_type_32)(int32_t, int32_t, int32_t);
typedef int64_t (*fp_type_64)(int32_t, int32_t, int32_t);

int32_t internal_function_ret_32(int32_t i, int32_t j, int32_t k) {
    return 32;
}
int64_t internal_function_ret_64(int32_t i, int32_t j, int32_t k) {
    return 64;
}

int main() {
    fp_type_32 fp32_internal = &internal_function_ret_32;
    fp_type_32 fp32_external = &function_ret_32;
    fp_type_64 fp64_external = &function_ret_64;
    fp_type_64 fp64_internal = &internal_function_ret_64;
    int32_t ires32 = fp32_internal(0,0,0);
    printf("res32 - internal %d\n",ires32);
    int32_t eres32 = fp32_external(0,0,0);
    printf("res32 - external %d\n",eres32);

    int64_t ires64 = fp64_internal(0,0,0);
    printf("res64 - internal %" PRId64 "\n",ires64);
    int64_t eres64 = fp64_external(0,0,0);
    printf("res64 - external %" PRId64 "\n",eres64);
    return 0;
}

preload.js:

if (typeof(Module) === "undefined") Module = {};
Module.dynamicLibraries = ['side.wasm'];

Compiling the side module with
em++ -g --profiling -Wall -fPIC -s WASM=1 side.cpp -s SIDE_MODULE=2 -o side.wasm

Compiling the main module with
em++ -o main.js -g --profiling -Wall main.cpp -s MAIN_MODULE=1 -s EXPORTED_FUNCTIONS=['_main'] --pre-js preload.js

Running the program leads to the RuntimeError when fp64_external is called. Without the fix #9855 the line that should produce output res64 - internal 64 fails.

btw: Thanks for the great work! It is a lot of fun working with emscripten.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions