Skip to content

Commit b5d6443

Browse files
authored
[Wasm64] Fix pointer types used embind's craftInvokerFunction (#17311)
There are still some remaining failures but this fixes a whole class of failures with wasm64 and embind.
1 parent 7aa4f64 commit b5d6443

File tree

5 files changed

+46
-14
lines changed

5 files changed

+46
-14
lines changed

embuilder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
'libdlmalloc-noerrno',
4444
'libdlmalloc-tracing',
4545
'libdlmalloc-debug',
46+
'libembind',
4647
'libembind-rtti',
4748
'libemmalloc',
4849
'libemmalloc-debug',

src/embind/embind.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1165,7 +1165,7 @@ var LibraryEmbind = {
11651165
},
11661166

11671167
$embind__requireFunction__deps: ['$readLatin1String', '$throwBindingError'
1168-
#if DYNCALLS || !WASM_BIGINT
1168+
#if DYNCALLS || !WASM_BIGINT || MEMORY64
11691169
, '$getDynCaller'
11701170
#endif
11711171
],
@@ -1180,6 +1180,10 @@ var LibraryEmbind = {
11801180
if (signature.includes('j')) {
11811181
return getDynCaller(signature, rawFunction);
11821182
}
1183+
#elif MEMORY64
1184+
if (signature.includes('p')) {
1185+
return getDynCaller(signature, rawFunction);
1186+
}
11831187
#endif
11841188
return getWasmTableEntry(rawFunction);
11851189
#endif

src/library.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,19 +3201,20 @@ mergeInto(LibraryManager.library, {
32013201
#if MINIMAL_RUNTIME
32023202
var f = dynCalls[sig];
32033203
#else
3204-
var f = Module["dynCall_" + sig];
3204+
var f = Module['dynCall_' + sig];
32053205
#endif
32063206
return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr);
32073207
},
32083208
$dynCall__deps: ['$dynCallLegacy', '$getWasmTableEntry'],
3209+
#endif
32093210

32103211
// Used in library code to get JS function from wasm function pointer.
32113212
// All callers should use direct table access where possible and only fall
32123213
// back to this function if needed.
32133214
$getDynCaller__deps: ['$dynCall'],
32143215
$getDynCaller: function(sig, ptr) {
32153216
#if ASSERTIONS && !DYNCALLS
3216-
assert(sig.includes('j'), 'getDynCaller should only be called with i64 sigs')
3217+
assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs')
32173218
#endif
32183219
var argCache = [];
32193220
return function() {
@@ -3222,7 +3223,6 @@ mergeInto(LibraryManager.library, {
32223223
return dynCall(sig, ptr, argCache);
32233224
};
32243225
},
3225-
#endif
32263226

32273227
$dynCall__docs: '/** @param {Object=} args */',
32283228
$dynCall: function(sig, ptr, args) {
@@ -3239,6 +3239,21 @@ mergeInto(LibraryManager.library, {
32393239
#endif
32403240
#if ASSERTIONS
32413241
assert(getWasmTableEntry(ptr), 'missing table entry in dynCall: ' + ptr);
3242+
#endif
3243+
#if MEMORY64
3244+
// With MEMORY64 we have an additional step to covert `p` arguments to
3245+
// bigint. This is the runtime equivalent of the wrappers we create for wasm
3246+
// exports in `emscripten.py:create_wasm64_wrappers`.
3247+
if (sig.includes('p')) {
3248+
var new_args = [];
3249+
args.forEach((arg, index) => {
3250+
if (sig[index + 1] == 'p') {
3251+
arg = BigInt(arg);
3252+
}
3253+
new_args.push(arg);
3254+
});
3255+
args = new_args;
3256+
}
32423257
#endif
32433258
return getWasmTableEntry(ptr).apply(null, args)
32443259
#endif

system/include/emscripten/bind.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,17 @@ struct SignatureCode<double> {
432432
}
433433
};
434434

435+
#ifdef __wasm64__
436+
// With wasm32 we can fallback to 'i' for pointer types but we need special
437+
// handling with wasm64.
438+
template<>
439+
struct SignatureCode<void*> {
440+
static constexpr char get() {
441+
return 'p';
442+
}
443+
};
444+
#endif
445+
435446
template<typename... Args>
436447
const char* getGenericSignature() {
437448
static constexpr char signature[] = { SignatureCode<Args>::get()..., 0 };
@@ -442,6 +453,12 @@ template<typename T> struct SignatureTranslator { using type = int; };
442453
template<> struct SignatureTranslator<void> { using type = void; };
443454
template<> struct SignatureTranslator<float> { using type = float; };
444455
template<> struct SignatureTranslator<double> { using type = double; };
456+
#ifdef __wasm64__
457+
template<typename PtrType>
458+
struct SignatureTranslator<PtrType*> { using type = void*; };
459+
template<typename ReturnType, typename... Args>
460+
struct SignatureTranslator<ReturnType (*)(Args...)> { using type = void*; };
461+
#endif
445462

446463
template<typename... Args>
447464
EMSCRIPTEN_ALWAYS_INLINE const char* getSpecificSignature() {

tests/test_core.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7334,12 +7334,11 @@ def test_embind(self):
73347334
''')
73357335
self.do_runf('test_embind.cpp', 'abs(-10): 10\nabs(-11): 11', emcc_args=args)
73367336

7337-
@no_wasm64('embind does not yet support MEMORY64')
73387337
def test_embind_2(self):
73397338
self.emcc_args += ['-lembind', '--post-js', 'post.js']
73407339
create_file('post.js', '''
73417340
function printLerp() {
7342-
out('lerp ' + Module.lerp(100, 200, 66) + '.');
7341+
out('lerp ' + Module.lerp(100, 200, 66) + '.');
73437342
}
73447343
''')
73457344
create_file('test_embind_2.cpp', r'''
@@ -7348,14 +7347,14 @@ def test_embind_2(self):
73487347
#include <emscripten/bind.h>
73497348
using namespace emscripten;
73507349
int lerp(int a, int b, int t) {
7351-
return (100 - t) * a + t * b;
7350+
return (100 - t) * a + t * b;
73527351
}
73537352
EMSCRIPTEN_BINDINGS(my_module) {
7354-
function("lerp", &lerp);
7353+
function("lerp", &lerp);
73557354
}
73567355
int main(int argc, char **argv) {
7357-
EM_ASM(printLerp());
7358-
return 0;
7356+
EM_ASM(printLerp());
7357+
return 0;
73597358
}
73607359
''')
73617360
self.do_runf('test_embind_2.cpp', 'lerp 166')
@@ -7388,7 +7387,6 @@ def test_embind_3(self):
73887387
''')
73897388
self.do_runf('test_embind_3.cpp', 'UnboundTypeError: Cannot call compute due to unbound types: Pi')
73907389

7391-
@no_wasm64('embind does not yet support MEMORY64')
73927390
def test_embind_4(self):
73937391
self.emcc_args += ['-lembind', '--post-js', 'post.js']
73947392
create_file('post.js', '''
@@ -7440,7 +7438,6 @@ def test_embind_negative_constants(self):
74407438
self.do_run_in_out_file_test('embind/test_negative_constants.cpp')
74417439

74427440
@also_with_wasm_bigint
7443-
@no_wasm64('embind does not yet support MEMORY64')
74447441
def test_embind_unsigned(self):
74457442
self.emcc_args += ['-lembind']
74467443
self.do_run_in_out_file_test('embind/test_unsigned.cpp')
@@ -7474,7 +7471,6 @@ def test_embind_i64_binding(self):
74747471
self.node_args += ['--experimental-wasm-bigint']
74757472
self.do_run_in_out_file_test('embind/test_i64_binding.cpp', assert_identical=True)
74767473

7477-
@no_wasm64('embind does not yet support MEMORY64')
74787474
def test_embind_no_rtti(self):
74797475
create_file('main.cpp', r'''
74807476
#include <emscripten.h>
@@ -7508,7 +7504,6 @@ def test_embind_polymorphic_class_no_rtti(self):
75087504
self.emcc_args += ['-lembind', '-fno-rtti', '-DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0']
75097505
self.do_core_test('test_embind_polymorphic_class_no_rtti.cpp')
75107506

7511-
@no_wasm64('embind does not yet support MEMORY64')
75127507
def test_embind_no_rtti_followed_by_rtti(self):
75137508
src = r'''
75147509
#include <emscripten.h>

0 commit comments

Comments
 (0)