diff options
-rwxr-xr-x | auto_update_tests.py | 1 | ||||
-rwxr-xr-x | scripts/test/lld.py | 55 | ||||
-rwxr-xr-x | scripts/test/s2wasm.py | 1 | ||||
-rw-r--r-- | src/tools/s2wasm.cpp | 12 | ||||
-rw-r--r-- | src/tools/wasm-emscripten-finalize.cpp | 10 | ||||
-rw-r--r-- | src/tools/wasm-link-metadata.cpp | 12 | ||||
-rw-r--r-- | src/wasm-emscripten.cpp | 134 | ||||
-rw-r--r-- | src/wasm-emscripten.h | 11 | ||||
-rw-r--r-- | test/dot_s/reserved_func_ptrs.jscall.wast | 281 | ||||
-rw-r--r-- | test/dot_s/reserved_func_ptrs.s | 59 | ||||
-rw-r--r-- | test/dot_s/reserved_func_ptrs.wast | 147 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.cpp | 34 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.jscall.json | 1 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.json | 1 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.o | bin | 0 -> 566 bytes | |||
-rw-r--r-- | test/lld/reserved_func_ptr.wast | 111 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.wast.jscall.out | 294 | ||||
-rw-r--r-- | test/lld/reserved_func_ptr.wast.out | 155 |
18 files changed, 1289 insertions, 30 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py index 050dab1d1..1ec8f23c5 100755 --- a/auto_update_tests.py +++ b/auto_update_tests.py @@ -53,6 +53,7 @@ extension_arg_map = { '.wast': [], '.clamp.wast': ['--trap-mode=clamp'], '.js.wast': ['--trap-mode=js'], + '.jscall.wast': ['--emscripten-reserved-function-pointers=3'], } for dot_s_dir in ['dot_s', 'llvm_autogenerated']: for s in sorted(os.listdir(os.path.join('test', dot_s_dir))): diff --git a/scripts/test/lld.py b/scripts/test/lld.py index 793031ca6..85159ba3a 100755 --- a/scripts/test/lld.py +++ b/scripts/test/lld.py @@ -25,36 +25,53 @@ from shared import ( def test_wasm_link_metadata(): print '\n[ checking wasm-link-metadata testcases... ]\n' + extension_arg_map = { + '.json': [], + '.jscall.json': ['--emscripten-reserved-function-pointers=3'], + } + for obj_path in files_with_pattern(options.binaryen_test, 'lld', '*.o'): print '..', obj_path - expected_file = obj_path.replace('.o', '.json') + for ext, ext_args in extension_arg_map.items(): + expected_file = obj_path.replace('.o', ext) + if ext != '.json' and not os.path.exists(expected_file): + continue - cmd = WASM_LINK_METADATA + [obj_path] - actual = run_command(cmd) + cmd = WASM_LINK_METADATA + [obj_path] + ext_args + actual = run_command(cmd) - if not os.path.exists(expected_file): - print actual - fail_with_error('output ' + expected_file + ' does not exist') - expected = open(expected_file, 'rb').read() - if actual != expected: - fail(actual, expected) + if not os.path.exists(expected_file): + print actual + fail_with_error('output ' + expected_file + ' does not exist') + expected = open(expected_file, 'rb').read() + if actual != expected: + fail(actual, expected) def test_wasm_emscripten_finalize(): print '\n[ checking wasm-emscripten-finalize testcases... ]\n' + extension_arg_map = { + '.out': [], + '.jscall.out': ['--emscripten-reserved-function-pointers=3'], + } + for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'): print '..', wast_path - expected_file = wast_path + '.out' - cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] - actual = run_command(cmd) - - if not os.path.exists(expected_file): - print actual - fail_with_error('output ' + expected_file + ' does not exist') - expected = open(expected_file, 'rb').read() - if actual != expected: - fail(actual, expected) + for ext, ext_args in extension_arg_map.items(): + expected_file = wast_path + ext + if ext != '.out' and not os.path.exists(expected_file): + continue + + cmd = WASM_EMSCRIPTEN_FINALIZE + [wast_path, '-S'] + ext_args + actual = run_command(cmd) + + if not os.path.exists(expected_file): + print actual + fail_with_error('output ' + expected_file + ' does not exist') + expected = open(expected_file, 'rb').read() + if actual != expected: + fail(actual, expected) if __name__ == '__main__': diff --git a/scripts/test/s2wasm.py b/scripts/test/s2wasm.py index 405ed5fdf..a3345f87b 100755 --- a/scripts/test/s2wasm.py +++ b/scripts/test/s2wasm.py @@ -36,6 +36,7 @@ def test_s2wasm(): '.wast': [], '.clamp.wast': ['--trap-mode=clamp'], '.js.wast': ['--trap-mode=js'], + '.jscall.wast': ['--emscripten-reserved-function-pointers=3'], } for dot_s_dir in ['dot_s', 'llvm_autogenerated']: dot_s_path = os.path.join(options.binaryen_test, dot_s_dir) diff --git a/src/tools/s2wasm.cpp b/src/tools/s2wasm.cpp index d4e7731c5..a2c4e4a38 100644 --- a/src/tools/s2wasm.cpp +++ b/src/tools/s2wasm.cpp @@ -41,6 +41,7 @@ int main(int argc, const char *argv[]) { std::string startFunction; std::vector<std::string> archiveLibraries; TrapMode trapMode = TrapMode::Allow; + unsigned numReservedFunctionPointers = 0; Options options("s2wasm", "Link .s file into .wast"); options.extra["validate"] = "wasm"; options @@ -121,6 +122,14 @@ int main(int argc, const char *argv[]) { } o->extra["validate"] = argument; }) + .add("--emscripten-reserved-function-pointers", "", + "Number of reserved function pointers for emscripten addFunction " + "support", + Options::Arguments::One, + [&numReservedFunctionPointers](Options *o, + const std::string &argument) { + numReservedFunctionPointers = std::stoi(argument); + }) .add_positional("INFILE", Options::Arguments::One, [](Options *o, const std::string& argument) { o->extra["infile"] = argument; @@ -189,7 +198,8 @@ int main(int argc, const char *argv[]) { allowMemoryGrowth, linker.getStackPointerAddress(), linker.getStaticBump(), - linker.getOutput().getInitializerFunctions()); + linker.getOutput().getInitializerFunctions(), + numReservedFunctionPointers); } if (options.extra["validate"] != "none") { diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index 223fa3082..28f5a7c06 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -39,6 +39,7 @@ int main(int argc, const char *argv[]) { std::string infile; std::string outfile; bool emitBinary = true; + unsigned numReservedFunctionPointers = 0; std::vector<Name> forcedExports; Options options("wasm-emscripten-finalize", "Performs Emscripten-specific transforms on .wasm files"); @@ -54,6 +55,14 @@ int main(int argc, const char *argv[]) { [&emitBinary](Options*, const std::string& ) { emitBinary = false; }) + .add("--emscripten-reserved-function-pointers", "", + "Number of reserved function pointers for emscripten addFunction " + "support", + Options::Arguments::One, + [&numReservedFunctionPointers](Options *, + const std::string &argument) { + numReservedFunctionPointers = std::stoi(argument); + }) .add_positional("INFILE", Options::Arguments::One, [&infile](Options *o, const std::string& argument) { infile = argument; @@ -80,6 +89,7 @@ int main(int argc, const char *argv[]) { generator.generateRuntimeFunctions(); generator.generateMemoryGrowthFunction(); generator.generateDynCallThunks(); + generator.generateJSCallThunks(numReservedFunctionPointers); generator.fixEmAsmConsts(); if (options.debug) { diff --git a/src/tools/wasm-link-metadata.cpp b/src/tools/wasm-link-metadata.cpp index 96e06f95b..3af00fbbf 100644 --- a/src/tools/wasm-link-metadata.cpp +++ b/src/tools/wasm-link-metadata.cpp @@ -67,6 +67,7 @@ void parseLinkingSection(std::vector<char> const& data, uint32_t &dataSize) { int main(int argc, const char *argv[]) { std::string infile; std::string outfile; + unsigned numReservedFunctionPointers = 0; Options options("wasm-link-metadata", "Reads wasm .o file and emits .json metadata"); options @@ -76,6 +77,14 @@ int main(int argc, const char *argv[]) { outfile = argument; Colors::disable(); }) + .add("--emscripten-reserved-function-pointers", "", + "Number of reserved function pointers for emscripten addFunction " + "support", + Options::Arguments::One, + [&numReservedFunctionPointers](Options *o, + const std::string &argument) { + numReservedFunctionPointers = std::stoi(argument); + }) .add_positional("INFILE", Options::Arguments::One, [&infile](Options *o, const std::string& argument) { infile = argument; @@ -110,7 +119,8 @@ int main(int argc, const char *argv[]) { initializerFunctions.push_back("__wasm_call_ctors"); EmscriptenGlueGenerator generator(wasm); - std::string metadata = generator.generateEmscriptenMetadata(dataSize, initializerFunctions); + std::string metadata = generator.generateEmscriptenMetadata( + dataSize, initializerFunctions, numReservedFunctionPointers); Output output(outfile, Flags::Text, Flags::Release); output << metadata; diff --git a/src/wasm-emscripten.cpp b/src/wasm-emscripten.cpp index 60bf5cce3..821f3aa9d 100644 --- a/src/wasm-emscripten.cpp +++ b/src/wasm-emscripten.cpp @@ -196,6 +196,106 @@ void EmscriptenGlueGenerator::generateDynCallThunks() { } } +struct JSCallWalker : public PostWalker<JSCallWalker> { + Module &wasm; + JSCallWalker(Module &_wasm) : wasm(_wasm) { + if (wasm.table.segments.size() == 0) { + auto emptySegment = + wasm.allocator.alloc<Const>()->set(Literal(uint32_t(0))); + wasm.table.segments.emplace_back(emptySegment); + } + const auto& tableSegmentData = wasm.table.segments[0].data; + + // Check if jsCalls have already been created + for (Index i = 0; i < tableSegmentData.size(); ++i) { + if (tableSegmentData[i].startsWith("jsCall_")) { + jsCallStartIndex = i; + return; + } + } + jsCallStartIndex = + wasm.table.segments[0].offset->cast<Const>()->value.getInteger() + + tableSegmentData.size(); + } + + // Gather all function signatures used in call_indirect, because any of them + // can be used to call function pointers created by emscripten's addFunction. + void visitCallIndirect(CallIndirect *curr) { + // dynCall thunks are generated in binaryen and call_indirect instructions + // within them cannot be used to call function pointers returned by + // emscripten's addFunction. + if (!getFunction()->name.startsWith("dynCall_")) { + indirectlyCallableSigs.insert( + getSig(wasm.getFunctionType(curr->fullType))); + } + } + + bool createJSCallThunks; + Index jsCallStartIndex; + // Function type signatures used in call_indirect instructions + std::set<std::string> indirectlyCallableSigs; +}; + +JSCallWalker getJSCallWalker(Module& wasm) { + JSCallWalker walker(wasm); + walker.walkModule(&wasm); + return walker; +} + +void EmscriptenGlueGenerator::generateJSCallThunks( + unsigned numReservedFunctionPointers) { + if (numReservedFunctionPointers == 0) + return; + + JSCallWalker walker = getJSCallWalker(wasm); + auto& tableSegmentData = wasm.table.segments[0].data; + for (std::string sig : walker.indirectlyCallableSigs) { + // Add imports for jsCall_sig (e.g. jsCall_vi). + // Imported jsCall_sig functions have their first parameter as an index to + // the function table, so we should prepend an 'i' to parameters' signature + // (e.g. If the signature of the callee is 'vi', the imported jsCall_vi + // function would have signature 'vii'.) + std::string importSig = std::string(1, sig[0]) + 'i' + sig.substr(1); + FunctionType *importType = ensureFunctionType(importSig, &wasm); + auto import = new Import; + import->name = import->base = "jsCall_" + sig; + import->module = ENV; + import->functionType = importType->name; + import->kind = ExternalKind::Function; + wasm.addImport(import); + FunctionType *funcType = ensureFunctionType(sig, &wasm); + + // Create jsCall_sig_index thunks (e.g. jsCall_vi_0, jsCall_vi_1, ...) + // e.g. If # of reserved function pointers (given by a command line + // argument) is 3 and there are two possible signature 'vi' and 'ii', the + // genereated thunks will be jsCall_vi_0, jsCall_vi_1, jsCall_vi_2, + // jsCall_ii_0, jsCall_ii_1, and jsCall_ii_2. + for (unsigned fp = 0; fp < numReservedFunctionPointers; ++fp) { + std::vector<NameType> params; + int p = 0; + for (const auto& ty : funcType->params) { + params.emplace_back(std::to_string(p++), ty); + } + Function* f = builder.makeFunction( + std::string("jsCall_") + sig + "_" + std::to_string(fp), + std::move(params), funcType->result, {}); + std::vector<Expression*> args; + args.push_back(builder.makeConst(Literal(fp))); + for (unsigned i = 0; i < funcType->params.size(); ++i) { + args.push_back(builder.makeGetLocal(i, funcType->params[i])); + } + Expression* call = + builder.makeCallImport(import->name, args, funcType->result); + f->body = call; + wasm.addFunction(f); + tableSegmentData.push_back(f->name); + } + } + wasm.table.initial = wasm.table.max = + wasm.table.segments[0].offset->cast<Const>()->value.getInteger() + + tableSegmentData.size(); +} + struct AsmConstWalker : public PostWalker<AsmConstWalker> { Module& wasm; std::vector<Address> segmentOffsets; // segment index => address offset @@ -362,22 +462,22 @@ void printSet(std::ostream& o, C& c) { } std::string EmscriptenGlueGenerator::generateEmscriptenMetadata( - Address staticBump, - std::vector<Name> const& initializerFunctions) { + Address staticBump, std::vector<Name> const& initializerFunctions, + unsigned numReservedFunctionPointers) { std::stringstream meta; meta << "{ "; - AsmConstWalker walker = fixEmAsmConstsAndReturnWalker(wasm); + AsmConstWalker emAsmWalker = fixEmAsmConstsAndReturnWalker(wasm); // print meta << "\"asmConsts\": {"; bool first = true; - for (auto& pair : walker.sigsForCode) { + for (auto& pair : emAsmWalker.sigsForCode) { auto& code = pair.first; auto& sigs = pair.second; if (first) first = false; else meta << ","; - meta << '"' << walker.ids[code] << "\": [\"" << code << "\", "; + meta << '"' << emAsmWalker.ids[code] << "\": [\"" << code << "\", "; printSet(meta, sigs); meta << "]"; } @@ -394,6 +494,20 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata( } meta << "]"; + if (numReservedFunctionPointers) { + JSCallWalker jsCallWalker = getJSCallWalker(wasm); + meta << ", "; + meta << "\"jsCallStartIndex\": " << jsCallWalker.jsCallStartIndex << ", "; + meta << "\"jsCallFuncType\": ["; + bool first = true; + for (std::string sig : jsCallWalker.indirectlyCallableSigs) { + if (!first) meta << ", "; + first = false; + meta << "\"" << sig << "\""; + } + meta << "]"; + } + meta << " }\n"; return meta.str(); @@ -404,7 +518,8 @@ std::string emscriptenGlue( bool allowMemoryGrowth, Address stackPointer, Address staticBump, - std::vector<Name> const& initializerFunctions) { + std::vector<Name> const& initializerFunctions, + unsigned numReservedFunctionPointers) { EmscriptenGlueGenerator generator(wasm, stackPointer); generator.generateRuntimeFunctions(); @@ -414,7 +529,12 @@ std::string emscriptenGlue( generator.generateDynCallThunks(); - return generator.generateEmscriptenMetadata(staticBump, initializerFunctions); + if (numReservedFunctionPointers) { + generator.generateJSCallThunks(numReservedFunctionPointers); + } + + return generator.generateEmscriptenMetadata(staticBump, initializerFunctions, + numReservedFunctionPointers); } } // namespace wasm diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h index 1878e6531..d2a0a8e3e 100644 --- a/src/wasm-emscripten.h +++ b/src/wasm-emscripten.h @@ -39,8 +39,14 @@ public: // signature in the indirect function table. void generateDynCallThunks(); + // Create thunks to support emscripten's addFunction functionality. Creates (# + // of reserved function pointers) thunks for each indirectly called function + // signature. + void generateJSCallThunks(unsigned numReservedFunctionPointers); + std::string generateEmscriptenMetadata( - Address staticBump, std::vector<Name> const& initializerFunctions); + Address staticBump, std::vector<Name> const& initializerFunctions, + unsigned numReservedFunctionPointers); // Replace placeholder emscripten_asm_const functions with *_signature versions. void fixEmAsmConsts(); @@ -64,7 +70,8 @@ std::string emscriptenGlue( bool allowMemoryGrowth, Address stackPointer, Address staticBump, - std::vector<Name> const& initializerFunctions); + std::vector<Name> const& initializerFunctions, + unsigned numReservedFunctionPointers); } // namespace wasm diff --git a/test/dot_s/reserved_func_ptrs.jscall.wast b/test/dot_s/reserved_func_ptrs.jscall.wast new file mode 100644 index 000000000..fd48f0a90 --- /dev/null +++ b/test/dot_s/reserved_func_ptrs.jscall.wast @@ -0,0 +1,281 @@ +(module + (type $FUNCSIG$v (func)) + (type $FUNCSIG$vi (func (param i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$fffi (func (param f32 f32 i32) (result f32))) + (type $FUNCSIG$ddi (func (param f64 i32) (result f64))) + (type $FUNCSIG$viii (func (param i32 i32 i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$didi (func (param i32 f64 i32) (result f64))) + (type $FUNCSIG$fiffi (func (param i32 f32 f32 i32) (result f32))) + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$vii (func (param i32 i32))) + (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) + (import "env" "atoi" (func $atoi (param i32) (result i32))) + (import "env" "memory" (memory $0 1)) + (import "env" "jsCall_ddi" (func $jsCall_ddi (param i32 f64 i32) (result f64))) + (import "env" "jsCall_fffi" (func $jsCall_fffi (param i32 f32 f32 i32) (result f32))) + (import "env" "jsCall_iii" (func $jsCall_iii (param i32 i32 i32) (result i32))) + (import "env" "jsCall_v" (func $jsCall_v (param i32))) + (import "env" "jsCall_vi" (func $jsCall_vi (param i32 i32))) + (import "env" "jsCall_viii" (func $jsCall_viii (param i32 i32 i32 i32))) + (table 21 21 anyfunc) + (elem (i32.const 0) $__wasm_nullptr $_Z18address_taken_funciii $_Z19address_taken_func2iii $jsCall_ddi_0 $jsCall_ddi_1 $jsCall_ddi_2 $jsCall_fffi_0 $jsCall_fffi_1 $jsCall_fffi_2 $jsCall_iii_0 $jsCall_iii_1 $jsCall_iii_2 $jsCall_v_0 $jsCall_v_1 $jsCall_v_2 $jsCall_vi_0 $jsCall_vi_1 $jsCall_vi_2 $jsCall_viii_0 $jsCall_viii_1 $jsCall_viii_2) + (export "main" (func $main)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "dynCall_viii" (func $dynCall_viii)) + (func $_Z18address_taken_funciii (; 7 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + ) + (func $_Z19address_taken_func2iii (; 8 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + ) + (func $main (; 9 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (set_local $2 + (call $atoi + (i32.load offset=4 + (get_local $1) + ) + ) + ) + (set_local $3 + (call $atoi + (i32.load offset=8 + (get_local $1) + ) + ) + ) + (set_local $4 + (call $atoi + (i32.load offset=12 + (get_local $1) + ) + ) + ) + (set_local $5 + (call $atoi + (i32.load offset=16 + (get_local $1) + ) + ) + ) + (set_local $1 + (call $atoi + (i32.load offset=20 + (get_local $1) + ) + ) + ) + (call_indirect (type $FUNCSIG$v) + (get_local $2) + ) + (call_indirect (type $FUNCSIG$vi) + (i32.const 3) + (get_local $3) + ) + (drop + (call_indirect (type $FUNCSIG$iii) + (i32.const 4) + (i32.const 5) + (get_local $4) + ) + ) + (drop + (call_indirect (type $FUNCSIG$fffi) + (f32.const 3.0999999046325684) + (f32.const 4.199999809265137) + (i32.const 5) + (get_local $5) + ) + ) + (drop + (call_indirect (type $FUNCSIG$ddi) + (f64.const 4.2) + (i32.const 5) + (get_local $1) + ) + ) + (call_indirect (type $FUNCSIG$viii) + (i32.const 1) + (i32.const 2) + (i32.const 3) + (select + (i32.const 1) + (i32.const 2) + (i32.gt_s + (get_local $0) + (i32.const 3) + ) + ) + ) + (i32.const 0) + ) + (func $__wasm_nullptr (; 10 ;) (type $FUNCSIG$v) + (unreachable) + ) + (func $stackSave (; 11 ;) (result i32) + (i32.load offset=4 + (i32.const 0) + ) + ) + (func $stackAlloc (; 12 ;) (param $0 i32) (result i32) + (local $1 i32) + (i32.store offset=4 + (i32.const 0) + (tee_local $1 + (i32.and + (i32.sub + (i32.load offset=4 + (i32.const 0) + ) + (get_local $0) + ) + (i32.const -16) + ) + ) + ) + (get_local $1) + ) + (func $stackRestore (; 13 ;) (param $0 i32) + (i32.store offset=4 + (i32.const 0) + (get_local $0) + ) + ) + (func $dynCall_viii (; 14 ;) (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) + (call_indirect (type $FUNCSIG$viii) + (get_local $0) + (get_local $1) + (get_local $2) + (get_local $fptr) + ) + ) + (func $jsCall_ddi_0 (; 15 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 0) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_ddi_1 (; 16 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 1) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_ddi_2 (; 17 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 2) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_fffi_0 (; 18 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 0) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_fffi_1 (; 19 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 1) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_fffi_2 (; 20 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 2) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_iii_0 (; 21 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 0) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_iii_1 (; 22 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 1) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_iii_2 (; 23 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 2) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_v_0 (; 24 ;) + (call $jsCall_v + (i32.const 0) + ) + ) + (func $jsCall_v_1 (; 25 ;) + (call $jsCall_v + (i32.const 1) + ) + ) + (func $jsCall_v_2 (; 26 ;) + (call $jsCall_v + (i32.const 2) + ) + ) + (func $jsCall_vi_0 (; 27 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 0) + (get_local $0) + ) + ) + (func $jsCall_vi_1 (; 28 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 1) + (get_local $0) + ) + ) + (func $jsCall_vi_2 (; 29 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 2) + (get_local $0) + ) + ) + (func $jsCall_viii_0 (; 30 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 0) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_viii_1 (; 31 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 1) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_viii_2 (; 32 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 2) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) +) +;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [], "jsCallStartIndex": 3, "jsCallFuncType": ["ddi", "fffi", "iii", "v", "vi", "viii"] } diff --git a/test/dot_s/reserved_func_ptrs.s b/test/dot_s/reserved_func_ptrs.s new file mode 100644 index 000000000..2e838c795 --- /dev/null +++ b/test/dot_s/reserved_func_ptrs.s @@ -0,0 +1,59 @@ + .text + .file "reserved_func_ptrs.cpp" + .type _Z18address_taken_funciii,@function +_Z18address_taken_funciii: + .param i32, i32, i32 + .endfunc +.Lfunc_end0: + .size _Z18address_taken_funciii, .Lfunc_end0-_Z18address_taken_funciii + + .type _Z19address_taken_func2iii,@function +_Z19address_taken_func2iii: + .param i32, i32, i32 + .endfunc +.Lfunc_end1: + .size _Z19address_taken_func2iii, .Lfunc_end1-_Z19address_taken_func2iii + + .hidden main + .globl main + .type main,@function +main: + .param i32, i32 + .result i32 + .local i32, i32, i32, i32 + i32.load $push0=, 4($1) + i32.call $2=, atoi@FUNCTION, $pop0 + i32.load $push1=, 8($1) + i32.call $3=, atoi@FUNCTION, $pop1 + i32.load $push2=, 12($1) + i32.call $4=, atoi@FUNCTION, $pop2 + i32.load $push3=, 16($1) + i32.call $5=, atoi@FUNCTION, $pop3 + i32.load $push4=, 20($1) + i32.call $1=, atoi@FUNCTION, $pop4 + call_indirect $2 + i32.const $push5=, 3 + call_indirect $pop5, $3 + i32.const $push7=, 4 + i32.const $push6=, 5 + i32.call_indirect $drop=, $pop7, $pop6, $4 + f32.const $push9=, 0x1.8cccccp1 + f32.const $push8=, 0x1.0cccccp2 + i32.const $push21=, 5 + f32.call_indirect $drop=, $pop9, $pop8, $pop21, $5 + f64.const $push10=, 0x1.0cccccccccccdp2 + i32.const $push20=, 5 + f64.call_indirect $drop=, $pop10, $pop20, $1 + i32.const $push16=, 1 + i32.const $push15=, 2 + i32.const $push19=, 3 + i32.const $push13=, _Z18address_taken_funciii@FUNCTION + i32.const $push12=, _Z19address_taken_func2iii@FUNCTION + i32.const $push18=, 3 + i32.gt_s $push11=, $0, $pop18 + i32.select $push14=, $pop13, $pop12, $pop11 + call_indirect $pop16, $pop15, $pop19, $pop14 + i32.const $push17=, 0 + .endfunc +.Lfunc_end2: + .size main, .Lfunc_end2-main diff --git a/test/dot_s/reserved_func_ptrs.wast b/test/dot_s/reserved_func_ptrs.wast new file mode 100644 index 000000000..08cf95282 --- /dev/null +++ b/test/dot_s/reserved_func_ptrs.wast @@ -0,0 +1,147 @@ +(module + (type $FUNCSIG$v (func)) + (type $FUNCSIG$vi (func (param i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$fffi (func (param f32 f32 i32) (result f32))) + (type $FUNCSIG$ddi (func (param f64 i32) (result f64))) + (type $FUNCSIG$viii (func (param i32 i32 i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) + (import "env" "atoi" (func $atoi (param i32) (result i32))) + (import "env" "memory" (memory $0 1)) + (table 3 3 anyfunc) + (elem (i32.const 0) $__wasm_nullptr $_Z18address_taken_funciii $_Z19address_taken_func2iii) + (export "main" (func $main)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "dynCall_viii" (func $dynCall_viii)) + (func $_Z18address_taken_funciii (; 1 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + ) + (func $_Z19address_taken_func2iii (; 2 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32) + ) + (func $main (; 3 ;) (param $0 i32) (param $1 i32) (result i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (set_local $2 + (call $atoi + (i32.load offset=4 + (get_local $1) + ) + ) + ) + (set_local $3 + (call $atoi + (i32.load offset=8 + (get_local $1) + ) + ) + ) + (set_local $4 + (call $atoi + (i32.load offset=12 + (get_local $1) + ) + ) + ) + (set_local $5 + (call $atoi + (i32.load offset=16 + (get_local $1) + ) + ) + ) + (set_local $1 + (call $atoi + (i32.load offset=20 + (get_local $1) + ) + ) + ) + (call_indirect (type $FUNCSIG$v) + (get_local $2) + ) + (call_indirect (type $FUNCSIG$vi) + (i32.const 3) + (get_local $3) + ) + (drop + (call_indirect (type $FUNCSIG$iii) + (i32.const 4) + (i32.const 5) + (get_local $4) + ) + ) + (drop + (call_indirect (type $FUNCSIG$fffi) + (f32.const 3.0999999046325684) + (f32.const 4.199999809265137) + (i32.const 5) + (get_local $5) + ) + ) + (drop + (call_indirect (type $FUNCSIG$ddi) + (f64.const 4.2) + (i32.const 5) + (get_local $1) + ) + ) + (call_indirect (type $FUNCSIG$viii) + (i32.const 1) + (i32.const 2) + (i32.const 3) + (select + (i32.const 1) + (i32.const 2) + (i32.gt_s + (get_local $0) + (i32.const 3) + ) + ) + ) + (i32.const 0) + ) + (func $__wasm_nullptr (; 4 ;) (type $FUNCSIG$v) + (unreachable) + ) + (func $stackSave (; 5 ;) (result i32) + (i32.load offset=4 + (i32.const 0) + ) + ) + (func $stackAlloc (; 6 ;) (param $0 i32) (result i32) + (local $1 i32) + (i32.store offset=4 + (i32.const 0) + (tee_local $1 + (i32.and + (i32.sub + (i32.load offset=4 + (i32.const 0) + ) + (get_local $0) + ) + (i32.const -16) + ) + ) + ) + (get_local $1) + ) + (func $stackRestore (; 7 ;) (param $0 i32) + (i32.store offset=4 + (i32.const 0) + (get_local $0) + ) + ) + (func $dynCall_viii (; 8 ;) (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) + (call_indirect (type $FUNCSIG$viii) + (get_local $0) + (get_local $1) + (get_local $2) + (get_local $fptr) + ) + ) +) +;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [] } diff --git a/test/lld/reserved_func_ptr.cpp b/test/lld/reserved_func_ptr.cpp new file mode 100644 index 000000000..f40613ea0 --- /dev/null +++ b/test/lld/reserved_func_ptr.cpp @@ -0,0 +1,34 @@ +int atoi(const char *nptr); + +void address_taken_func(int a, int b, int c) {} +void address_taken_func2(int a, int b, int c) {} + +int main(int argc, char **argv) { + int fp_v = atoi(argv[1]); + int fp_vi = atoi(argv[2]); + int fp_iii = atoi(argv[3]); + int fp_fffi = atoi(argv[4]); + int fp_ddi = atoi(argv[5]); + + void (*f_viiii)(int, int, int) = 0; + if (argc > 3) + f_viiii = address_taken_func; + else + f_viiii = address_taken_func2; + + void (*f_v)() = reinterpret_cast<void (*)()>(fp_v); + void (*f_vi)(int) = reinterpret_cast<void (*)(int)>(fp_vi); + int (*f_iii)(int, int) = reinterpret_cast<int (*)(int, int)>(fp_iii); + float (*f_fffi)(float, float, int) = + reinterpret_cast<float (*)(float, float, int)>(fp_fffi); + double (*f_ddi)(double, int) = + reinterpret_cast<double (*)(double, int)>(fp_ddi); + + f_v(); + f_vi(3); + f_iii(4, 5); + f_fffi(3.1f, 4.2f, 5); + f_ddi(4.2, 5); + f_viiii(1, 2, 3); + return 0; +} diff --git a/test/lld/reserved_func_ptr.jscall.json b/test/lld/reserved_func_ptr.jscall.json new file mode 100644 index 000000000..e463aafe7 --- /dev/null +++ b/test/lld/reserved_func_ptr.jscall.json @@ -0,0 +1 @@ +{ "asmConsts": {},"staticBump": 0, "initializers": ["__wasm_call_ctors"], "jsCallStartIndex": 3, "jsCallFuncType": ["ddi", "fffi", "iii", "v", "vi", "viii"] } diff --git a/test/lld/reserved_func_ptr.json b/test/lld/reserved_func_ptr.json new file mode 100644 index 000000000..82f73d077 --- /dev/null +++ b/test/lld/reserved_func_ptr.json @@ -0,0 +1 @@ +{ "asmConsts": {},"staticBump": 0, "initializers": ["__wasm_call_ctors"] } diff --git a/test/lld/reserved_func_ptr.o b/test/lld/reserved_func_ptr.o Binary files differnew file mode 100644 index 000000000..f352c5cfe --- /dev/null +++ b/test/lld/reserved_func_ptr.o diff --git a/test/lld/reserved_func_ptr.wast b/test/lld/reserved_func_ptr.wast new file mode 100644 index 000000000..6a77ec71b --- /dev/null +++ b/test/lld/reserved_func_ptr.wast @@ -0,0 +1,111 @@ +(module + (type $0 (func)) + (type $1 (func (param i32))) + (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (param f32 f32 i32) (result f32))) + (type $4 (func (param f64 i32) (result f64))) + (type $5 (func (param i32 i32 i32))) + (type $6 (func (param i32) (result i32))) + (import "env" "_Z4atoiPKc" (func $_Z4atoiPKc (param i32) (result i32))) + (global $global$0 (mut i32) (i32.const 66560)) + (global $global$1 i32 (i32.const 66560)) + (table 3 3 anyfunc) + (elem (i32.const 1) $_Z18address_taken_funciii $_Z19address_taken_func2iii) + (memory $0 2) + (export "memory" (memory $0)) + (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "main" (func $main)) + (export "__heap_base" (global $global$1)) + (func $_Z18address_taken_funciii (; 1 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + ) + (func $_Z19address_taken_func2iii (; 2 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + ) + (func $main (; 3 ;) (type $2) (param $var$0 i32) (param $var$1 i32) (result i32) + (local $var$2 i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (set_local $var$2 + (call $_Z4atoiPKc + (i32.load offset=4 + (get_local $var$1) + ) + ) + ) + (set_local $var$3 + (call $_Z4atoiPKc + (i32.load offset=8 + (get_local $var$1) + ) + ) + ) + (set_local $var$4 + (call $_Z4atoiPKc + (i32.load offset=12 + (get_local $var$1) + ) + ) + ) + (set_local $var$5 + (call $_Z4atoiPKc + (i32.load offset=16 + (get_local $var$1) + ) + ) + ) + (set_local $var$1 + (call $_Z4atoiPKc + (i32.load offset=20 + (get_local $var$1) + ) + ) + ) + (call_indirect (type $0) + (get_local $var$2) + ) + (call_indirect (type $1) + (i32.const 3) + (get_local $var$3) + ) + (drop + (call_indirect (type $2) + (i32.const 4) + (i32.const 5) + (get_local $var$4) + ) + ) + (drop + (call_indirect (type $3) + (f32.const 3.0999999046325684) + (f32.const 4.199999809265137) + (i32.const 5) + (get_local $var$5) + ) + ) + (drop + (call_indirect (type $4) + (f64.const 4.2) + (i32.const 5) + (get_local $var$1) + ) + ) + (call_indirect (type $5) + (i32.const 1) + (i32.const 2) + (i32.const 3) + (select + (i32.const 1) + (i32.const 2) + (i32.gt_s + (get_local $var$0) + (i32.const 3) + ) + ) + ) + (i32.const 0) + ) + (func $__wasm_call_ctors (; 4 ;) (type $0) + ) + ;; custom section "linking", size 3 +) + diff --git a/test/lld/reserved_func_ptr.wast.jscall.out b/test/lld/reserved_func_ptr.wast.jscall.out new file mode 100644 index 000000000..02166bf6c --- /dev/null +++ b/test/lld/reserved_func_ptr.wast.jscall.out @@ -0,0 +1,294 @@ +(module + (type $0 (func)) + (type $1 (func (param i32))) + (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (param f32 f32 i32) (result f32))) + (type $4 (func (param f64 i32) (result f64))) + (type $5 (func (param i32 i32 i32))) + (type $6 (func (param i32) (result i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$viii (func (param i32 i32 i32))) + (type $FUNCSIG$didi (func (param i32 f64 i32) (result f64))) + (type $FUNCSIG$ddi (func (param f64 i32) (result f64))) + (type $FUNCSIG$fiffi (func (param i32 f32 f32 i32) (result f32))) + (type $FUNCSIG$fffi (func (param f32 f32 i32) (result f32))) + (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) + (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $FUNCSIG$vi (func (param i32))) + (type $FUNCSIG$v (func)) + (type $FUNCSIG$vii (func (param i32 i32))) + (type $FUNCSIG$viiii (func (param i32 i32 i32 i32))) + (import "env" "_Z4atoiPKc" (func $_Z4atoiPKc (param i32) (result i32))) + (import "env" "jsCall_ddi" (func $jsCall_ddi (param i32 f64 i32) (result f64))) + (import "env" "jsCall_fffi" (func $jsCall_fffi (param i32 f32 f32 i32) (result f32))) + (import "env" "jsCall_iii" (func $jsCall_iii (param i32 i32 i32) (result i32))) + (import "env" "jsCall_v" (func $jsCall_v (param i32))) + (import "env" "jsCall_vi" (func $jsCall_vi (param i32 i32))) + (import "env" "jsCall_viii" (func $jsCall_viii (param i32 i32 i32 i32))) + (global $global$0 (mut i32) (i32.const 66560)) + (global $global$1 i32 (i32.const 66560)) + (table 21 21 anyfunc) + (elem (i32.const 1) $_Z18address_taken_funciii $_Z19address_taken_func2iii $jsCall_ddi_0 $jsCall_ddi_1 $jsCall_ddi_2 $jsCall_fffi_0 $jsCall_fffi_1 $jsCall_fffi_2 $jsCall_iii_0 $jsCall_iii_1 $jsCall_iii_2 $jsCall_v_0 $jsCall_v_1 $jsCall_v_2 $jsCall_vi_0 $jsCall_vi_1 $jsCall_vi_2 $jsCall_viii_0 $jsCall_viii_1 $jsCall_viii_2) + (memory $0 2) + (export "memory" (memory $0)) + (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "main" (func $main)) + (export "__heap_base" (global $global$1)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "dynCall_viii" (func $dynCall_viii)) + (func $_Z18address_taken_funciii (; 7 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + (nop) + ) + (func $_Z19address_taken_func2iii (; 8 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + (nop) + ) + (func $main (; 9 ;) (type $2) (param $var$0 i32) (param $var$1 i32) (result i32) + (local $var$2 i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (set_local $var$2 + (call $_Z4atoiPKc + (i32.load offset=4 + (get_local $var$1) + ) + ) + ) + (set_local $var$3 + (call $_Z4atoiPKc + (i32.load offset=8 + (get_local $var$1) + ) + ) + ) + (set_local $var$4 + (call $_Z4atoiPKc + (i32.load offset=12 + (get_local $var$1) + ) + ) + ) + (set_local $var$5 + (call $_Z4atoiPKc + (i32.load offset=16 + (get_local $var$1) + ) + ) + ) + (set_local $var$1 + (call $_Z4atoiPKc + (i32.load offset=20 + (get_local $var$1) + ) + ) + ) + (call_indirect (type $0) + (get_local $var$2) + ) + (call_indirect (type $1) + (i32.const 3) + (get_local $var$3) + ) + (drop + (call_indirect (type $2) + (i32.const 4) + (i32.const 5) + (get_local $var$4) + ) + ) + (drop + (call_indirect (type $3) + (f32.const 3.0999999046325684) + (f32.const 4.199999809265137) + (i32.const 5) + (get_local $var$5) + ) + ) + (drop + (call_indirect (type $4) + (f64.const 4.2) + (i32.const 5) + (get_local $var$1) + ) + ) + (call_indirect (type $5) + (i32.const 1) + (i32.const 2) + (i32.const 3) + (select + (i32.const 1) + (i32.const 2) + (i32.gt_s + (get_local $var$0) + (i32.const 3) + ) + ) + ) + (i32.const 0) + ) + (func $__wasm_call_ctors (; 10 ;) (type $0) + (nop) + ) + (func $stackSave (; 11 ;) (result i32) + (get_global $global$0) + ) + (func $stackAlloc (; 12 ;) (param $0 i32) (result i32) + (local $1 i32) + (set_global $global$0 + (tee_local $1 + (i32.and + (i32.sub + (get_global $global$0) + (get_local $0) + ) + (i32.const -16) + ) + ) + ) + (get_local $1) + ) + (func $stackRestore (; 13 ;) (param $0 i32) + (set_global $global$0 + (get_local $0) + ) + ) + (func $__growWasmMemory (; 14 ;) (param $newSize i32) (result i32) + (grow_memory + (get_local $newSize) + ) + ) + (func $dynCall_viii (; 15 ;) (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) + (call_indirect (type $FUNCSIG$viii) + (get_local $0) + (get_local $1) + (get_local $2) + (get_local $fptr) + ) + ) + (func $jsCall_ddi_0 (; 16 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 0) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_ddi_1 (; 17 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 1) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_ddi_2 (; 18 ;) (param $0 f64) (param $1 i32) (result f64) + (call $jsCall_ddi + (i32.const 2) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_fffi_0 (; 19 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 0) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_fffi_1 (; 20 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 1) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_fffi_2 (; 21 ;) (param $0 f32) (param $1 f32) (param $2 i32) (result f32) + (call $jsCall_fffi + (i32.const 2) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_iii_0 (; 22 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 0) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_iii_1 (; 23 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 1) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_iii_2 (; 24 ;) (param $0 i32) (param $1 i32) (result i32) + (call $jsCall_iii + (i32.const 2) + (get_local $0) + (get_local $1) + ) + ) + (func $jsCall_v_0 (; 25 ;) + (call $jsCall_v + (i32.const 0) + ) + ) + (func $jsCall_v_1 (; 26 ;) + (call $jsCall_v + (i32.const 1) + ) + ) + (func $jsCall_v_2 (; 27 ;) + (call $jsCall_v + (i32.const 2) + ) + ) + (func $jsCall_vi_0 (; 28 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 0) + (get_local $0) + ) + ) + (func $jsCall_vi_1 (; 29 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 1) + (get_local $0) + ) + ) + (func $jsCall_vi_2 (; 30 ;) (param $0 i32) + (call $jsCall_vi + (i32.const 2) + (get_local $0) + ) + ) + (func $jsCall_viii_0 (; 31 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 0) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_viii_1 (; 32 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 1) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) + (func $jsCall_viii_2 (; 33 ;) (param $0 i32) (param $1 i32) (param $2 i32) + (call $jsCall_viii + (i32.const 2) + (get_local $0) + (get_local $1) + (get_local $2) + ) + ) +) diff --git a/test/lld/reserved_func_ptr.wast.out b/test/lld/reserved_func_ptr.wast.out new file mode 100644 index 000000000..983269810 --- /dev/null +++ b/test/lld/reserved_func_ptr.wast.out @@ -0,0 +1,155 @@ +(module + (type $0 (func)) + (type $1 (func (param i32))) + (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (param f32 f32 i32) (result f32))) + (type $4 (func (param f64 i32) (result f64))) + (type $5 (func (param i32 i32 i32))) + (type $6 (func (param i32) (result i32))) + (type $FUNCSIG$ii (func (param i32) (result i32))) + (type $FUNCSIG$viii (func (param i32 i32 i32))) + (import "env" "_Z4atoiPKc" (func $_Z4atoiPKc (param i32) (result i32))) + (global $global$0 (mut i32) (i32.const 66560)) + (global $global$1 i32 (i32.const 66560)) + (table 3 3 anyfunc) + (elem (i32.const 1) $_Z18address_taken_funciii $_Z19address_taken_func2iii) + (memory $0 2) + (export "memory" (memory $0)) + (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "main" (func $main)) + (export "__heap_base" (global $global$1)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "dynCall_viii" (func $dynCall_viii)) + (func $_Z18address_taken_funciii (; 1 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + (nop) + ) + (func $_Z19address_taken_func2iii (; 2 ;) (type $5) (param $var$0 i32) (param $var$1 i32) (param $var$2 i32) + (nop) + ) + (func $main (; 3 ;) (type $2) (param $var$0 i32) (param $var$1 i32) (result i32) + (local $var$2 i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (set_local $var$2 + (call $_Z4atoiPKc + (i32.load offset=4 + (get_local $var$1) + ) + ) + ) + (set_local $var$3 + (call $_Z4atoiPKc + (i32.load offset=8 + (get_local $var$1) + ) + ) + ) + (set_local $var$4 + (call $_Z4atoiPKc + (i32.load offset=12 + (get_local $var$1) + ) + ) + ) + (set_local $var$5 + (call $_Z4atoiPKc + (i32.load offset=16 + (get_local $var$1) + ) + ) + ) + (set_local $var$1 + (call $_Z4atoiPKc + (i32.load offset=20 + (get_local $var$1) + ) + ) + ) + (call_indirect (type $0) + (get_local $var$2) + ) + (call_indirect (type $1) + (i32.const 3) + (get_local $var$3) + ) + (drop + (call_indirect (type $2) + (i32.const 4) + (i32.const 5) + (get_local $var$4) + ) + ) + (drop + (call_indirect (type $3) + (f32.const 3.0999999046325684) + (f32.const 4.199999809265137) + (i32.const 5) + (get_local $var$5) + ) + ) + (drop + (call_indirect (type $4) + (f64.const 4.2) + (i32.const 5) + (get_local $var$1) + ) + ) + (call_indirect (type $5) + (i32.const 1) + (i32.const 2) + (i32.const 3) + (select + (i32.const 1) + (i32.const 2) + (i32.gt_s + (get_local $var$0) + (i32.const 3) + ) + ) + ) + (i32.const 0) + ) + (func $__wasm_call_ctors (; 4 ;) (type $0) + (nop) + ) + (func $stackSave (; 5 ;) (result i32) + (get_global $global$0) + ) + (func $stackAlloc (; 6 ;) (param $0 i32) (result i32) + (local $1 i32) + (set_global $global$0 + (tee_local $1 + (i32.and + (i32.sub + (get_global $global$0) + (get_local $0) + ) + (i32.const -16) + ) + ) + ) + (get_local $1) + ) + (func $stackRestore (; 7 ;) (param $0 i32) + (set_global $global$0 + (get_local $0) + ) + ) + (func $__growWasmMemory (; 8 ;) (param $newSize i32) (result i32) + (grow_memory + (get_local $newSize) + ) + ) + (func $dynCall_viii (; 9 ;) (param $fptr i32) (param $0 i32) (param $1 i32) (param $2 i32) + (call_indirect (type $FUNCSIG$viii) + (get_local $0) + (get_local $1) + (get_local $2) + (get_local $fptr) + ) + ) +) |