summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-emscripten.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-emscripten.cpp')
-rw-r--r--src/wasm/wasm-emscripten.cpp124
1 files changed, 58 insertions, 66 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 695561f68..9a0b145da 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -20,7 +20,6 @@
#include "asm_v_wasm.h"
#include "asmjs/shared-constants.h"
-#include "ir/function-type-utils.h"
#include "ir/import-utils.h"
#include "ir/literal-utils.h"
#include "ir/module-utils.h"
@@ -207,7 +206,7 @@ void EmscriptenGlueGenerator::generateRuntimeFunctions() {
}
static Function*
-ensureFunctionImport(Module* module, Name name, std::string sig) {
+ensureFunctionImport(Module* module, Name name, Signature sig) {
// Then see if its already imported
ImportInfo info(*module);
if (Function* f = info.getImportedFunction(ENV, name)) {
@@ -218,9 +217,7 @@ ensureFunctionImport(Module* module, Name name, std::string sig) {
import->name = name;
import->module = ENV;
import->base = name;
- auto* functionType = ensureFunctionType(sig, module);
- import->type = functionType->name;
- FunctionTypeUtils::fillFunction(import, functionType);
+ import->sig = sig;
module->addFunction(import);
return import;
}
@@ -267,7 +264,7 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() {
for (Global* g : gotMemEntries) {
Name getter(std::string("g$") + g->base.c_str());
- ensureFunctionImport(&wasm, getter, "i");
+ ensureFunctionImport(&wasm, getter, Signature(Type::none, Type::i32));
Expression* call = builder.makeCall(getter, {}, i32);
GlobalSet* globalSet = builder.makeGlobalSet(g->name, call);
block->list.push_back(globalSet);
@@ -293,7 +290,7 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() {
Name getter(
(std::string("fp$") + g->base.c_str() + std::string("$") + getSig(f))
.c_str());
- ensureFunctionImport(&wasm, getter, "i");
+ ensureFunctionImport(&wasm, getter, Signature(Type::none, Type::i32));
Expression* call = builder.makeCall(getter, {}, i32);
GlobalSet* globalSet = builder.makeGlobalSet(g->name, call);
block->list.push_back(globalSet);
@@ -371,29 +368,28 @@ inline void exportFunction(Module& wasm, Name name, bool must_export) {
wasm.addExport(exp);
}
-void EmscriptenGlueGenerator::generateDynCallThunk(std::string sig) {
- auto* funcType = ensureFunctionType(sig, &wasm);
+void EmscriptenGlueGenerator::generateDynCallThunk(Signature sig) {
if (!sigs.insert(sig).second) {
return; // sig is already in the set
}
- Name name = std::string("dynCall_") + sig;
+ Name name = std::string("dynCall_") + getSig(sig.results, sig.params);
if (wasm.getFunctionOrNull(name) || wasm.getExportOrNull(name)) {
return; // module already contains this dyncall
}
std::vector<NameType> params;
params.emplace_back("fptr", i32); // function pointer param
int p = 0;
- for (const auto& ty : funcType->params) {
+ const std::vector<Type>& paramTypes = sig.params.expand();
+ for (const auto& ty : paramTypes) {
params.emplace_back(std::to_string(p++), ty);
}
- Function* f =
- builder.makeFunction(name, std::move(params), funcType->result, {});
+ Function* f = builder.makeFunction(name, std::move(params), sig.results, {});
Expression* fptr = builder.makeLocalGet(0, i32);
std::vector<Expression*> args;
- for (unsigned i = 0; i < funcType->params.size(); ++i) {
- args.push_back(builder.makeLocalGet(i + 1, funcType->params[i]));
+ for (unsigned i = 0; i < paramTypes.size(); ++i) {
+ args.push_back(builder.makeLocalGet(i + 1, paramTypes[i]));
}
- Expression* call = builder.makeCallIndirect(funcType, fptr, args);
+ Expression* call = builder.makeCallIndirect(fptr, args, sig);
f->body = call;
wasm.addFunction(f);
@@ -407,8 +403,7 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
tableSegmentData = wasm.table.segments[0].data;
}
for (const auto& indirectFunc : tableSegmentData) {
- std::string sig = getSig(wasm.getFunction(indirectFunc));
- generateDynCallThunk(sig);
+ generateDynCallThunk(wasm.getFunction(indirectFunc)->sig);
}
}
@@ -479,10 +474,11 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
RemoveStackPointer walker(stackPointer);
walker.walkModule(&wasm);
if (walker.needStackSave) {
- ensureFunctionImport(&wasm, STACK_SAVE, "i");
+ ensureFunctionImport(&wasm, STACK_SAVE, Signature(Type::none, Type::i32));
}
if (walker.needStackRestore) {
- ensureFunctionImport(&wasm, STACK_RESTORE, "vi");
+ ensureFunctionImport(
+ &wasm, STACK_RESTORE, Signature(Type::i32, Type::none));
}
// Finally remove the stack pointer global itself. This avoids importing
@@ -545,7 +541,7 @@ void EmscriptenGlueGenerator::enforceStackLimit() {
void EmscriptenGlueGenerator::generateSetStackLimitFunction() {
Function* function =
- builder.makeFunction(SET_STACK_LIMIT, std::vector<Type>({i32}), none, {});
+ builder.makeFunction(SET_STACK_LIMIT, Signature(Type::i32, Type::none), {});
LocalGet* getArg = builder.makeLocalGet(0, i32);
Expression* store = builder.makeGlobalSet(STACK_LIMIT, getArg);
function->body = store;
@@ -562,9 +558,7 @@ Name EmscriptenGlueGenerator::importStackOverflowHandler() {
import->name = STACK_OVERFLOW_IMPORT;
import->module = ENV;
import->base = STACK_OVERFLOW_IMPORT;
- auto* functionType = ensureFunctionType("v", &wasm);
- import->type = functionType->name;
- FunctionTypeUtils::fillFunction(import, functionType);
+ import->sig = Signature(Type::none, Type::none);
wasm.addFunction(import);
return STACK_OVERFLOW_IMPORT;
}
@@ -696,14 +690,14 @@ struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
std::vector<Address> segmentOffsets; // segment index => address offset
struct AsmConst {
- std::set<std::string> sigs;
+ std::set<Signature> sigs;
Address id;
std::string code;
Proxying proxy;
};
std::vector<AsmConst> asmConsts;
- std::set<std::pair<std::string, Proxying>> allSigs;
+ std::set<std::pair<Signature, Proxying>> allSigs;
// last sets in the current basic block, per index
std::map<Index, LocalSet*> sets;
@@ -719,12 +713,12 @@ struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
void process();
private:
- std::string fixupName(Name& name, std::string baseSig, Proxying proxy);
+ Signature fixupName(Name& name, Signature baseSig, Proxying proxy);
AsmConst&
- createAsmConst(uint32_t id, std::string code, std::string sig, Name name);
- std::string asmConstSig(std::string baseSig);
- Name nameForImportWithSig(std::string sig, Proxying proxy);
- void queueImport(Name importName, std::string baseSig);
+ createAsmConst(uint32_t id, std::string code, Signature sig, Name name);
+ Signature asmConstSig(Signature baseSig);
+ Name nameForImportWithSig(Signature sig, Proxying proxy);
+ void queueImport(Name importName, Signature baseSig);
void addImports();
Proxying proxyType(Name name);
@@ -750,7 +744,7 @@ void AsmConstWalker::visitCall(Call* curr) {
return;
}
- auto baseSig = getSig(curr);
+ auto baseSig = wasm.getFunction(curr->target)->sig;
auto sig = asmConstSig(baseSig);
auto* arg = curr->operands[0];
while (!arg->dynCast<Const>()) {
@@ -816,9 +810,8 @@ void AsmConstWalker::visitTable(Table* curr) {
for (auto& name : segment.data) {
auto* func = wasm.getFunction(name);
if (func->imported() && func->base.hasSubstring(EM_ASM_PREFIX)) {
- std::string baseSig = getSig(func);
auto proxy = proxyType(func->base);
- fixupName(name, baseSig, proxy);
+ fixupName(name, func->sig, proxy);
}
}
}
@@ -832,8 +825,8 @@ void AsmConstWalker::process() {
addImports();
}
-std::string
-AsmConstWalker::fixupName(Name& name, std::string baseSig, Proxying proxy) {
+Signature
+AsmConstWalker::fixupName(Name& name, Signature baseSig, Proxying proxy) {
auto sig = asmConstSig(baseSig);
auto importName = nameForImportWithSig(sig, proxy);
name = importName;
@@ -848,7 +841,7 @@ AsmConstWalker::fixupName(Name& name, std::string baseSig, Proxying proxy) {
AsmConstWalker::AsmConst& AsmConstWalker::createAsmConst(uint32_t id,
std::string code,
- std::string sig,
+ Signature sig,
Name name) {
AsmConst asmConst;
asmConst.id = id;
@@ -859,31 +852,27 @@ AsmConstWalker::AsmConst& AsmConstWalker::createAsmConst(uint32_t id,
return asmConsts.back();
}
-std::string AsmConstWalker::asmConstSig(std::string baseSig) {
- std::string sig = "";
- for (size_t i = 0; i < baseSig.size(); ++i) {
- // Omit the signature of the "code" parameter, taken as a string, as the
- // first argument
- if (i != 1) {
- sig += baseSig[i];
- }
- }
- return sig;
+Signature AsmConstWalker::asmConstSig(Signature baseSig) {
+ std::vector<Type> params = baseSig.params.expand();
+ assert(params.size() >= 1);
+ // Omit the signature of the "code" parameter, taken as a string, as the
+ // first argument
+ params.erase(params.begin());
+ return Signature(Type(params), baseSig.results);
}
-Name AsmConstWalker::nameForImportWithSig(std::string sig, Proxying proxy) {
- std::string fixedTarget =
- EM_ASM_PREFIX.str + std::string("_") + proxyingSuffix(proxy) + sig;
+Name AsmConstWalker::nameForImportWithSig(Signature sig, Proxying proxy) {
+ std::string fixedTarget = EM_ASM_PREFIX.str + std::string("_") +
+ proxyingSuffix(proxy) +
+ getSig(sig.results, sig.params);
return Name(fixedTarget.c_str());
}
-void AsmConstWalker::queueImport(Name importName, std::string baseSig) {
+void AsmConstWalker::queueImport(Name importName, Signature baseSig) {
auto import = new Function;
import->name = import->base = importName;
import->module = ENV;
- auto* funcType = ensureFunctionType(baseSig, &wasm);
- import->type = funcType->name;
- FunctionTypeUtils::fillFunction(import, funcType);
+ import->sig = baseSig;
queuedImports.push_back(std::unique_ptr<Function>(import));
}
@@ -994,7 +983,7 @@ struct FixInvokeFunctionNamesWalker
std::map<Name, Name> importRenames;
std::vector<Name> toRemove;
std::set<Name> newImports;
- std::set<std::string> invokeSigs;
+ std::set<Signature> invokeSigs;
FixInvokeFunctionNamesWalker(Module& _wasm) : wasm(_wasm) {}
@@ -1017,7 +1006,7 @@ struct FixInvokeFunctionNamesWalker
// This function converts the names of invoke wrappers based on their lowered
// argument types and a return type. In the example above, the resulting new
// wrapper name becomes "invoke_vii".
- Name fixEmExceptionInvoke(const Name& name, const std::string& sig) {
+ Name fixEmExceptionInvoke(const Name& name, Signature sig) {
std::string nameStr = name.c_str();
if (nameStr.front() == '"' && nameStr.back() == '"') {
nameStr = nameStr.substr(1, nameStr.size() - 2);
@@ -1025,12 +1014,16 @@ struct FixInvokeFunctionNamesWalker
if (nameStr.find("__invoke_") != 0) {
return name;
}
- std::string sigWoOrigFunc = sig.front() + sig.substr(2, sig.size() - 2);
+
+ const std::vector<Type>& params = sig.params.expand();
+ std::vector<Type> newParams(params.begin() + 1, params.end());
+ Signature sigWoOrigFunc = Signature(Type(newParams), sig.results);
invokeSigs.insert(sigWoOrigFunc);
- return Name("invoke_" + sigWoOrigFunc);
+ return Name("invoke_" +
+ getSig(sigWoOrigFunc.results, sigWoOrigFunc.params));
}
- Name fixEmEHSjLjNames(const Name& name, const std::string& sig) {
+ Name fixEmEHSjLjNames(const Name& name, Signature sig) {
if (name == "emscripten_longjmp_jmpbuf") {
return "emscripten_longjmp";
}
@@ -1042,8 +1035,7 @@ struct FixInvokeFunctionNamesWalker
return;
}
- FunctionType* func = wasm.getFunctionType(curr->type);
- Name newname = fixEmEHSjLjNames(curr->base, getSig(func));
+ Name newname = fixEmEHSjLjNames(curr->base, curr->sig);
if (newname == curr->base) {
return;
}
@@ -1085,16 +1077,16 @@ void EmscriptenGlueGenerator::fixInvokeFunctionNames() {
}
}
-template<class C> void printSet(std::ostream& o, C& c) {
+void printSignatures(std::ostream& o, const std::set<Signature>& c) {
o << "[";
bool first = true;
- for (auto& item : c) {
+ for (auto& sig : c) {
if (first) {
first = false;
} else {
o << ",";
}
- o << '"' << item << '"';
+ o << '"' << getSig(sig.results, sig.params) << '"';
}
o << "]";
}
@@ -1123,7 +1115,7 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
for (auto& asmConst : emAsmWalker.asmConsts) {
meta << nextElement();
meta << '"' << asmConst.id << "\": [\"" << asmConst.code << "\", ";
- printSet(meta, asmConst.sigs);
+ printSignatures(meta, asmConst.sigs);
meta << ", [\"" << proxyingSuffix(asmConst.proxy) << "\"]";
meta << "]";
@@ -1303,7 +1295,7 @@ void EmscriptenGlueGenerator::exportWasiStart() {
{LiteralUtils::makeZero(i32, wasm), LiteralUtils::makeZero(i32, wasm)},
i32));
auto* func =
- builder.makeFunction(_start, std::vector<wasm::Type>{}, none, {}, body);
+ builder.makeFunction(_start, Signature(Type::none, Type::none), {}, body);
wasm.addFunction(func);
wasm.addExport(builder.makeExport(_start, _start, ExternalKind::Function));
}