summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp148
1 files changed, 40 insertions, 108 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b8b001927..d86eea8f5 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -30,56 +30,7 @@ namespace wasm {
void WasmBinaryWriter::prepare() {
// Collect function types and their frequencies. Collect information in each
// function in parallel, then merge.
- typedef std::unordered_map<Signature, size_t> Counts;
- ModuleUtils::ParallelFunctionAnalysis<Counts> analysis(
- *wasm, [&](Function* func, Counts& counts) {
- if (func->imported()) {
- return;
- }
- struct TypeCounter : PostWalker<TypeCounter> {
- Module& wasm;
- Counts& counts;
-
- TypeCounter(Module& wasm, Counts& counts)
- : wasm(wasm), counts(counts) {}
-
- void visitCallIndirect(CallIndirect* curr) {
- auto* type = wasm.getFunctionType(curr->fullType);
- Signature sig(Type(type->params), type->result);
- counts[sig]++;
- }
- };
- TypeCounter(*wasm, counts).walk(func->body);
- });
- // Collect all the counts.
- Counts counts;
- for (auto& curr : wasm->functions) {
- counts[Signature(Type(curr->params), curr->result)]++;
- }
- for (auto& curr : wasm->events) {
- counts[curr->sig]++;
- }
- for (auto& pair : analysis.map) {
- Counts& functionCounts = pair.second;
- for (auto& innerPair : functionCounts) {
- counts[innerPair.first] += innerPair.second;
- }
- }
- std::vector<std::pair<Signature, size_t>> sorted(counts.begin(),
- counts.end());
- std::sort(sorted.begin(), sorted.end(), [&](auto a, auto b) {
- // order by frequency then simplicity
- if (a.second != b.second) {
- return a.second > b.second;
- } else {
- return a.first < b.first;
- }
- });
- for (Index i = 0; i < sorted.size(); ++i) {
- typeIndexes[sorted[i].first] = i;
- types.push_back(sorted[i].first);
- }
-
+ ModuleUtils::collectSignatures(*wasm, types, typeIndices);
importInfo = wasm::make_unique<ImportInfo>(*wasm);
}
@@ -250,7 +201,7 @@ void WasmBinaryWriter::writeImports() {
BYN_TRACE("write one function\n");
writeImportHeader(func);
o << U32LEB(int32_t(ExternalKind::Function));
- o << U32LEB(getTypeIndex(Signature(Type(func->params), func->result)));
+ o << U32LEB(getTypeIndex(func->sig));
});
ModuleUtils::iterImportedGlobals(*wasm, [&](Global* global) {
BYN_TRACE("write one global\n");
@@ -297,7 +248,7 @@ void WasmBinaryWriter::writeFunctionSignatures() {
o << U32LEB(importInfo->getNumDefinedFunctions());
ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
BYN_TRACE("write one\n");
- o << U32LEB(getTypeIndex(Signature(Type(func->params), func->result)));
+ o << U32LEB(getTypeIndex(func->sig));
});
finishSection(start);
}
@@ -458,8 +409,8 @@ uint32_t WasmBinaryWriter::getEventIndex(Name name) const {
}
uint32_t WasmBinaryWriter::getTypeIndex(Signature sig) const {
- auto it = typeIndexes.find(sig);
- assert(it != typeIndexes.end());
+ auto it = typeIndices.find(sig);
+ assert(it != typeIndices.end());
return it->second;
}
@@ -1124,7 +1075,8 @@ void WasmBinaryBuilder::readSignatures() {
BYN_TRACE("num: " << numTypes << std::endl);
for (size_t i = 0; i < numTypes; i++) {
BYN_TRACE("read one\n");
- auto curr = make_unique<FunctionType>();
+ std::vector<Type> params;
+ std::vector<Type> results;
auto form = getS32LEB();
if (form != BinaryConsts::EncodedType::Func) {
throwError("bad signature form " + std::to_string(form));
@@ -1132,19 +1084,14 @@ void WasmBinaryBuilder::readSignatures() {
size_t numParams = getU32LEB();
BYN_TRACE("num params: " << numParams << std::endl);
for (size_t j = 0; j < numParams; j++) {
- curr->params.push_back(getConcreteType());
+ params.push_back(getConcreteType());
}
auto numResults = getU32LEB();
- if (numResults == 0) {
- curr->result = none;
- } else {
- if (numResults != 1) {
- throwError("signature must have 1 result");
- }
- curr->result = getType();
+ BYN_TRACE("num results: " << numResults << std::endl);
+ for (size_t j = 0; j < numResults; j++) {
+ results.push_back(getConcreteType());
}
- curr->name = Name::fromInt(wasm.functionTypes.size());
- wasm.addFunctionType(std::move(curr));
+ signatures.emplace_back(Type(params), Type(results));
}
}
@@ -1205,17 +1152,13 @@ void WasmBinaryBuilder::readImports() {
case ExternalKind::Function: {
auto name = Name(std::string("fimport$") + std::to_string(i));
auto index = getU32LEB();
- if (index >= wasm.functionTypes.size()) {
+ if (index > signatures.size()) {
throwError("invalid function index " + std::to_string(index) + " / " +
- std::to_string(wasm.functionTypes.size()));
+ std::to_string(signatures.size()));
}
- auto* functionType = wasm.functionTypes[index].get();
- auto params = functionType->params;
- auto result = functionType->result;
- auto* curr = builder.makeFunction(name, std::move(params), result, {});
+ auto* curr = builder.makeFunction(name, signatures[index], {});
curr->module = module;
curr->base = base;
- curr->type = functionType->name;
wasm.addFunction(curr);
functionImports.push_back(curr);
break;
@@ -1267,13 +1210,11 @@ void WasmBinaryBuilder::readImports() {
auto name = Name(std::string("eimport$") + std::to_string(i));
auto attribute = getU32LEB();
auto index = getU32LEB();
- if (index >= wasm.functionTypes.size()) {
+ if (index >= signatures.size()) {
throwError("invalid event index " + std::to_string(index) + " / " +
- std::to_string(wasm.functionTypes.size()));
+ std::to_string(signatures.size()));
}
- Type params = Type(wasm.functionTypes[index]->params);
- auto* curr =
- builder.makeEvent(name, attribute, Signature(params, Type::none));
+ auto* curr = builder.makeEvent(name, attribute, signatures[index]);
curr->module = module;
curr->base = base;
wasm.addEvent(curr);
@@ -1302,17 +1243,17 @@ void WasmBinaryBuilder::readFunctionSignatures() {
for (size_t i = 0; i < num; i++) {
BYN_TRACE("read one\n");
auto index = getU32LEB();
- if (index >= wasm.functionTypes.size()) {
+ if (index >= signatures.size()) {
throwError("invalid function type index for function");
}
- functionTypes.push_back(wasm.functionTypes[index].get());
+ functionSignatures.push_back(signatures[index]);
}
}
void WasmBinaryBuilder::readFunctions() {
BYN_TRACE("== readFunctions\n");
size_t total = getU32LEB();
- if (total != functionTypes.size()) {
+ if (total != functionSignatures.size()) {
throwError("invalid function section size, must equal types");
}
for (size_t i = 0; i < total; i++) {
@@ -1325,17 +1266,12 @@ void WasmBinaryBuilder::readFunctions() {
Function* func = new Function;
func->name = Name::fromInt(i);
+ func->sig = functionSignatures[i];
currFunction = func;
readNextDebugLocation();
- auto type = functionTypes[i];
BYN_TRACE("reading " << i << std::endl);
- func->type = type->name;
- func->result = type->result;
- for (size_t j = 0; j < type->params.size(); j++) {
- func->params.emplace_back(type->params[j]);
- }
size_t numLocalTypes = getU32LEB();
for (size_t t = 0; t < numLocalTypes; t++) {
auto num = getU32LEB();
@@ -1357,7 +1293,7 @@ void WasmBinaryBuilder::readFunctions() {
assert(breakStack.empty());
assert(expressionStack.empty());
assert(depth == 0);
- func->body = getBlockOrSingleton(func->result);
+ func->body = getBlockOrSingleton(func->sig.results);
assert(depth == 0);
assert(breakStack.size() == 0);
assert(breakTargetNames.size() == 0);
@@ -1391,7 +1327,7 @@ void WasmBinaryBuilder::readExports() {
names.insert(curr->name);
curr->kind = (ExternalKind)getU32LEB();
auto index = getU32LEB();
- exportIndexes[curr] = index;
+ exportIndices[curr] = index;
exportOrder.push_back(curr);
}
}
@@ -1753,7 +1689,7 @@ void WasmBinaryBuilder::processFunctions() {
}
for (auto* curr : exportOrder) {
- auto index = exportIndexes[curr];
+ auto index = exportIndices[curr];
switch (curr->kind) {
case ExternalKind::Function: {
curr->value = getFunctionName(index);
@@ -1787,8 +1723,8 @@ void WasmBinaryBuilder::processFunctions() {
for (auto& pair : functionTable) {
auto i = pair.first;
- auto& indexes = pair.second;
- for (auto j : indexes) {
+ auto& indices = pair.second;
+ for (auto j : indices) {
wasm.table.segments[i].data.push_back(getFunctionName(j));
}
}
@@ -1884,13 +1820,12 @@ void WasmBinaryBuilder::readEvents() {
BYN_TRACE("read one\n");
auto attribute = getU32LEB();
auto typeIndex = getU32LEB();
- if (typeIndex >= wasm.functionTypes.size()) {
+ if (typeIndex >= signatures.size()) {
throwError("invalid event index " + std::to_string(typeIndex) + " / " +
- std::to_string(wasm.functionTypes.size()));
+ std::to_string(signatures.size()));
}
- Type params = Type(wasm.functionTypes[typeIndex]->params);
wasm.addEvent(Builder::makeEvent(
- "event$" + std::to_string(i), attribute, Signature(params, Type::none)));
+ "event$" + std::to_string(i), attribute, signatures[typeIndex]));
}
}
@@ -2463,24 +2398,23 @@ void WasmBinaryBuilder::visitSwitch(Switch* curr) {
void WasmBinaryBuilder::visitCall(Call* curr) {
BYN_TRACE("zz node: Call\n");
auto index = getU32LEB();
- FunctionType* type;
+ Signature sig;
if (index < functionImports.size()) {
auto* import = functionImports[index];
- type = wasm.getFunctionType(import->type);
+ sig = import->sig;
} else {
Index adjustedIndex = index - functionImports.size();
- if (adjustedIndex >= functionTypes.size()) {
+ if (adjustedIndex >= functionSignatures.size()) {
throwError("invalid call index");
}
- type = functionTypes[adjustedIndex];
+ sig = functionSignatures[adjustedIndex];
}
- assert(type);
- auto num = type->params.size();
+ auto num = sig.params.size();
curr->operands.resize(num);
for (size_t i = 0; i < num; i++) {
curr->operands[num - i - 1] = popNonVoidExpression();
}
- curr->type = type->result;
+ curr->type = sig.results;
functionCalls[index].push_back(curr); // we don't know function names yet
curr->finalize();
}
@@ -2488,22 +2422,20 @@ void WasmBinaryBuilder::visitCall(Call* curr) {
void WasmBinaryBuilder::visitCallIndirect(CallIndirect* curr) {
BYN_TRACE("zz node: CallIndirect\n");
auto index = getU32LEB();
- if (index >= wasm.functionTypes.size()) {
+ if (index >= signatures.size()) {
throwError("bad call_indirect function index");
}
- auto* fullType = wasm.functionTypes[index].get();
+ curr->sig = signatures[index];
auto reserved = getU32LEB();
if (reserved != 0) {
throwError("Invalid flags field in call_indirect");
}
- curr->fullType = fullType->name;
- auto num = fullType->params.size();
+ auto num = curr->sig.params.size();
curr->operands.resize(num);
curr->target = popNonVoidExpression();
for (size_t i = 0; i < num; i++) {
curr->operands[num - i - 1] = popNonVoidExpression();
}
- curr->type = fullType->result;
curr->finalize();
}
@@ -4299,7 +4231,7 @@ void WasmBinaryBuilder::visitSelect(Select* curr) {
void WasmBinaryBuilder::visitReturn(Return* curr) {
BYN_TRACE("zz node: Return\n");
requireFunctionContext("return");
- if (currFunction->result != none) {
+ if (currFunction->sig.results != Type::none) {
curr->value = popNonVoidExpression();
}
curr->finalize();