std::vector<Function*> makeDynCallThunks(Module& wasm, std::vector<Name> const& tableSegmentData) { wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions std::vector<Function*> generatedFunctions; std::unordered_set<std::string> sigs; Builder wasmBuilder(wasm); for (const auto& indirectFunc : tableSegmentData) { std::string sig(getSig(wasm.getFunction(indirectFunc))); auto* funcType = ensureFunctionType(sig, &wasm); if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. if (!sigs.insert(sig).second) continue; // Sig is already in the set std::vector<NameType> params; params.emplace_back("fptr", i32); // function pointer param int p = 0; for (const auto& ty : funcType->params) params.emplace_back(std::to_string(p++), ty); Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {}); Expression* fptr = wasmBuilder.makeGetLocal(0, i32); std::vector<Expression*> args; for (unsigned i = 0; i < funcType->params.size(); ++i) { args.push_back(wasmBuilder.makeGetLocal(i + 1, funcType->params[i])); } Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, args); f->body = call; wasm.addFunction(f); generatedFunctions.push_back(f); } return generatedFunctions; }
void generateMemoryGrowthFunction(Module& wasm) { Builder wasmBuilder(wasm); Name name(GROW_WASM_MEMORY); std::vector<NameType> params { { NEW_SIZE, i32 } }; Function* growFunction = wasmBuilder.makeFunction( name, std::move(params), i32, {} ); growFunction->body = wasmBuilder.makeHost( GrowMemory, Name(), { wasmBuilder.makeGetLocal(0, i32) } ); wasm.addFunction(growFunction); auto export_ = new Export; export_->name = export_->value = name; export_->kind = ExternalKind::Function; wasm.addExport(export_); }