summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild-js.sh15
-rw-r--r--src/binaryen-c.cpp161
-rw-r--r--src/binaryen-c.h38
-rw-r--r--src/ir/ReFinalize.cpp1
-rw-r--r--src/ir/import-utils.h24
-rw-r--r--src/ir/module-utils.h45
-rw-r--r--src/ir/utils.h2
-rw-r--r--src/js/binaryen.js-post.js37
-rw-r--r--src/passes/Metrics.cpp1
-rw-r--r--src/passes/MinifyImportsAndExports.cpp1
-rw-r--r--src/passes/Print.cpp26
-rw-r--r--src/passes/RemoveUnusedModuleElements.cpp33
-rw-r--r--src/shared-constants.h2
-rw-r--r--src/tools/fuzzing.h25
-rw-r--r--src/tools/wasm-metadce.cpp34
-rw-r--r--src/wasm-binary.h10
-rw-r--r--src/wasm-builder.h13
-rw-r--r--src/wasm-s-parser.h6
-rw-r--r--src/wasm-traversal.h13
-rw-r--r--src/wasm.h25
-rw-r--r--src/wasm/wasm-binary.cpp95
-rw-r--r--src/wasm/wasm-s-parser.cpp149
-rw-r--r--src/wasm/wasm-type.cpp3
-rw-r--r--src/wasm/wasm-validator.cpp35
-rw-r--r--src/wasm/wasm.cpp47
-rw-r--r--test/binaryen.js/event.js32
-rw-r--r--test/binaryen.js/event.js.txt16
-rw-r--r--test/binaryen.js/kitchen-sink.js14
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt38
-rw-r--r--test/events.wast15
-rw-r--r--test/events.wast.from-wast12
-rw-r--r--test/events.wast.fromBinary13
-rw-r--r--test/events.wast.fromBinary.noDebugInfo13
-rw-r--r--test/example/c-api-kitchen-sink.c5
-rw-r--r--test/example/c-api-kitchen-sink.txt26
-rw-r--r--test/example/c-api-kitchen-sink.txt.txt4
-rw-r--r--test/metadce/rooted-export.wast6
-rw-r--r--test/metadce/rooted-export.wast.dced3
-rw-r--r--test/metadce/rooted-export.wast.dced.stdout4
-rw-r--r--test/metadce/rooted-export.wast.graph.txt7
-rw-r--r--test/passes/O3_low-memory-unused_metrics.txt1
-rw-r--r--test/passes/converge_O3_metrics.bin.txt3
-rw-r--r--test/passes/func-metrics.txt6
-rw-r--r--test/passes/metrics_all-features.txt (renamed from test/passes/metrics.txt)5
-rw-r--r--test/passes/metrics_all-features.wast (renamed from test/passes/metrics.wast)2
-rw-r--r--test/passes/metrics_strip-debug_metrics.bin.txt2
-rw-r--r--test/passes/metrics_strip-producers_metrics.bin.txt2
-rw-r--r--test/passes/minify-imports-and-exports_all-features.txt (renamed from test/passes/minify-imports-and-exports.txt)15
-rw-r--r--test/passes/minify-imports-and-exports_all-features.wast (renamed from test/passes/minify-imports-and-exports.wast)4
-rw-r--r--test/passes/minify-imports_all-features.txt (renamed from test/passes/minify-imports.txt)6
-rw-r--r--test/passes/minify-imports_all-features.wast (renamed from test/passes/minify-imports.wast)4
-rw-r--r--test/passes/remove-unused-module-elements_all-features.txt (renamed from test/passes/remove-unused-module-elements_enable-threads.txt)5
-rw-r--r--test/passes/remove-unused-module-elements_all-features.wast (renamed from test/passes/remove-unused-module-elements_enable-threads.wast)9
-rw-r--r--test/passes/remove-unused-nonfunction-module-elements_all-features.txt (renamed from test/passes/remove-unused-nonfunction-module-elements_enable-threads.txt)9
-rw-r--r--test/passes/remove-unused-nonfunction-module-elements_all-features.wast (renamed from test/passes/remove-unused-nonfunction-module-elements_enable-threads.wast)9
-rw-r--r--test/passes/translate-to-fuzz_all-features.txt770
-rw-r--r--test/passes/translate-to-fuzz_all-features.wast2
-rw-r--r--test/passes/translate-to-fuzz_no-fuzz-nans_all-features.txt783
-rw-r--r--test/passes/translate-to-fuzz_no-fuzz-nans_all-features.wast2
-rw-r--r--test/spec/events.wast43
60 files changed, 2011 insertions, 720 deletions
diff --git a/build-js.sh b/build-js.sh
index 71bed923e..832847f74 100755
--- a/build-js.sh
+++ b/build-js.sh
@@ -230,6 +230,7 @@ export_function "_BinaryenExternalFunction"
export_function "_BinaryenExternalTable"
export_function "_BinaryenExternalMemory"
export_function "_BinaryenExternalGlobal"
+export_function "_BinaryenExternalEvent"
# Features
export_function "_BinaryenFeatureMVP"
@@ -759,14 +760,19 @@ export_function "_BinaryenRemoveFunction"
export_function "_BinaryenAddGlobal"
export_function "_BinaryenGetGlobal"
export_function "_BinaryenRemoveGlobal"
+export_function "_BinaryenAddEvent"
+export_function "_BinaryenGetEvent"
+export_function "_BinaryenRemoveEvent"
export_function "_BinaryenAddFunctionImport"
export_function "_BinaryenAddTableImport"
export_function "_BinaryenAddMemoryImport"
export_function "_BinaryenAddGlobalImport"
+export_function "_BinaryenAddEventImport"
export_function "_BinaryenAddFunctionExport"
export_function "_BinaryenAddTableExport"
export_function "_BinaryenAddMemoryExport"
export_function "_BinaryenAddGlobalExport"
+export_function "_BinaryenAddEventExport"
export_function "_BinaryenRemoveExport"
export_function "_BinaryenSetFunctionTable"
export_function "_BinaryenSetMemory"
@@ -817,11 +823,20 @@ export_function "_BinaryenGlobalGetType"
export_function "_BinaryenGlobalIsMutable"
export_function "_BinaryenGlobalGetInitExpr"
+# 'Event' operations
+export_function "_BinaryenEventGetName"
+export_function "_BinaryenEventGetType"
+export_function "_BinaryenEventGetNumParams"
+export_function "_BinaryenEventGetParam"
+export_function "_BinaryenEventGetAttribute"
+
# 'Import' operations
export_function "_BinaryenGlobalImportGetModule"
export_function "_BinaryenGlobalImportGetBase"
export_function "_BinaryenFunctionImportGetModule"
export_function "_BinaryenFunctionImportGetBase"
+export_function "_BinaryenEventImportGetModule"
+export_function "_BinaryenEventImportGetBase"
# 'Export' operations
export_function "_BinaryenExportGetKind"
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index da3485843..2df1d478a 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -125,6 +125,7 @@ std::map<BinaryenFunctionTypeRef, size_t> functionTypes;
std::map<BinaryenExpressionRef, size_t> expressions;
std::map<BinaryenFunctionRef, size_t> functions;
std::map<BinaryenGlobalRef, size_t> globals;
+std::map<BinaryenEventRef, size_t> events;
std::map<BinaryenExportRef, size_t> exports;
std::map<RelooperBlockRef, size_t> relooperBlocks;
@@ -368,6 +369,9 @@ BinaryenExternalKind BinaryenExternalMemory(void) {
BinaryenExternalKind BinaryenExternalGlobal(void) {
return static_cast<BinaryenExternalKind>(ExternalKind::Global);
}
+BinaryenExternalKind BinaryenExternalEvent(void) {
+ return static_cast<BinaryenExternalKind>(ExternalKind::Event);
+}
// Features
@@ -417,12 +421,14 @@ void BinaryenModuleDispose(BinaryenModuleRef module) {
std::cout << " expressions.clear();\n";
std::cout << " functions.clear();\n";
std::cout << " globals.clear();\n";
+ std::cout << " events.clear();\n";
std::cout << " exports.clear();\n";
std::cout << " relooperBlocks.clear();\n";
functionTypes.clear();
expressions.clear();
functions.clear();
globals.clear();
+ events.clear();
exports.clear();
relooperBlocks.clear();
}
@@ -2775,6 +2781,45 @@ void BinaryenRemoveGlobal(BinaryenModuleRef module, const char* name) {
wasm->removeGlobal(name);
}
+// Events
+
+BinaryenEventRef BinaryenAddEvent(BinaryenModuleRef module,
+ const char* name,
+ uint32_t attribute,
+ BinaryenFunctionTypeRef type) {
+ if (tracing) {
+ std::cout << " BinaryenAddEvent(the_module, \"" << name << "\", "
+ << attribute << ", functionTypes[" << functionTypes[type]
+ << "]);\n";
+ }
+
+ auto* wasm = (Module*)module;
+ auto* ret = new Event();
+ ret->name = name;
+ ret->attribute = attribute;
+ ret->type = ((FunctionType*)type)->name;
+ ret->params = ((FunctionType*)type)->params;
+ wasm->addEvent(ret);
+ return ret;
+}
+
+BinaryenEventRef BinaryenGetEvent(BinaryenModuleRef module, const char* name) {
+ if (tracing) {
+ std::cout << " BinaryenGetEvent(the_module, \"" << name << "\");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ return wasm->getEvent(name);
+}
+void BinaryenRemoveEvent(BinaryenModuleRef module, const char* name) {
+ if (tracing) {
+ std::cout << " BinaryenRemoveEvent(the_module, \"" << name << "\");\n";
+ }
+
+ auto* wasm = (Module*)module;
+ wasm->removeEvent(name);
+}
+
// Imports
void BinaryenAddFunctionImport(BinaryenModuleRef module,
@@ -2850,6 +2895,29 @@ void BinaryenAddGlobalImport(BinaryenModuleRef module,
ret->type = Type(globalType);
wasm->addGlobal(ret);
}
+void BinaryenAddEventImport(BinaryenModuleRef module,
+ const char* internalName,
+ const char* externalModuleName,
+ const char* externalBaseName,
+ uint32_t attribute,
+ BinaryenFunctionTypeRef eventType) {
+ auto* wasm = (Module*)module;
+ auto* ret = new Event();
+
+ if (tracing) {
+ std::cout << " BinaryenAddEventImport(the_module, \"" << internalName
+ << "\", \"" << externalModuleName << "\", \"" << externalBaseName
+ << "\", " << attribute << ", functionTypes["
+ << functionTypes[eventType] << "]);\n";
+ }
+
+ ret->name = internalName;
+ ret->module = externalModuleName;
+ ret->base = externalBaseName;
+ ret->type = ((FunctionType*)eventType)->name;
+ ret->params = ((FunctionType*)eventType)->params;
+ wasm->addEvent(ret);
+}
// Exports
@@ -2938,6 +3006,26 @@ BinaryenExportRef BinaryenAddGlobalExport(BinaryenModuleRef module,
wasm->addExport(ret);
return ret;
}
+BinaryenExportRef BinaryenAddEventExport(BinaryenModuleRef module,
+ const char* internalName,
+ const char* externalName) {
+ auto* wasm = (Module*)module;
+ auto* ret = new Export();
+
+ if (tracing) {
+ auto id = exports.size();
+ exports[ret] = id;
+ std::cout << " exports[" << id
+ << "] = BinaryenAddEventExport(the_module, \"" << internalName
+ << "\", \"" << externalName << "\");\n";
+ }
+
+ ret->value = internalName;
+ ret->name = externalName;
+ ret->kind = ExternalKind::Event;
+ wasm->addExport(ret);
+ return ret;
+}
void BinaryenRemoveExport(BinaryenModuleRef module, const char* externalName) {
if (tracing) {
std::cout << " BinaryenRemoveExport(the_module, \"" << externalName
@@ -3655,6 +3743,52 @@ BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global) {
}
//
+// =========== Event operations ===========
+//
+
+const char* BinaryenEventGetName(BinaryenEventRef event) {
+ if (tracing) {
+ std::cout << " BinaryenEventGetName(events[" << events[event] << "]);\n";
+ }
+
+ return ((Event*)event)->name.c_str();
+}
+int BinaryenEventGetAttribute(BinaryenEventRef event) {
+ if (tracing) {
+ std::cout << " BinaryenEventGetAttribute(events[" << events[event]
+ << "]);\n";
+ }
+
+ return ((Event*)event)->attribute;
+}
+const char* BinaryenEventGetType(BinaryenEventRef event) {
+ if (tracing) {
+ std::cout << " BinaryenEventGetType(events[" << events[event] << "]);\n";
+ }
+
+ return ((Event*)event)->type.c_str();
+}
+BinaryenIndex BinaryenEventGetNumParams(BinaryenEventRef event) {
+ if (tracing) {
+ std::cout << " BinaryenEventGetNumParams(events[" << events[event]
+ << "]);\n";
+ }
+
+ return ((Event*)event)->params.size();
+}
+BinaryenType BinaryenEventGetParam(BinaryenEventRef event,
+ BinaryenIndex index) {
+ if (tracing) {
+ std::cout << " BinaryenEventGetParam(events[" << events[event] << "], "
+ << index << ");\n";
+ }
+
+ auto* fn = (Event*)event;
+ assert(index < fn->params.size());
+ return fn->params[index];
+}
+
+//
// =========== Import operations ===========
//
@@ -3684,6 +3818,19 @@ const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import) {
return "";
}
}
+const char* BinaryenEventImportGetModule(BinaryenEventRef import) {
+ if (tracing) {
+ std::cout << " BinaryenEventImportGetModule(events[" << events[import]
+ << "]);\n";
+ }
+
+ auto* event = (Event*)import;
+ if (event->imported()) {
+ return event->module.c_str();
+ } else {
+ return "";
+ }
+}
const char* BinaryenFunctionImportGetBase(BinaryenFunctionRef import) {
if (tracing) {
std::cout << " BinaryenFunctionImportGetBase(functions["
@@ -3710,6 +3857,19 @@ const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import) {
return "";
}
}
+const char* BinaryenEventImportGetBase(BinaryenEventRef import) {
+ if (tracing) {
+ std::cout << " BinaryenEventImportGetBase(events[" << events[import]
+ << "]);\n";
+ }
+
+ auto* event = (Event*)import;
+ if (event->imported()) {
+ return event->base.c_str();
+ } else {
+ return "";
+ }
+}
//
// =========== Export operations ===========
@@ -3875,6 +4035,7 @@ void BinaryenSetAPITracing(int on) {
" std::map<size_t, BinaryenExpressionRef> expressions;\n"
" std::map<size_t, BinaryenFunctionRef> functions;\n"
" std::map<size_t, BinaryenGlobalRef> globals;\n"
+ " std::map<size_t, BinaryenEventRef> events;\n"
" std::map<size_t, BinaryenExportRef> exports;\n"
" std::map<size_t, RelooperBlockRef> relooperBlocks;\n"
" BinaryenModuleRef the_module = NULL;\n"
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 879d78498..7b9b0141a 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -136,6 +136,7 @@ BinaryenExternalKind BinaryenExternalFunction(void);
BinaryenExternalKind BinaryenExternalTable(void);
BinaryenExternalKind BinaryenExternalMemory(void);
BinaryenExternalKind BinaryenExternalGlobal(void);
+BinaryenExternalKind BinaryenExternalEvent(void);
// Features. Call to get the value of each; you can cache them. Use bitwise
// operators to combine and test particular features.
@@ -882,6 +883,12 @@ void BinaryenAddGlobalImport(BinaryenModuleRef module,
const char* externalModuleName,
const char* externalBaseName,
BinaryenType globalType);
+void BinaryenAddEventImport(BinaryenModuleRef module,
+ const char* internalName,
+ const char* externalModuleName,
+ const char* externalBaseName,
+ uint32_t attribute,
+ BinaryenFunctionTypeRef eventType);
// Exports
@@ -902,6 +909,9 @@ BinaryenExportRef BinaryenAddMemoryExport(BinaryenModuleRef module,
BinaryenExportRef BinaryenAddGlobalExport(BinaryenModuleRef module,
const char* internalName,
const char* externalName);
+BinaryenExportRef BinaryenAddEventExport(BinaryenModuleRef module,
+ const char* internalName,
+ const char* externalName);
void BinaryenRemoveExport(BinaryenModuleRef module, const char* externalName);
// Globals
@@ -917,6 +927,17 @@ BinaryenGlobalRef BinaryenAddGlobal(BinaryenModuleRef module,
BinaryenGlobalRef BinaryenGetGlobal(BinaryenModuleRef module, const char* name);
void BinaryenRemoveGlobal(BinaryenModuleRef module, const char* name);
+// Events
+
+typedef void* BinaryenEventRef;
+
+BinaryenEventRef BinaryenAddEvent(BinaryenModuleRef module,
+ const char* name,
+ uint32_t attribute,
+ BinaryenFunctionTypeRef type);
+BinaryenEventRef BinaryenGetEvent(BinaryenModuleRef module, const char* name);
+void BinaryenEventEvent(BinaryenModuleRef module, const char* name);
+
// Function table. One per module
void BinaryenSetFunctionTable(BinaryenModuleRef module,
@@ -1153,6 +1174,21 @@ int BinaryenGlobalIsMutable(BinaryenGlobalRef global);
BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global);
//
+// ========== Event Operations ==========
+//
+
+// Gets the name of the specified `Event`.
+const char* BinaryenEventGetName(BinaryenEventRef event);
+// Gets the attribute of the specified `Event`.
+int BinaryenEventGetAttribute(BinaryenEventRef event);
+// Gets the name of the `FunctionType` associated with the specified `Event`.
+const char* BinaryenEventGetType(BinaryenEventRef event);
+// Gets the number of parameters of the specified `Event`.
+BinaryenIndex BinaryenEventGetNumParams(BinaryenEventRef event);
+// Gets the type of the parameter at the specified index of the specified
+// `Event`.
+BinaryenType BinaryenEventGetParam(BinaryenEventRef event, BinaryenIndex index);
+
//
// ========== Import Operations ==========
//
@@ -1160,9 +1196,11 @@ BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global);
// Gets the external module name of the specified import.
const char* BinaryenFunctionImportGetModule(BinaryenFunctionRef import);
const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import);
+const char* BinaryenEventImportGetModule(BinaryenEventRef import);
// Gets the external base name of the specified import.
const char* BinaryenFunctionImportGetBase(BinaryenFunctionRef import);
const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import);
+const char* BinaryenEventImportGetBase(BinaryenEventRef import);
//
// ========== Export Operations ==========
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 0bd8a7a0f..6723c5e4f 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -172,6 +172,7 @@ void ReFinalize::visitExport(Export* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitGlobal(Global* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitTable(Table* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE(); }
+void ReFinalize::visitEvent(Event* curr) { WASM_UNREACHABLE(); }
void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE(); }
void ReFinalize::updateBreakValueType(Name name, Type type) {
diff --git a/src/ir/import-utils.h b/src/ir/import-utils.h
index 950b9bfcb..3f3d27f1b 100644
--- a/src/ir/import-utils.h
+++ b/src/ir/import-utils.h
@@ -29,6 +29,7 @@ struct ImportInfo {
std::vector<Global*> importedGlobals;
std::vector<Function*> importedFunctions;
+ std::vector<Event*> importedEvents;
ImportInfo(Module& wasm) : wasm(wasm) {
for (auto& import : wasm.globals) {
@@ -41,6 +42,11 @@ struct ImportInfo {
importedFunctions.push_back(import.get());
}
}
+ for (auto& import : wasm.events) {
+ if (import->imported()) {
+ importedEvents.push_back(import.get());
+ }
+ }
}
Global* getImportedGlobal(Name module, Name base) {
@@ -61,13 +67,25 @@ struct ImportInfo {
return nullptr;
}
+ Event* getImportedEvent(Name module, Name base) {
+ for (auto* import : importedEvents) {
+ if (import->module == module && import->base == base) {
+ return import;
+ }
+ }
+ return nullptr;
+ }
+
Index getNumImportedGlobals() { return importedGlobals.size(); }
Index getNumImportedFunctions() { return importedFunctions.size(); }
+ Index getNumImportedEvents() { return importedEvents.size(); }
+
Index getNumImports() {
return getNumImportedGlobals() + getNumImportedFunctions() +
- (wasm.memory.imported() ? 1 : 0) + (wasm.table.imported() ? 1 : 0);
+ getNumImportedEvents() + (wasm.memory.imported() ? 1 : 0) +
+ (wasm.table.imported() ? 1 : 0);
}
Index getNumDefinedGlobals() {
@@ -77,6 +95,10 @@ struct ImportInfo {
Index getNumDefinedFunctions() {
return wasm.functions.size() - getNumImportedFunctions();
}
+
+ Index getNumDefinedEvents() {
+ return wasm.events.size() - getNumImportedEvents();
+ }
};
} // namespace wasm
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 5569843fd..067f59416 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -34,6 +34,7 @@ namespace ModuleUtils {
struct BinaryIndexes {
std::unordered_map<Name, Index> functionIndexes;
std::unordered_map<Name, Index> globalIndexes;
+ std::unordered_map<Name, Index> eventIndexes;
BinaryIndexes(Module& wasm) {
auto addGlobal = [&](Global* curr) {
@@ -66,6 +67,21 @@ struct BinaryIndexes {
}
}
assert(functionIndexes.size() == wasm.functions.size());
+ auto addEvent = [&](Event* curr) {
+ auto index = eventIndexes.size();
+ eventIndexes[curr->name] = index;
+ };
+ for (auto& curr : wasm.events) {
+ if (curr->imported()) {
+ addEvent(curr.get());
+ }
+ }
+ for (auto& curr : wasm.events) {
+ if (!curr->imported()) {
+ addEvent(curr.get());
+ }
+ }
+ assert(eventIndexes.size() == wasm.events.size());
}
};
@@ -105,6 +121,16 @@ inline Global* copyGlobal(Global* global, Module& out) {
return ret;
}
+inline Event* copyEvent(Event* event, Module& out) {
+ auto* ret = new Event();
+ ret->name = event->name;
+ ret->attribute = event->attribute;
+ ret->type = event->type;
+ ret->params = event->params;
+ out.addEvent(ret);
+ return ret;
+}
+
inline void copyModule(Module& in, Module& out) {
// we use names throughout, not raw points, so simple copying is fine
// for everything *but* expressions
@@ -120,6 +146,9 @@ inline void copyModule(Module& in, Module& out) {
for (auto& curr : in.globals) {
copyGlobal(curr.get(), out);
}
+ for (auto& curr : in.events) {
+ copyEvent(curr.get(), out);
+ }
out.table = in.table;
for (auto& segment : out.table.segments) {
segment.offset = ExpressionManipulator::copy(segment.offset, out);
@@ -243,6 +272,22 @@ template<typename T> inline void iterDefinedFunctions(Module& wasm, T visitor) {
}
}
+template<typename T> inline void iterImportedEvents(Module& wasm, T visitor) {
+ for (auto& import : wasm.events) {
+ if (import->imported()) {
+ visitor(import.get());
+ }
+ }
+}
+
+template<typename T> inline void iterDefinedEvents(Module& wasm, T visitor) {
+ for (auto& import : wasm.events) {
+ if (!import->imported()) {
+ visitor(import.get());
+ }
+ }
+}
+
} // namespace ModuleUtils
} // namespace wasm
diff --git a/src/ir/utils.h b/src/ir/utils.h
index a8af3ed18..b8e8fe815 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -154,6 +154,7 @@ struct ReFinalize
void visitGlobal(Global* curr);
void visitTable(Table* curr);
void visitMemory(Memory* curr);
+ void visitEvent(Event* curr);
void visitModule(Module* curr);
private:
@@ -208,6 +209,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitGlobal(Global* curr) { WASM_UNREACHABLE(); }
void visitTable(Table* curr) { WASM_UNREACHABLE(); }
void visitMemory(Memory* curr) { WASM_UNREACHABLE(); }
+ void visitEvent(Event* curr) { WASM_UNREACHABLE(); }
void visitModule(Module* curr) { WASM_UNREACHABLE(); }
// given a stack of nested expressions, update them all from child to parent
diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js
index 180d08bb5..d2703e425 100644
--- a/src/js/binaryen.js-post.js
+++ b/src/js/binaryen.js-post.js
@@ -84,6 +84,7 @@ Module['ExternalFunction'] = Module['_BinaryenExternalFunction']();
Module['ExternalTable'] = Module['_BinaryenExternalTable']();
Module['ExternalMemory'] = Module['_BinaryenExternalMemory']();
Module['ExternalGlobal'] = Module['_BinaryenExternalGlobal']();
+Module['ExternalEvent'] = Module['_BinaryenExternalEvent']();
// Features
Module['Features'] = {
@@ -1788,6 +1789,21 @@ function wrapModule(module, self) {
return Module['_BinaryenRemoveGlobal'](module, strToStack(name));
});
}
+ self['addEvent'] = function(name, attribute, eventType) {
+ return preserveStack(function() {
+ return Module['_BinaryenAddEvent'](module, strToStack(name), attribute, eventType);
+ });
+ };
+ self['getEvent'] = function(name) {
+ return preserveStack(function() {
+ return Module['_BinaryenGetEvent'](module, strToStack(name));
+ });
+ };
+ self['removeEvent'] = function(name) {
+ return preserveStack(function() {
+ return Module['_BinaryenRemoveEvent'](module, strToStack(name));
+ });
+ };
self['addFunctionImport'] = function(internalName, externalModuleName, externalBaseName, functionType) {
return preserveStack(function() {
return Module['_BinaryenAddFunctionImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), functionType);
@@ -1808,6 +1824,11 @@ function wrapModule(module, self) {
return Module['_BinaryenAddGlobalImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), globalType);
});
};
+ self['addEventImport'] = function(internalName, externalModuleName, externalBaseName, attribute, eventType) {
+ return preserveStack(function() {
+ return Module['_BinaryenAddEventImport'](module, strToStack(internalName), strToStack(externalModuleName), strToStack(externalBaseName), attribute, eventType);
+ });
+ };
self['addExport'] = // deprecated
self['addFunctionExport'] = function(internalName, externalName) {
return preserveStack(function() {
@@ -1829,6 +1850,11 @@ function wrapModule(module, self) {
return Module['_BinaryenAddGlobalExport'](module, strToStack(internalName), strToStack(externalName));
});
};
+ self['addEventExport'] = function(internalName, externalName) {
+ return preserveStack(function() {
+ return Module['_BinaryenAddEventExport'](module, strToStack(internalName), strToStack(externalName));
+ });
+ };
self['removeExport'] = function(externalName) {
return preserveStack(function() {
return Module['_BinaryenRemoveExport'](module, strToStack(externalName));
@@ -2354,6 +2380,17 @@ Module['getGlobalInfo'] = function(global) {
};
};
+// Obtains information about a 'Event'
+Module['getEventInfo'] = function(event_) {
+ return {
+ 'name': UTF8ToString(Module['_BinaryenEventGetName'](event_)),
+ 'module': UTF8ToString(Module['_BinaryenEventImportGetModule'](event_)),
+ 'base': UTF8ToString(Module['_BinaryenEventImportGetBase'](event_)),
+ 'attribute': Module['_BinaryenEventGetAttribute'](event_),
+ 'type': UTF8ToString(Module['_BinaryenEventGetType'](event_))
+ };
+};
+
// Obtains information about an 'Export'
Module['getExportInfo'] = function(export_) {
return {
diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp
index af5a62697..a408ccf95 100644
--- a/src/passes/Metrics.cpp
+++ b/src/passes/Metrics.cpp
@@ -66,6 +66,7 @@ struct Metrics
counts["[imports]"] = imports.getNumImports();
counts["[funcs]"] = imports.getNumDefinedFunctions();
counts["[globals]"] = imports.getNumDefinedGlobals();
+ counts["[events]"] = imports.getNumDefinedEvents();
counts["[exports]"] = module->exports.size();
// add memory and table
if (module->memory.exists) {
diff --git a/src/passes/MinifyImportsAndExports.cpp b/src/passes/MinifyImportsAndExports.cpp
index 23dd2a21a..043cfb588 100644
--- a/src/passes/MinifyImportsAndExports.cpp
+++ b/src/passes/MinifyImportsAndExports.cpp
@@ -159,6 +159,7 @@ private:
};
ModuleUtils::iterImportedGlobals(*module, processImport);
ModuleUtils::iterImportedFunctions(*module, processImport);
+ ModuleUtils::iterImportedEvents(*module, processImport);
if (minifyExports) {
// Minify the exported names.
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index fb85023f0..9dbf3cc1f 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1660,6 +1660,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
case ExternalKind::Global:
o << "global";
break;
+ case ExternalKind::Event:
+ o << "event";
+ break;
case ExternalKind::Invalid:
WASM_UNREACHABLE();
}
@@ -1805,6 +1808,25 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
}
o << maybeNewLine;
}
+ void visitEvent(Event* curr) {
+ doIndent(o, indent);
+ if (curr->imported()) {
+ o << '(';
+ emitImportHeader(curr);
+ }
+ o << "(event ";
+ printName(curr->name, o);
+ o << maybeSpace << "(attr " << curr->attribute << ')' << maybeSpace << '(';
+ printMinor(o, "param");
+ for (auto& param : curr->params) {
+ o << ' ' << printType(param);
+ }
+ o << "))";
+ if (curr->imported()) {
+ o << ')';
+ }
+ o << maybeNewLine;
+ }
void printTableHeader(Table* curr) {
o << '(';
printMedium(o, "table") << ' ';
@@ -1948,12 +1970,16 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
*curr, [&](Global* global) { visitGlobal(global); });
ModuleUtils::iterImportedFunctions(
*curr, [&](Function* func) { visitFunction(func); });
+ ModuleUtils::iterImportedEvents(*curr,
+ [&](Event* event) { visitEvent(event); });
ModuleUtils::iterDefinedMemories(
*curr, [&](Memory* memory) { visitMemory(memory); });
ModuleUtils::iterDefinedTables(*curr,
[&](Table* table) { visitTable(table); });
ModuleUtils::iterDefinedGlobals(
*curr, [&](Global* global) { visitGlobal(global); });
+ ModuleUtils::iterDefinedEvents(*curr,
+ [&](Event* event) { visitEvent(event); });
for (auto& child : curr->exports) {
doIndent(o, indent);
visitExport(child.get());
diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp
index c96ce1a8c..20c30d271 100644
--- a/src/passes/RemoveUnusedModuleElements.cpp
+++ b/src/passes/RemoveUnusedModuleElements.cpp
@@ -15,9 +15,9 @@
*/
//
-// Removes module elements that are are never used: functions and globals,
-// which may be imported or not, and function types (which we merge
-// and remove if unneeded)
+// Removes module elements that are are never used: functions, globals, and
+// events, which may be imported or not, and function types (which we merge and
+// remove if unneeded)
//
#include <memory>
@@ -30,7 +30,7 @@
namespace wasm {
-enum class ModuleElementKind { Function, Global };
+enum class ModuleElementKind { Function, Global, Event };
typedef std::pair<ModuleElementKind, Name> ModuleElement;
@@ -68,7 +68,7 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> {
if (!func->imported()) {
walk(func->body);
}
- } else {
+ } else if (curr.first == ModuleElementKind::Global) {
// if not imported, it has an init expression we need to walk
auto* global = module->getGlobal(curr.second);
if (!global->imported()) {
@@ -122,6 +122,7 @@ struct ReachabilityAnalyzer : public PostWalker<ReachabilityAnalyzer> {
struct FunctionTypeAnalyzer : public PostWalker<FunctionTypeAnalyzer> {
std::vector<Function*> functions;
std::vector<CallIndirect*> indirectCalls;
+ std::vector<Event*> events;
void visitFunction(Function* curr) {
if (curr->type.is()) {
@@ -129,6 +130,8 @@ struct FunctionTypeAnalyzer : public PostWalker<FunctionTypeAnalyzer> {
}
}
+ void visitEvent(Event* curr) { events.push_back(curr); }
+
void visitCallIndirect(CallIndirect* curr) { indirectCalls.push_back(curr); }
};
@@ -139,11 +142,11 @@ struct RemoveUnusedModuleElements : public Pass {
: rootAllFunctions(rootAllFunctions) {}
void run(PassRunner* runner, Module* module) override {
- optimizeGlobalsAndFunctions(module);
+ optimizeGlobalsAndFunctionsAndEvents(module);
optimizeFunctionTypes(module);
}
- void optimizeGlobalsAndFunctions(Module* module) {
+ void optimizeGlobalsAndFunctionsAndEvents(Module* module) {
std::vector<ModuleElement> roots;
// Module start is a root.
if (module->start.is()) {
@@ -169,6 +172,8 @@ struct RemoveUnusedModuleElements : public Pass {
roots.emplace_back(ModuleElementKind::Function, curr->value);
} else if (curr->kind == ExternalKind::Global) {
roots.emplace_back(ModuleElementKind::Global, curr->value);
+ } else if (curr->kind == ExternalKind::Event) {
+ roots.emplace_back(ModuleElementKind::Event, curr->value);
} else if (curr->kind == ExternalKind::Memory) {
exportsMemory = true;
} else if (curr->kind == ExternalKind::Table) {
@@ -215,6 +220,17 @@ struct RemoveUnusedModuleElements : public Pass {
}),
v.end());
}
+ {
+ auto& v = module->events;
+ v.erase(std::remove_if(v.begin(),
+ v.end(),
+ [&](const std::unique_ptr<Event>& curr) {
+ return analyzer.reachable.count(
+ ModuleElement(ModuleElementKind::Event,
+ curr->name)) == 0;
+ }),
+ v.end());
+ }
module->updateMaps();
// Handle the memory and table
if (!exportsMemory && !analyzer.usesMemory) {
@@ -272,6 +288,9 @@ struct RemoveUnusedModuleElements : public Pass {
for (auto* call : analyzer.indirectCalls) {
call->fullType = canonicalize(call->fullType);
}
+ for (auto* event : analyzer.events) {
+ event->type = canonicalize(event->type);
+ }
// remove no-longer used types
module->functionTypes.erase(
std::remove_if(module->functionTypes.begin(),
diff --git a/src/shared-constants.h b/src/shared-constants.h
index 9e119dc95..9fb84dbf8 100644
--- a/src/shared-constants.h
+++ b/src/shared-constants.h
@@ -62,6 +62,8 @@ extern Name SPECTEST;
extern Name PRINT;
extern Name EXIT;
extern Name SHARED;
+extern Name EVENT;
+extern Name ATTR;
} // namespace wasm
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index f7dd20e76..0a7128e3e 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -197,6 +197,9 @@ public:
}
setupTable();
setupGlobals();
+ if (wasm.features.hasExceptionHandling()) {
+ setupEvents();
+ }
addImportLoggingSupport();
// keep adding functions until we run out of input
while (!finishedInput) {
@@ -397,6 +400,28 @@ private:
}
}
+ void setupEvents() {
+ Index num = upTo(3);
+ for (size_t i = 0; i < num; i++) {
+ // Events should have void return type and at least one param type
+ Type type = pick(i32, i64, f32, f64);
+ std::string sig = std::string("v") + getSig(type);
+ std::vector<Type> params;
+ params.push_back(type);
+ Index numValues = upToSquared(MAX_PARAMS - 1);
+ for (Index i = 0; i < numValues; i++) {
+ type = pick(i32, i64, f32, f64);
+ sig += getSig(type);
+ params.push_back(type);
+ }
+ auto* event = builder.makeEvent(std::string("event$") + std::to_string(i),
+ WASM_EVENT_ATTRIBUTE_EXCEPTION,
+ ensureFunctionType(sig, &wasm)->name,
+ std::move(params));
+ wasm.addEvent(event);
+ }
+ }
+
void finalizeTable() {
wasm.table.initial = wasm.table.segments[0].data.size();
wasm.table.max =
diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp
index c04286f59..96b368bc4 100644
--- a/src/tools/wasm-metadce.cpp
+++ b/src/tools/wasm-metadce.cpp
@@ -55,10 +55,12 @@ struct MetaDCEGraph {
std::unordered_map<Name, Name> exportToDCENode;
std::unordered_map<Name, Name> functionToDCENode; // function name => DCE name
std::unordered_map<Name, Name> globalToDCENode; // global name => DCE name
+ std::unordered_map<Name, Name> eventToDCENode; // event name => DCE name
std::unordered_map<Name, Name> DCENodeToExport; // reverse maps
std::unordered_map<Name, Name> DCENodeToFunction;
std::unordered_map<Name, Name> DCENodeToGlobal;
+ std::unordered_map<Name, Name> DCENodeToEvent;
// imports are not mapped 1:1 to DCE nodes in the wasm, since env.X might
// be imported twice, for example. So we don't map a DCE node to an Import,
@@ -80,6 +82,11 @@ struct MetaDCEGraph {
return getImportId(imp->module, imp->base);
}
+ ImportId getEventImportId(Name name) {
+ auto* imp = wasm.getEvent(name);
+ return getImportId(imp->module, imp->base);
+ }
+
// import module.base => DCE name
std::unordered_map<Name, Name> importIdToDCENode;
@@ -106,8 +113,14 @@ struct MetaDCEGraph {
globalToDCENode[global->name] = dceName;
nodes[dceName] = DCENode(dceName);
});
- // only process function and global imports - the table and memory are
- // always there
+ ModuleUtils::iterDefinedEvents(wasm, [&](Event* event) {
+ auto dceName = getName("event", event->name.str);
+ DCENodeToEvent[dceName] = event->name;
+ eventToDCENode[event->name] = dceName;
+ nodes[dceName] = DCENode(dceName);
+ });
+ // only process function, global, and event imports - the table and memory
+ // are always there
ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
auto id = getImportId(import->module, import->base);
if (importIdToDCENode.find(id) == importIdToDCENode.end()) {
@@ -122,6 +135,13 @@ struct MetaDCEGraph {
importIdToDCENode[id] = dceName;
}
});
+ ModuleUtils::iterImportedEvents(wasm, [&](Event* import) {
+ auto id = getImportId(import->module, import->base);
+ if (importIdToDCENode.find(id) == importIdToDCENode.end()) {
+ auto dceName = getName("importId", import->name.str);
+ importIdToDCENode[id] = dceName;
+ }
+ });
for (auto& exp : wasm.exports) {
if (exportToDCENode.find(exp->name) == exportToDCENode.end()) {
auto dceName = getName("export", exp->name.str);
@@ -145,6 +165,13 @@ struct MetaDCEGraph {
node.reaches.push_back(
importIdToDCENode[getGlobalImportId(exp->value)]);
}
+ } else if (exp->kind == ExternalKind::Event) {
+ if (!wasm.getEvent(exp->value)->imported()) {
+ node.reaches.push_back(eventToDCENode[exp->value]);
+ } else {
+ node.reaches.push_back(
+ importIdToDCENode[getEventImportId(exp->value)]);
+ }
}
}
// Add initializer dependencies
@@ -355,6 +382,9 @@ public:
if (DCENodeToGlobal.find(name) != DCENodeToGlobal.end()) {
std::cout << " is global " << DCENodeToGlobal[name] << '\n';
}
+ if (DCENodeToEvent.find(name) != DCENodeToEvent.end()) {
+ std::cout << " is event " << DCENodeToEvent[name] << '\n';
+ }
for (auto target : node.reaches) {
std::cout << " reaches: " << target.str << '\n';
}
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index ce3144715..e2323967e 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -363,6 +363,7 @@ enum Section {
Code = 10,
Data = 11,
DataCount = 12,
+ Event = 13
};
enum SegmentFlag {
@@ -948,13 +949,18 @@ public:
void writeExports();
void writeDataCount();
void writeDataSegments();
+ void writeEvents();
// name of the Function => index. first imports, then internals
std::unordered_map<Name, Index> mappedFunctions;
// name of the Global => index. first imported globals, then internal globals
std::unordered_map<Name, uint32_t> mappedGlobals;
+ // name of the Event => index. first imported events, then internal events
+ std::unordered_map<Name, uint32_t> mappedEvents;
+
uint32_t getFunctionIndex(Name name);
uint32_t getGlobalIndex(Name name);
+ uint32_t getEventIndex(Name name);
void writeFunctionTableDeclaration();
void writeTableElements();
@@ -1071,6 +1077,7 @@ public:
// gets a name in the combined import+defined space
Name getFunctionName(Index index);
Name getGlobalName(Index index);
+ Name getEventName(Index index);
void getResizableLimits(Address& initial,
Address& max,
@@ -1165,6 +1172,9 @@ public:
void readFunctionTableDeclaration();
void readTableElements();
+
+ void readEvents();
+
void readNames(size_t);
void readFeatures(size_t);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 0b7326b6e..284608105 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -683,6 +683,19 @@ public:
glob->mutable_ = mutable_ == Mutable;
return glob;
}
+
+ // TODO Remove 'type' parameter once we remove FunctionType
+ static Event* makeEvent(Name name,
+ uint32_t attribute,
+ Name type,
+ std::vector<Type>&& params) {
+ auto* event = new Event;
+ event->name = name;
+ event->attribute = attribute;
+ event->type = type;
+ event->params = params;
+ return event;
+ }
};
} // namespace wasm
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index d501a349a..71249748e 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -113,8 +113,10 @@ class SExpressionWasmBuilder {
MixedArena& allocator;
std::vector<Name> functionNames;
std::vector<Name> globalNames;
- int functionCounter;
+ std::vector<Name> eventNames;
+ int functionCounter = 0;
int globalCounter = 0;
+ int eventCounter = 0;
// we need to know function return types before we parse their contents
std::map<Name, Type> functionTypes;
std::unordered_map<cashew::IString, Index> debugInfoFileIndices;
@@ -142,6 +144,7 @@ private:
Name getFunctionName(Element& s);
Name getFunctionTypeName(Element& s);
Name getGlobalName(Element& s);
+ Name getEventName(Element& s);
void parseStart(Element& s) { wasm.addStart(getFunctionName(*s[1])); }
// returns the next index in s
@@ -247,6 +250,7 @@ private:
void parseElem(Element& s);
void parseInnerElem(Element& s, Index i = 1, Expression* offset = nullptr);
void parseType(Element& s);
+ void parseEvent(Element& s, bool preParseImport = false);
Function::DebugLocation getDebugLocation(const SourceLocation& loc);
};
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index 73f57a538..f1306721e 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -79,6 +79,7 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
ReturnType visitFunction(Function* curr) { return ReturnType(); }
ReturnType visitTable(Table* curr) { return ReturnType(); }
ReturnType visitMemory(Memory* curr) { return ReturnType(); }
+ ReturnType visitEvent(Event* curr) { return ReturnType(); }
ReturnType visitModule(Module* curr) { return ReturnType(); }
ReturnType visit(Expression* curr) {
@@ -223,6 +224,7 @@ struct OverriddenVisitor {
UNIMPLEMENTED(Function);
UNIMPLEMENTED(Table);
UNIMPLEMENTED(Memory);
+ UNIMPLEMENTED(Event);
UNIMPLEMENTED(Module);
#undef UNIMPLEMENTED
@@ -486,6 +488,10 @@ struct Walker : public VisitorType {
setFunction(nullptr);
}
+ void walkEvent(Event* event) {
+ static_cast<SubType*>(this)->visitEvent(event);
+ }
+
void walkFunctionInModule(Function* func, Module* module) {
setModule(module);
setFunction(func);
@@ -545,6 +551,13 @@ struct Walker : public VisitorType {
self->walkFunction(curr.get());
}
}
+ for (auto& curr : module->events) {
+ if (curr->imported()) {
+ self->visitEvent(curr.get());
+ } else {
+ self->walkEvent(curr.get());
+ }
+ }
self->walkTable(&module->table);
self->walkMemory(&module->memory);
}
diff --git a/src/wasm.h b/src/wasm.h
index d4ffe86f2..de3289289 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1063,6 +1063,7 @@ enum class ExternalKind {
Table = 1,
Memory = 2,
Global = 3,
+ Event = 4,
Invalid = -1
};
@@ -1156,6 +1157,24 @@ public:
bool mutable_ = false;
};
+// Kinds of event attributes.
+enum WasmEventAttribute : unsigned { WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0 };
+
+class Event : public Importable {
+public:
+ Name name;
+ // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible.
+ uint32_t attribute;
+ // Type string in the format of function type. Return type is considered as a
+ // void type. So if you have an event whose type is (i32, i32), the type
+ // string will be "vii".
+ Name type;
+ // This is duplicate info of 'Name type', but we store this anyway because
+ // we plan to remove FunctionType in future.
+ // TODO remove either this or FunctionType
+ std::vector<Type> params;
+};
+
// "Opaque" data, not part of the core wasm spec, that is held in binaries.
// May be parsed/handled by utility code elsewhere, but not in wasm.h
class UserSection {
@@ -1172,6 +1191,7 @@ public:
std::vector<std::unique_ptr<Export>> exports;
std::vector<std::unique_ptr<Function>> functions;
std::vector<std::unique_ptr<Global>> globals;
+ std::vector<std::unique_ptr<Event>> events;
Table table;
Memory memory;
@@ -1197,6 +1217,7 @@ private:
std::map<Name, Export*> exportsMap;
std::map<Name, Function*> functionsMap;
std::map<Name, Global*> globalsMap;
+ std::map<Name, Event*> eventsMap;
public:
Module() = default;
@@ -1205,17 +1226,20 @@ public:
Export* getExport(Name name);
Function* getFunction(Name name);
Global* getGlobal(Name name);
+ Event* getEvent(Name name);
FunctionType* getFunctionTypeOrNull(Name name);
Export* getExportOrNull(Name name);
Function* getFunctionOrNull(Name name);
Global* getGlobalOrNull(Name name);
+ Event* getEventOrNull(Name name);
FunctionType* addFunctionType(std::unique_ptr<FunctionType> curr);
Export* addExport(Export* curr);
Function* addFunction(Function* curr);
Function* addFunction(std::unique_ptr<Function> curr);
Global* addGlobal(Global* curr);
+ Event* addEvent(Event* curr);
void addStart(const Name& s);
@@ -1223,6 +1247,7 @@ public:
void removeExport(Name name);
void removeFunction(Name name);
void removeGlobal(Name name);
+ void removeEvent(Name name);
void updateMaps();
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index d8ce18de5..91a2184e9 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -37,6 +37,7 @@ void WasmBinaryWriter::prepare() {
ModuleUtils::BinaryIndexes indexes(*wasm);
mappedFunctions = std::move(indexes.functionIndexes);
mappedGlobals = std::move(indexes.globalIndexes);
+ mappedEvents = std::move(indexes.eventIndexes);
importInfo = wasm::make_unique<ImportInfo>(*wasm);
}
@@ -63,6 +64,7 @@ void WasmBinaryWriter::write() {
writeDataCount();
writeFunctions();
writeDataSegments();
+ writeEvents();
if (debugInfo) {
writeNames();
}
@@ -245,6 +247,15 @@ void WasmBinaryWriter::writeImports() {
o << binaryType(global->type);
o << U32LEB(global->mutable_);
});
+ ModuleUtils::iterImportedEvents(*wasm, [&](Event* event) {
+ if (debug) {
+ std::cerr << "write one event" << std::endl;
+ }
+ writeImportHeader(event);
+ o << U32LEB(int32_t(ExternalKind::Event));
+ o << U32LEB(event->attribute);
+ o << U32LEB(getFunctionTypeIndex(event->type));
+ });
if (wasm->memory.imported()) {
if (debug) {
std::cerr << "write one memory" << std::endl;
@@ -401,6 +412,9 @@ void WasmBinaryWriter::writeExports() {
case ExternalKind::Global:
o << U32LEB(getGlobalIndex(curr->value));
break;
+ case ExternalKind::Event:
+ o << U32LEB(getEventIndex(curr->value));
+ break;
default:
WASM_UNREACHABLE();
}
@@ -453,6 +467,11 @@ uint32_t WasmBinaryWriter::getGlobalIndex(Name name) {
return mappedGlobals[name];
}
+uint32_t WasmBinaryWriter::getEventIndex(Name name) {
+ assert(mappedEvents.count(name));
+ return mappedEvents[name];
+}
+
void WasmBinaryWriter::writeFunctionTableDeclaration() {
if (!wasm->table.exists || wasm->table.imported()) {
return;
@@ -493,6 +512,27 @@ void WasmBinaryWriter::writeTableElements() {
finishSection(start);
}
+void WasmBinaryWriter::writeEvents() {
+ if (importInfo->getNumDefinedEvents() == 0) {
+ return;
+ }
+ if (debug) {
+ std::cerr << "== writeEvents" << std::endl;
+ }
+ auto start = startSection(BinaryConsts::Section::Event);
+ auto num = importInfo->getNumDefinedEvents();
+ o << U32LEB(num);
+ ModuleUtils::iterDefinedEvents(*wasm, [&](Event* event) {
+ if (debug) {
+ std::cerr << "write one" << std::endl;
+ }
+ o << U32LEB(event->attribute);
+ o << U32LEB(getFunctionTypeIndex(event->type));
+ });
+
+ finishSection(start);
+}
+
void WasmBinaryWriter::writeNames() {
bool hasContents = false;
if (wasm->functions.size() > 0) {
@@ -828,6 +868,9 @@ void WasmBinaryBuilder::read() {
case BinaryConsts::Section::Table:
readFunctionTableDeclaration();
break;
+ case BinaryConsts::Section::Event:
+ readEvents();
+ break;
default: {
readUserSection(payloadLen);
if (pos > oldPos + payloadLen) {
@@ -1210,6 +1253,13 @@ Name WasmBinaryBuilder::getGlobalName(Index index) {
return wasm.globals[index]->name;
}
+Name WasmBinaryBuilder::getEventName(Index index) {
+ if (index >= wasm.events.size()) {
+ throwError("invalid event index");
+ }
+ return wasm.events[index]->name;
+}
+
void WasmBinaryBuilder::getResizableLimits(Address& initial,
Address& max,
bool& shared,
@@ -1310,6 +1360,23 @@ void WasmBinaryBuilder::readImports() {
wasm.addGlobal(curr);
break;
}
+ case ExternalKind::Event: {
+ auto name = Name(std::string("eimport$") + std::to_string(i));
+ auto attribute = getU32LEB();
+ auto index = getU32LEB();
+ if (index >= wasm.functionTypes.size()) {
+ throwError("invalid event index " + std::to_string(index) + " / " +
+ std::to_string(wasm.functionTypes.size()));
+ }
+ Name type = wasm.functionTypes[index]->name;
+ std::vector<Type> params = wasm.functionTypes[index]->params;
+ auto* curr =
+ builder.makeEvent(name, attribute, type, std::move(params));
+ curr->module = module;
+ curr->base = base;
+ wasm.addEvent(curr);
+ break;
+ }
default: { throwError("bad import kind"); }
}
}
@@ -1841,6 +1908,9 @@ void WasmBinaryBuilder::processFunctions() {
case ExternalKind::Global:
curr->value = getGlobalName(index);
break;
+ case ExternalKind::Event:
+ curr->value = getEventName(index);
+ break;
default:
throwError("bad export kind");
}
@@ -1954,6 +2024,31 @@ void WasmBinaryBuilder::readTableElements() {
}
}
+void WasmBinaryBuilder::readEvents() {
+ if (debug) {
+ std::cerr << "== readEvents" << std::endl;
+ }
+ size_t numEvents = getU32LEB();
+ if (debug) {
+ std::cerr << "num: " << numEvents << std::endl;
+ }
+ for (size_t i = 0; i < numEvents; i++) {
+ if (debug) {
+ std::cerr << "read one" << std::endl;
+ }
+ auto attribute = getU32LEB();
+ auto typeIndex = getU32LEB();
+ if (typeIndex >= wasm.functionTypes.size()) {
+ throwError("invalid event index " + std::to_string(typeIndex) + " / " +
+ std::to_string(wasm.functionTypes.size()));
+ }
+ Name type = wasm.functionTypes[typeIndex]->name;
+ std::vector<Type> params = wasm.functionTypes[typeIndex]->params;
+ wasm.addEvent(Builder::makeEvent(
+ "event$" + std::to_string(i), attribute, type, std::move(params)));
+ }
+}
+
static bool isIdChar(char ch) {
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') || ch == '!' || ch == '#' || ch == '$' ||
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 3a5dfbced..8ead42608 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -388,6 +388,8 @@ void SExpressionWasmBuilder::preParseImports(Element& curr) {
parseTable(curr, true /* preParseImport */);
} else if (id == MEMORY) {
parseMemory(curr, true /* preParseImport */);
+ } else if (id == EVENT) {
+ parseEvent(curr, true /* preParseImport */);
} else {
throw ParseException(
"fancy import we don't support yet", curr.line, curr.col);
@@ -430,6 +432,9 @@ void SExpressionWasmBuilder::parseModuleElement(Element& curr) {
if (id == TYPE) {
return; // already done
}
+ if (id == EVENT) {
+ return parseEvent(curr);
+ }
std::cerr << "bad module element " << id.str << '\n';
throw ParseException("unknown module element", curr.line, curr.col);
}
@@ -473,6 +478,19 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) {
}
}
+Name SExpressionWasmBuilder::getEventName(Element& s) {
+ if (s.dollared()) {
+ return s.str();
+ } else {
+ // index
+ size_t offset = atoi(s.str().c_str());
+ if (offset >= eventNames.size()) {
+ throw ParseException("unknown event in getEventName");
+ }
+ return eventNames[offset];
+ }
+}
+
// Parse various forms of (param ...) or (local ...) element. This ignores all
// parameter or local names when specified.
std::vector<Type> SExpressionWasmBuilder::parseParamOrLocal(Element& s) {
@@ -1877,6 +1895,8 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
ex->kind = ExternalKind::Table;
} else if (elementStartsWith(inner, GLOBAL)) {
ex->kind = ExternalKind::Global;
+ } else if (inner[0]->str() == EVENT) {
+ ex->kind = ExternalKind::Event;
} else {
throw ParseException("invalid export");
}
@@ -1913,6 +1933,8 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.table.exists = true;
} else if (elementStartsWith(*s[3], GLOBAL)) {
kind = ExternalKind::Global;
+ } else if ((*s[3])[0]->str() == EVENT) {
+ kind = ExternalKind::Event;
} else {
newStyle = false; // either (param..) or (result..)
}
@@ -1936,6 +1958,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
name = Name("import$memory$" + std::to_string(0));
} else if (kind == ExternalKind::Table) {
name = Name("import$table$" + std::to_string(0));
+ } else if (kind == ExternalKind::Event) {
+ name = Name("import$event" + std::to_string(eventCounter++));
+ eventNames.push_back(name);
} else {
throw ParseException("invalid import");
}
@@ -1957,7 +1982,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
if (kind == ExternalKind::Function) {
FunctionType* functionType = nullptr;
auto func = make_unique<Function>();
- parseTypeUse(inner, j, functionType, func->params, func->result);
+ j = parseTypeUse(inner, j, functionType, func->params, func->result);
func->name = name;
func->module = module;
func->base = base;
@@ -1968,9 +1993,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
Type type;
bool mutable_ = false;
if (inner[j]->isStr()) {
- type = stringToType(inner[j]->str());
+ type = stringToType(inner[j++]->str());
} else {
- auto& inner2 = *inner[j];
+ auto& inner2 = *inner[j++];
if (inner2[0]->str() != MUT) {
throw ParseException("expected mut");
}
@@ -1997,6 +2022,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
} else {
wasm.table.max = Table::kUnlimitedSize;
}
+ j++; // funcref
// ends with the table element type
} else if (kind == ExternalKind::Memory) {
wasm.memory.module = module;
@@ -2007,10 +2033,32 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
throw ParseException("bad memory limit declaration");
}
wasm.memory.shared = true;
- parseMemoryLimits(limits, 1);
+ j = parseMemoryLimits(limits, 1);
} else {
- parseMemoryLimits(inner, j);
+ j = parseMemoryLimits(inner, j);
+ }
+ } else if (kind == ExternalKind::Event) {
+ FunctionType* functionType = nullptr;
+ auto event = make_unique<Event>();
+ if (j >= inner.size()) {
+ throw ParseException("event does not have an attribute", s.line, s.col);
+ }
+ auto& attrElem = *inner[j++];
+ if (!elementStartsWith(attrElem, ATTR) || attrElem.size() != 2) {
+ throw ParseException("invalid attribute", attrElem.line, attrElem.col);
}
+ event->attribute = atoi(attrElem[1]->c_str());
+ Type fakeResult; // just to call parseTypeUse
+ j = parseTypeUse(inner, j, functionType, event->params, fakeResult);
+ event->name = name;
+ event->module = module;
+ event->base = base;
+ event->type = functionType->name;
+ wasm.addEvent(event.release());
+ }
+ // If there are more elements, they are invalid
+ if (j < inner.size()) {
+ throw ParseException("invalid element", inner[j]->line, inner[j]->col);
}
}
@@ -2234,4 +2282,95 @@ void SExpressionWasmBuilder::parseType(Element& s) {
wasm.addFunctionType(std::move(type));
}
+void SExpressionWasmBuilder::parseEvent(Element& s, bool preParseImport) {
+ auto event = make_unique<Event>();
+ size_t i = 1;
+
+ // Parse name
+ if (s[i]->isStr() && s[i]->dollared()) {
+ auto& inner = *s[i++];
+ event->name = inner.str();
+ if (wasm.getEventOrNull(event->name)) {
+ throw ParseException("duplicate event", inner.line, inner.col);
+ }
+ } else {
+ event->name = Name::fromInt(eventCounter);
+ assert(!wasm.getEventOrNull(event->name));
+ }
+ eventCounter++;
+ eventNames.push_back(event->name);
+
+ // Parse import, if any
+ if (i < s.size() && elementStartsWith(*s[i], IMPORT)) {
+ assert(preParseImport && "import element in non-preParseImport mode");
+ auto& importElem = *s[i++];
+ if (importElem.size() != 3) {
+ throw ParseException("invalid import", importElem.line, importElem.col);
+ }
+ if (!importElem[1]->isStr() || importElem[1]->dollared()) {
+ throw ParseException(
+ "invalid import module name", importElem[1]->line, importElem[1]->col);
+ }
+ if (!importElem[2]->isStr() || importElem[2]->dollared()) {
+ throw ParseException(
+ "invalid import base name", importElem[2]->line, importElem[2]->col);
+ }
+ event->module = importElem[1]->str();
+ event->base = importElem[2]->str();
+ }
+
+ // Parse export, if any
+ if (i < s.size() && elementStartsWith(*s[i], EXPORT)) {
+ auto& exportElem = *s[i++];
+ if (event->module.is()) {
+ throw ParseException("import and export cannot be specified together",
+ exportElem.line,
+ exportElem.col);
+ }
+ if (exportElem.size() != 2) {
+ throw ParseException("invalid export", exportElem.line, exportElem.col);
+ }
+ if (!exportElem[1]->isStr() || exportElem[1]->dollared()) {
+ throw ParseException(
+ "invalid export name", exportElem[1]->line, exportElem[1]->col);
+ }
+ auto ex = make_unique<Export>();
+ ex->name = exportElem[1]->str();
+ if (wasm.getExportOrNull(ex->name)) {
+ throw ParseException(
+ "duplicate export", exportElem[1]->line, exportElem[1]->col);
+ }
+ ex->value = event->name;
+ ex->kind = ExternalKind::Event;
+ }
+
+ // Parse attribute
+ if (i >= s.size()) {
+ throw ParseException("event does not have an attribute", s.line, s.col);
+ }
+ auto& attrElem = *s[i++];
+ if (!elementStartsWith(attrElem, ATTR) || attrElem.size() != 2) {
+ throw ParseException("invalid attribute", attrElem.line, attrElem.col);
+ }
+ if (!attrElem[1]->isStr()) {
+ throw ParseException(
+ "invalid attribute", attrElem[1]->line, attrElem[1]->col);
+ }
+ event->attribute = atoi(attrElem[1]->c_str());
+
+ // Parse typeuse
+ FunctionType* functionType = nullptr;
+ Type fakeResult; // just co call parseTypeUse
+ i = parseTypeUse(s, i, functionType, event->params, fakeResult);
+ assert(functionType && "functionType should've been set by parseTypeUse");
+ event->type = functionType->name;
+
+ // If there are more elements, they are invalid
+ if (i < s.size()) {
+ throw ParseException("invalid element", s[i]->line, s[i]->col);
+ }
+
+ wasm.addEvent(event.release());
+}
+
} // namespace wasm
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index ebaba3f24..2c2723bf6 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -68,6 +68,9 @@ FeatureSet getFeatures(Type type) {
if (type == v128) {
return FeatureSet::SIMD;
}
+ if (type == except_ref) {
+ return FeatureSet::ExceptionHandling;
+ }
return FeatureSet();
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 01fe7e976..1d12c2452 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1745,6 +1745,10 @@ static void validateExports(Module& module, ValidationInfo& info) {
info.shouldBeTrue(name == Name("0") || name == module.memory.name,
name,
"module memory exports must be found");
+ } else if (exp->kind == ExternalKind::Event) {
+ info.shouldBeTrue(module.getEventOrNull(name),
+ name,
+ "module event exports must be found");
} else {
WASM_UNREACHABLE();
}
@@ -1855,6 +1859,36 @@ static void validateTable(Module& module, ValidationInfo& info) {
}
}
+static void validateEvents(Module& module, ValidationInfo& info) {
+ if (!module.events.empty()) {
+ info.shouldBeTrue(module.features.hasExceptionHandling(),
+ module.events[0]->name,
+ "Module has events (event-handling is disabled)");
+ }
+ for (auto& curr : module.events) {
+ info.shouldBeTrue(
+ curr->type.is(), curr->name, "Event should have a valid type");
+ FunctionType* ft = module.getFunctionType(curr->type);
+ info.shouldBeEqual(
+ ft->result, none, curr->name, "Event type's result type should be none");
+ info.shouldBeTrue(!curr->params.empty(),
+ curr->name,
+ "There should be 1 or more values in an event type");
+ info.shouldBeEqual(curr->attribute,
+ (unsigned)0,
+ curr->attribute,
+ "Currently only attribute 0 is supported");
+ for (auto type : curr->params) {
+ info.shouldBeTrue(isIntegerType(type) || isFloatType(type),
+ curr->name,
+ "Values in an event should have integer or float type");
+ }
+ info.shouldBeTrue(curr->params == ft->params,
+ curr->name,
+ "Event's function type and internal type should match");
+ }
+}
+
static void validateModule(Module& module, ValidationInfo& info) {
// start
if (module.start.is()) {
@@ -1889,6 +1923,7 @@ bool WasmValidator::validate(Module& module, Flags flags) {
validateGlobals(module, info);
validateMemory(module, info);
validateTable(module, info);
+ validateEvents(module, info);
validateModule(module, info);
}
// validate additional internal IR details when in pass-debug mode
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index c32ead836..c543686ed 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -82,6 +82,8 @@ Name SPECTEST("spectest");
Name PRINT("print");
Name EXIT("exit");
Name SHARED("shared");
+Name EVENT("event");
+Name ATTR("attr");
// Expressions
@@ -908,11 +910,20 @@ Function* Module::getFunction(Name name) {
Global* Module::getGlobal(Name name) {
auto iter = globalsMap.find(name);
if (iter == globalsMap.end()) {
+ assert(false);
Fatal() << "Module::getGlobal: " << name << " does not exist";
}
return iter->second;
}
+Event* Module::getEvent(Name name) {
+ auto iter = eventsMap.find(name);
+ if (iter == eventsMap.end()) {
+ Fatal() << "Module::getEvent: " << name << " does not exist";
+ }
+ return iter->second;
+}
+
FunctionType* Module::getFunctionTypeOrNull(Name name) {
auto iter = functionTypesMap.find(name);
if (iter == functionTypesMap.end()) {
@@ -945,6 +956,14 @@ Global* Module::getGlobalOrNull(Name name) {
return iter->second;
}
+Event* Module::getEventOrNull(Name name) {
+ auto iter = eventsMap.find(name);
+ if (iter == eventsMap.end()) {
+ return nullptr;
+ }
+ return iter->second;
+}
+
FunctionType* Module::addFunctionType(std::unique_ptr<FunctionType> curr) {
if (!curr->name.is()) {
Fatal() << "Module::addFunctionType: empty name";
@@ -1009,6 +1028,20 @@ Global* Module::addGlobal(Global* curr) {
return curr;
}
+Event* Module::addEvent(Event* curr) {
+ if (!curr->name.is()) {
+ Fatal() << "Module::addEvent: empty name";
+ }
+ if (getEventOrNull(curr->name)) {
+ Fatal() << "Module::addEvent: " << curr->name << " already exists";
+ }
+
+ events.emplace_back(curr);
+
+ eventsMap[curr->name] = curr;
+ return curr;
+}
+
void Module::addStart(const Name& s) { start = s; }
void Module::removeFunctionType(Name name) {
@@ -1051,6 +1084,16 @@ void Module::removeGlobal(Name name) {
globalsMap.erase(name);
}
+void Module::removeEvent(Name name) {
+ for (size_t i = 0; i < events.size(); i++) {
+ if (events[i]->name == name) {
+ events.erase(events.begin() + i);
+ break;
+ }
+ }
+ eventsMap.erase(name);
+}
+
// TODO: remove* for other elements
void Module::updateMaps() {
@@ -1070,6 +1113,10 @@ void Module::updateMaps() {
for (auto& curr : globals) {
globalsMap[curr->name] = curr.get();
}
+ eventsMap.clear();
+ for (auto& curr : events) {
+ eventsMap[curr->name] = curr.get();
+ }
}
void Module::clearDebugInfo() { debugInfoFileNames.clear(); }
diff --git a/test/binaryen.js/event.js b/test/binaryen.js/event.js
new file mode 100644
index 000000000..ec7a0f3b1
--- /dev/null
+++ b/test/binaryen.js/event.js
@@ -0,0 +1,32 @@
+function cleanInfo(info) {
+ var ret = {};
+ for (var x in info) {
+ ret[x] = info[x];
+ }
+ return ret;
+}
+
+var module = new Binaryen.Module();
+module.setFeatures(Binaryen.Features.ExceptionHandling);
+
+var vi = module.addFunctionType("vi", Binaryen.none, [Binaryen.i32]);
+var vif = module.addFunctionType("vif", Binaryen.none, [Binaryen.i32, Binaryen.f32]);
+
+var event_ = module.addEvent("a-event", 0, vi);
+
+console.log("GetEvent is equal: " + (event_ === module.getEvent("a-event")));
+
+var eventInfo = Binaryen.getEventInfo(event_);
+console.log("getEventInfo=" + JSON.stringify(cleanInfo(eventInfo)));
+
+module.addEventExport("a-event", "a-event-exp");
+module.addEventImport("a-event-imp", "module", "base", 0, vif);
+
+module.validate();
+console.log(module.emitText());
+
+module.removeExport("a-event-exp");
+module.removeEvent("a-event");
+
+module.validate();
+console.log(module.emitText());
diff --git a/test/binaryen.js/event.js.txt b/test/binaryen.js/event.js.txt
new file mode 100644
index 000000000..233f4b037
--- /dev/null
+++ b/test/binaryen.js/event.js.txt
@@ -0,0 +1,16 @@
+GetEvent is equal: true
+getEventInfo={"name":"a-event","module":"","base":"","attribute":0,"type":"vi"}
+(module
+ (type $vi (func (param i32)))
+ (type $vif (func (param i32 f32)))
+ (import "module" "base" (event $a-event-imp (attr 0) (param i32 f32)))
+ (event $a-event (attr 0) (param i32))
+ (export "a-event-exp" (event $a-event))
+)
+
+(module
+ (type $vi (func (param i32)))
+ (type $vif (func (param i32 f32)))
+ (import "module" "base" (event $a-event-imp (attr 0) (param i32 f32)))
+)
+
diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js
index 649abfa4b..e745c0303 100644
--- a/test/binaryen.js/kitchen-sink.js
+++ b/test/binaryen.js/kitchen-sink.js
@@ -423,16 +423,22 @@ function test_core() {
var initExpr = module.i32.const(1);
var global = module.addGlobal("a-global", Binaryen.i32, false, initExpr)
+ // Create an event
+ var vi = module.addFunctionType("vi", Binaryen.none, [Binaryen.i32]);
+ var event_ = module.addEvent("a-event", 0, vi);
+
// Imports
var fiF = module.addFunctionType("fiF", Binaryen.f32, [ Binaryen.i32, Binaryen.f64 ]);
module.addFunctionImport("an-imported", "module", "base", fiF);
module.addGlobalImport("a-global-imp", "module", "base", Binaryen.i32);
+ module.addEventImport("a-event-imp", "module", "base", 0, vi);
// Exports
module.addFunctionExport("kitchen()sinker", "kitchen_sinker");
module.addGlobalExport("a-global", "a-global-exp");
+ module.addEventExport("a-event", "a-event-exp");
// Function table. One per module
@@ -683,13 +689,16 @@ function test_binaries() {
{ // create a module and write it to binary
module = new Binaryen.Module();
+ module.setFeatures(Binaryen.Features.All);
var iii = module.addFunctionType("iii", Binaryen.i32, [ Binaryen.i32, Binaryen.i32 ]);
+ var vii = module.addFunctionType("vii", Binaryen.none, [ Binaryen.i32, Binaryen.i32 ]);
var x = module.local.get(0, Binaryen.i32),
y = module.local.get(1, Binaryen.i32);
var add = module.i32.add(x, y);
var adder = module.addFunction("adder", iii, [], add);
var initExpr = module.i32.const(3);
var global = module.addGlobal("a-global", Binaryen.i32, false, initExpr)
+ var event_ = module.addEvent("a-event", 0, vii);
Binaryen.setDebugInfo(true); // include names section
buffer = module.emitBinary();
Binaryen.setDebugInfo(false);
@@ -702,6 +711,7 @@ function test_binaries() {
// read the module from the binary
module = Binaryen.readBinary(buffer);
+ module.setFeatures(Binaryen.Features.All);
// validate, print, and free
assert(module.validate());
@@ -755,16 +765,17 @@ function test_parsing() {
// create a module and write it to text
module = new Binaryen.Module();
-
module.setFeatures(Binaryen.Features.All);
var iii = module.addFunctionType("iii", Binaryen.i32, [ Binaryen.i32, Binaryen.i32 ]);
+ var vi = module.addFunctionType("vi", Binaryen.none, [ Binaryen.i32 ]);
var x = module.local.get(0, Binaryen.i32),
y = module.local.get(1, Binaryen.i32);
var add = module.i32.add(x, y);
var adder = module.addFunction("adder", iii, [], add);
var initExpr = module.i32.const(3);
var global = module.addGlobal("a-global", Binaryen.i32, false, initExpr)
+ var event_ = module.addEvent("a-event", 0, vi);
text = module.emitText();
module.dispose();
module = null;
@@ -773,6 +784,7 @@ function test_parsing() {
text = text.replace('adder', 'ADD_ER');
var module2 = Binaryen.parseText(text);
+ module2.setFeatures(Binaryen.Features.All);
assert(module2.validate());
console.log("module loaded from text form:");
console.log(module2.emitText());
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index 857950e6b..85085fa82 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -63,19 +63,23 @@ getExpressionInfo(f32.const)={"id":14,"type":3,"value":8.5}
getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
(module
(type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $vi (func (param i32)))
(type $fiF (func (param i32 f64) (result f32)))
(type $v (func))
- (type $3 (func))
+ (type $4 (func))
(import "module" "base" (global $a-global-imp i32))
(import "module" "base" (func $an-imported (param i32 f64) (result f32)))
+ (import "module" "base" (event $a-event-imp (attr 0) (param i32)))
(memory $0 1 256)
(data (i32.const 10) "hello, world")
(data passive "I am passive")
(table $0 1 funcref)
(elem (i32.const 0) "$kitchen()sinker")
(global $a-global i32 (i32.const 1))
+ (event $a-event (attr 0) (param i32))
(export "kitchen_sinker" (func "$kitchen()sinker"))
(export "a-global-exp" (global $a-global))
+ (export "a-event-exp" (event $a-event))
(export "mem" (memory $0))
(start $starter)
(func "$kitchen()sinker" (; 1 ;) (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
@@ -1898,7 +1902,9 @@ optimized:
module loaded from binary form:
(module
(type $0 (func (param i32 i32) (result i32)))
+ (type $1 (func (param i32 i32)))
(global $global$0 i32 (i32.const 3))
+ (event $event$0 (attr 0) (param i32 i32))
(func $adder (; 0 ;) (type $0) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(local.get $0)
@@ -1944,6 +1950,7 @@ int main() {
std::map<size_t, BinaryenExpressionRef> expressions;
std::map<size_t, BinaryenFunctionRef> functions;
std::map<size_t, BinaryenGlobalRef> globals;
+ std::map<size_t, BinaryenEventRef> events;
std::map<size_t, BinaryenExportRef> exports;
std::map<size_t, RelooperBlockRef> relooperBlocks;
BinaryenModuleRef the_module = NULL;
@@ -3343,13 +3350,20 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
expressions[656] = BinaryenConst(the_module, BinaryenLiteralInt32(1));
globals[0] = BinaryenAddGlobal(the_module, "a-global", 1, 0, expressions[656]);
{
+ BinaryenType paramTypes[] = { 1 };
+ functionTypes[1] = BinaryenAddFunctionType(the_module, "vi", 0, paramTypes, 1);
+ }
+ BinaryenAddEvent(the_module, "a-event", 0, functionTypes[1]);
+ {
BinaryenType paramTypes[] = { 1, 4 };
- functionTypes[1] = BinaryenAddFunctionType(the_module, "fiF", 3, paramTypes, 2);
+ functionTypes[2] = BinaryenAddFunctionType(the_module, "fiF", 3, paramTypes, 2);
}
- BinaryenAddFunctionImport(the_module, "an-imported", "module", "base", functionTypes[1]);
+ BinaryenAddFunctionImport(the_module, "an-imported", "module", "base", functionTypes[2]);
BinaryenAddGlobalImport(the_module, "a-global-imp", "module", "base", 1);
+ BinaryenAddEventImport(the_module, "a-event-imp", "module", "base", 0, functionTypes[1]);
exports[0] = BinaryenAddFunctionExport(the_module, "kitchen()sinker", "kitchen_sinker");
exports[1] = BinaryenAddGlobalExport(the_module, "a-global", "a-global-exp");
+ exports[2] = BinaryenAddEventExport(the_module, "a-event", "a-event-exp");
BinaryenFunctionGetName(functions[0]);
BinaryenFunctionImportGetModule(functions[0]);
BinaryenFunctionImportGetBase(functions[0]);
@@ -3379,17 +3393,17 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
}
{
BinaryenType paramTypes[] = { 0 };
- functionTypes[2] = BinaryenAddFunctionType(the_module, "v", 0, paramTypes, 0);
+ functionTypes[3] = BinaryenAddFunctionType(the_module, "v", 0, paramTypes, 0);
}
expressions[658] = BinaryenNop(the_module);
{
BinaryenType varTypes[] = { 0 };
- functions[1] = BinaryenAddFunction(the_module, "starter", functionTypes[2], varTypes, 0, expressions[658]);
+ functions[1] = BinaryenAddFunction(the_module, "starter", functionTypes[3], varTypes, 0, expressions[658]);
}
BinaryenSetStart(the_module, functions[1]);
{
BinaryenType paramTypes[] = { 0 };
- functionTypes[3] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
+ functionTypes[4] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
}
BinaryenModuleAutoDrop(the_module);
BinaryenModuleSetFeatures(the_module, 127);
@@ -3398,19 +3412,23 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
BinaryenModulePrint(the_module);
(module
(type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $vi (func (param i32)))
(type $fiF (func (param i32 f64) (result f32)))
(type $v (func))
- (type $3 (func))
+ (type $4 (func))
(import "module" "base" (global $a-global-imp i32))
(import "module" "base" (func $an-imported (param i32 f64) (result f32)))
+ (import "module" "base" (event $a-event-imp (attr 0) (param i32)))
(memory $0 1 256)
(data (i32.const 10) "hello, world")
(data passive "I am passive")
(table $0 1 funcref)
(elem (i32.const 0) "$kitchen()sinker")
(global $a-global i32 (i32.const 1))
+ (event $a-event (attr 0) (param i32))
(export "kitchen_sinker" (func "$kitchen()sinker"))
(export "a-global-exp" (global $a-global))
+ (export "a-event-exp" (event $a-event))
(export "mem" (memory $0))
(start $starter)
(func "$kitchen()sinker" (; 1 ;) (type $iiIfF) (param $0 i32) (param $1 i64) (param $2 f32) (param $3 f64) (result i32)
@@ -4765,6 +4783,7 @@ getExpressionInfo(f64.const)={"id":14,"type":4,"value":9.5}
expressions.clear();
functions.clear();
globals.clear();
+ events.clear();
exports.clear();
relooperBlocks.clear();
the_module = BinaryenModuleCreate();
@@ -5706,6 +5725,7 @@ optimized:
expressions.clear();
functions.clear();
globals.clear();
+ events.clear();
exports.clear();
relooperBlocks.clear();
return 0;
@@ -5713,7 +5733,9 @@ optimized:
test_parsing text:
(module
(type $iii (func (param i32 i32) (result i32)))
+ (type $vi (func (param i32)))
(global $a-global i32 (i32.const 3))
+ (event $a-event (attr 0) (param i32))
(func $adder (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(local.get $0)
@@ -5725,7 +5747,9 @@ test_parsing text:
module loaded from text form:
(module
(type $iii (func (param i32 i32) (result i32)))
+ (type $vi (func (param i32)))
(global $a-global i32 (i32.const 3))
+ (event $a-event (attr 0) (param i32))
(func $ADD_ER (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(local.get $0)
diff --git a/test/events.wast b/test/events.wast
new file mode 100644
index 000000000..a2c88b977
--- /dev/null
+++ b/test/events.wast
@@ -0,0 +1,15 @@
+;; Test events
+
+(module
+ (event (attr 0) (param i32))
+ (event $e (attr 0) (param i32 f32))
+
+ (event $e-params0 (attr 0) (param i32 f32))
+ (event $e-params1 (attr 0) (param i32) (param f32))
+
+ (event $e-export (export "ex0") (attr 0) (param i32))
+ (event $e-import (import "env" "im0") (attr 0) (param i32))
+
+ (import "env" "im1" (event (attr 0) (param i32 f32)))
+ (export "ex1" (event $e))
+)
diff --git a/test/events.wast.from-wast b/test/events.wast.from-wast
new file mode 100644
index 000000000..bcb78f6df
--- /dev/null
+++ b/test/events.wast.from-wast
@@ -0,0 +1,12 @@
+(module
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$vif (func (param i32 f32)))
+ (import "env" "im0" (event $e-import (attr 0) (param i32)))
+ (import "env" "im1" (event $import$event1 (attr 0) (param i32 f32)))
+ (event $2 (attr 0) (param i32))
+ (event $e (attr 0) (param i32 f32))
+ (event $e-params0 (attr 0) (param i32 f32))
+ (event $e-params1 (attr 0) (param i32 f32))
+ (event $e-export (attr 0) (param i32))
+ (export "ex1" (event $e))
+)
diff --git a/test/events.wast.fromBinary b/test/events.wast.fromBinary
new file mode 100644
index 000000000..ce19c63bd
--- /dev/null
+++ b/test/events.wast.fromBinary
@@ -0,0 +1,13 @@
+(module
+ (type $0 (func (param i32)))
+ (type $1 (func (param i32 f32)))
+ (import "env" "im0" (event $eimport$0 (attr 0) (param i32)))
+ (import "env" "im1" (event $eimport$1 (attr 0) (param i32 f32)))
+ (event $event$0 (attr 0) (param i32))
+ (event $event$1 (attr 0) (param i32 f32))
+ (event $event$2 (attr 0) (param i32 f32))
+ (event $event$3 (attr 0) (param i32 f32))
+ (event $event$4 (attr 0) (param i32))
+ (export "ex1" (event $event$1))
+)
+
diff --git a/test/events.wast.fromBinary.noDebugInfo b/test/events.wast.fromBinary.noDebugInfo
new file mode 100644
index 000000000..ce19c63bd
--- /dev/null
+++ b/test/events.wast.fromBinary.noDebugInfo
@@ -0,0 +1,13 @@
+(module
+ (type $0 (func (param i32)))
+ (type $1 (func (param i32 f32)))
+ (import "env" "im0" (event $eimport$0 (attr 0) (param i32)))
+ (import "env" "im1" (event $eimport$1 (attr 0) (param i32 f32)))
+ (event $event$0 (attr 0) (param i32))
+ (event $event$1 (attr 0) (param i32 f32))
+ (event $event$2 (attr 0) (param i32 f32))
+ (event $event$3 (attr 0) (param i32 f32))
+ (event $event$4 (attr 0) (param i32))
+ (export "ex1" (event $event$1))
+)
+
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index e0b4a5ec4..76a8aa675 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -488,6 +488,11 @@ void test_core() {
BinaryenAddGlobal(module, "a-global", BinaryenTypeInt32(), 0, makeInt32(module, 7));
BinaryenAddGlobal(module, "a-mutable-global", BinaryenTypeFloat32(), 1, makeFloat32(module, 7.5));
+ // Events
+ BinaryenType eparams[1] = { BinaryenTypeInt32() };
+ BinaryenFunctionTypeRef vi = BinaryenAddFunctionType(module, "vi", BinaryenTypeNone(), eparams, 1);
+ BinaryenAddEvent(module, "a-event", 0, vi);
+
// Imports
BinaryenType iparams[2] = { BinaryenTypeInt32(), BinaryenTypeFloat64() };
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index c9bcc4b68..e5e16c6fe 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -21,9 +21,10 @@ BinaryenFeatureAll: 127
)
(module
(type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $vi (func (param i32)))
(type $fiF (func (param i32 f64) (result f32)))
(type $v (func))
- (type $3 (func))
+ (type $4 (func))
(import "module" "base" (func $an-imported (param i32 f64) (result f32)))
(memory $0 1 256)
(data (i32.const 10) "hello, world")
@@ -32,6 +33,7 @@ BinaryenFeatureAll: 127
(elem (i32.const 0) "$kitchen()sinker")
(global $a-global i32 (i32.const 7))
(global $a-mutable-global (mut f32) (f32.const 7.5))
+ (event $a-event (attr 0) (param i32))
(export "kitchen_sinker" (func "$kitchen()sinker"))
(export "mem" (memory $0))
(start $starter)
@@ -1930,6 +1932,7 @@ int main() {
std::map<size_t, BinaryenExpressionRef> expressions;
std::map<size_t, BinaryenFunctionRef> functions;
std::map<size_t, BinaryenGlobalRef> globals;
+ std::map<size_t, BinaryenEventRef> events;
std::map<size_t, BinaryenExportRef> exports;
std::map<size_t, RelooperBlockRef> relooperBlocks;
BinaryenModuleRef the_module = NULL;
@@ -3308,10 +3311,15 @@ int main() {
expressions[654] = BinaryenConst(the_module, BinaryenLiteralFloat32(7.5));
globals[1] = BinaryenAddGlobal(the_module, "a-mutable-global", 3, 1, expressions[654]);
{
+ BinaryenType paramTypes[] = { 1 };
+ functionTypes[1] = BinaryenAddFunctionType(the_module, "vi", 0, paramTypes, 1);
+ }
+ BinaryenAddEvent(the_module, "a-event", 0, functionTypes[1]);
+ {
BinaryenType paramTypes[] = { 1, 4 };
- functionTypes[1] = BinaryenAddFunctionType(the_module, "fiF", 3, paramTypes, 2);
+ functionTypes[2] = BinaryenAddFunctionType(the_module, "fiF", 3, paramTypes, 2);
}
- BinaryenAddFunctionImport(the_module, "an-imported", "module", "base", functionTypes[1]);
+ BinaryenAddFunctionImport(the_module, "an-imported", "module", "base", functionTypes[2]);
exports[0] = BinaryenAddFunctionExport(the_module, "kitchen()sinker", "kitchen_sinker");
BinaryenFunctionGetName(functions[0]);
{
@@ -3330,17 +3338,17 @@ int main() {
}
{
BinaryenType paramTypes[] = { 0 };
- functionTypes[2] = BinaryenAddFunctionType(the_module, "v", 0, paramTypes, 0);
+ functionTypes[3] = BinaryenAddFunctionType(the_module, "v", 0, paramTypes, 0);
}
expressions[656] = BinaryenNop(the_module);
{
BinaryenType varTypes[] = { 0 };
- functions[1] = BinaryenAddFunction(the_module, "starter", functionTypes[2], varTypes, 0, expressions[656]);
+ functions[1] = BinaryenAddFunction(the_module, "starter", functionTypes[3], varTypes, 0, expressions[656]);
}
BinaryenSetStart(the_module, functions[1]);
{
BinaryenType paramTypes[] = { 0 };
- functionTypes[3] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
+ functionTypes[4] = BinaryenAddFunctionType(the_module, NULL, 0, paramTypes, 0);
}
BinaryenModuleAutoDrop(the_module);
BinaryenModuleSetFeatures(the_module, 127);
@@ -3349,9 +3357,10 @@ int main() {
BinaryenModulePrint(the_module);
(module
(type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $vi (func (param i32)))
(type $fiF (func (param i32 f64) (result f32)))
(type $v (func))
- (type $3 (func))
+ (type $4 (func))
(import "module" "base" (func $an-imported (param i32 f64) (result f32)))
(memory $0 1 256)
(data (i32.const 10) "hello, world")
@@ -3360,6 +3369,7 @@ int main() {
(elem (i32.const 0) "$kitchen()sinker")
(global $a-global i32 (i32.const 7))
(global $a-mutable-global (mut f32) (f32.const 7.5))
+ (event $a-event (attr 0) (param i32))
(export "kitchen_sinker" (func "$kitchen()sinker"))
(export "mem" (memory $0))
(start $starter)
@@ -4723,6 +4733,7 @@ int main() {
expressions.clear();
functions.clear();
globals.clear();
+ events.clear();
exports.clear();
relooperBlocks.clear();
the_module = BinaryenModuleCreate();
@@ -5657,6 +5668,7 @@ optimized:
expressions.clear();
functions.clear();
globals.clear();
+ events.clear();
exports.clear();
relooperBlocks.clear();
return 0;
diff --git a/test/example/c-api-kitchen-sink.txt.txt b/test/example/c-api-kitchen-sink.txt.txt
index 05edca1a2..679ae534c 100644
--- a/test/example/c-api-kitchen-sink.txt.txt
+++ b/test/example/c-api-kitchen-sink.txt.txt
@@ -3,9 +3,10 @@
)
(module
(type $iiIfF (func (param i32 i64 f32 f64) (result i32)))
+ (type $vi (func (param i32)))
(type $fiF (func (param i32 f64) (result f32)))
(type $v (func))
- (type $3 (func))
+ (type $4 (func))
(import "module" "base" (func $an-imported (param i32 f64) (result f32)))
(memory $0 1 256)
(data (i32.const 10) "hello, world")
@@ -14,6 +15,7 @@
(elem (i32.const 0) "$kitchen()sinker")
(global $a-global i32 (i32.const 7))
(global $a-mutable-global (mut f32) (f32.const 7.5))
+ (event $a-event (attr 0) (param i32))
(export "kitchen_sinker" (func "$kitchen()sinker"))
(export "mem" (memory $0))
(start $starter)
diff --git a/test/metadce/rooted-export.wast b/test/metadce/rooted-export.wast
index c2c88ec40..4b93969b4 100644
--- a/test/metadce/rooted-export.wast
+++ b/test/metadce/rooted-export.wast
@@ -8,5 +8,11 @@
(func $b_wasm_func
(unreachable)
)
+
+ (export "wasm_event_a" (event $a_wasm_event))
+ (export "wasm_event_b" (event $b_wasm_event))
+
+ (event $a_wasm_event (attr 0) (param i32))
+ (event $b_wasm_event (attr 0) (param i32))
)
diff --git a/test/metadce/rooted-export.wast.dced b/test/metadce/rooted-export.wast.dced
index 636be324b..7eef01f40 100644
--- a/test/metadce/rooted-export.wast.dced
+++ b/test/metadce/rooted-export.wast.dced
@@ -1,6 +1,9 @@
(module
(type $FUNCSIG$v (func))
+ (type $FUNCSIG$vi (func (param i32)))
+ (event $b_wasm_event (attr 0) (param i32))
(export "wasm_func_b" (func $b_wasm_func))
+ (export "wasm_event_b" (event $b_wasm_event))
(func $b_wasm_func (; 0 ;) (type $FUNCSIG$v)
(unreachable)
)
diff --git a/test/metadce/rooted-export.wast.dced.stdout b/test/metadce/rooted-export.wast.dced.stdout
index 0a0cce75a..5b6a25c02 100644
--- a/test/metadce/rooted-export.wast.dced.stdout
+++ b/test/metadce/rooted-export.wast.dced.stdout
@@ -1,2 +1,4 @@
-unused: export$wasm_func_a$2
+unused: event$a_wasm_event$2
+unused: export$wasm_event_a$5
+unused: export$wasm_func_a$4
unused: func$a_wasm_func$0
diff --git a/test/metadce/rooted-export.wast.graph.txt b/test/metadce/rooted-export.wast.graph.txt
index 274fb0d18..8ecd66dc0 100644
--- a/test/metadce/rooted-export.wast.graph.txt
+++ b/test/metadce/rooted-export.wast.graph.txt
@@ -1,8 +1,13 @@
[
{
- "name": "rooted-export",
+ "name": "rooted-export-func",
"root": true,
"export": "wasm_func_b"
+ },
+ {
+ "name": "rooted-export-event",
+ "root": true,
+ "export": "wasm_event_b"
}
]
diff --git a/test/passes/O3_low-memory-unused_metrics.txt b/test/passes/O3_low-memory-unused_metrics.txt
index 91ddf6d87..bf5cd01a8 100644
--- a/test/passes/O3_low-memory-unused_metrics.txt
+++ b/test/passes/O3_low-memory-unused_metrics.txt
@@ -1,4 +1,5 @@
total
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
diff --git a/test/passes/converge_O3_metrics.bin.txt b/test/passes/converge_O3_metrics.bin.txt
index dd8470d0d..1c7a3275e 100644
--- a/test/passes/converge_O3_metrics.bin.txt
+++ b/test/passes/converge_O3_metrics.bin.txt
@@ -1,4 +1,5 @@
total
+ [events] : 0
[exports] : 2
[funcs] : 8
[globals] : 1
@@ -242,6 +243,7 @@ total
)
)
total
+ [events] : 0
[exports] : 2
[funcs] : 8
[globals] : 1
@@ -486,6 +488,7 @@ total
)
)
total
+ [events] : 0
[exports] : 2
[funcs] : 8
[globals] : 1
diff --git a/test/passes/func-metrics.txt b/test/passes/func-metrics.txt
index 83aabc2fe..a6e9b0c92 100644
--- a/test/passes/func-metrics.txt
+++ b/test/passes/func-metrics.txt
@@ -1,4 +1,5 @@
global
+ [events] : 0
[exports] : 0
[funcs] : 3
[globals] : 1
@@ -89,6 +90,7 @@ func: ifs
)
)
global
+ [events] : 0
[exports] : 0
[funcs] : 0
[globals] : 0
@@ -97,6 +99,7 @@ global
(module
)
global
+ [events] : 0
[exports] : 2
[funcs] : 3
[globals] : 0
@@ -171,6 +174,7 @@ export: b (func_b)
)
)
global
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
@@ -202,6 +206,7 @@ start: func_a
)
)
global
+ [events] : 0
[exports] : 0
[funcs] : 1
[globals] : 0
@@ -229,6 +234,7 @@ start: func_a
)
)
global
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 1
diff --git a/test/passes/metrics.txt b/test/passes/metrics_all-features.txt
index 95ca2c601..ba772597d 100644
--- a/test/passes/metrics.txt
+++ b/test/passes/metrics_all-features.txt
@@ -1,4 +1,5 @@
total
+ [events] : 2
[exports] : 0
[funcs] : 1
[globals] : 1
@@ -14,11 +15,14 @@ total
if : 4
(module
(type $0 (func (param i32)))
+ (type $FUNCSIG$vii (func (param i32 i32)))
(memory $0 256 256)
(data (i32.const 0) "\ff\ef\0f\1f 0@P\99")
(table $0 256 256 funcref)
(elem (i32.const 0) $ifs $ifs $ifs)
(global $glob i32 (i32.const 1337))
+ (event $e0 (attr 0) (param i32))
+ (event $e1 (attr 0) (param i32 i32))
(func $ifs (; 0 ;) (type $0) (param $x i32)
(local $y f32)
(block $block0
@@ -60,6 +64,7 @@ total
)
)
total
+ [events] : 0
[exports] : 0
[funcs] : 0
[globals] : 0
diff --git a/test/passes/metrics.wast b/test/passes/metrics_all-features.wast
index 5ae98b7c7..018262f22 100644
--- a/test/passes/metrics.wast
+++ b/test/passes/metrics_all-features.wast
@@ -5,6 +5,8 @@
(data (i32.const 0) "\ff\ef\0f\1f\20\30\40\50\99")
(type $0 (func (param i32)))
(global $glob i32 (i32.const 1337))
+ (event $e0 (attr 0) (param i32))
+ (event $e1 (attr 0) (param i32 i32))
(func $ifs (type $0) (param $x i32)
(local $y f32)
(block $block0
diff --git a/test/passes/metrics_strip-debug_metrics.bin.txt b/test/passes/metrics_strip-debug_metrics.bin.txt
index 3e7294453..51dfd1e79 100644
--- a/test/passes/metrics_strip-debug_metrics.bin.txt
+++ b/test/passes/metrics_strip-debug_metrics.bin.txt
@@ -1,4 +1,5 @@
total
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
@@ -7,6 +8,7 @@ total
[vars] : 0
nop : 1
total
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
diff --git a/test/passes/metrics_strip-producers_metrics.bin.txt b/test/passes/metrics_strip-producers_metrics.bin.txt
index e977d4ed5..290ed2599 100644
--- a/test/passes/metrics_strip-producers_metrics.bin.txt
+++ b/test/passes/metrics_strip-producers_metrics.bin.txt
@@ -1,4 +1,5 @@
total
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
@@ -7,6 +8,7 @@ total
[vars] : 0
nop : 1
total
+ [events] : 0
[exports] : 1
[funcs] : 1
[globals] : 0
diff --git a/test/passes/minify-imports-and-exports.txt b/test/passes/minify-imports-and-exports_all-features.txt
index b6a2cf8bf..78852dfa8 100644
--- a/test/passes/minify-imports-and-exports.txt
+++ b/test/passes/minify-imports-and-exports_all-features.txt
@@ -942,7 +942,7 @@ longname3488 => J9
longname1490 => JA
longname4946 => JAa
longname1544 => JB
-exp1 => JBa
+eventname1 => JBa
longname1598 => JC
longname1652 => JD
longname1706 => JE
@@ -1035,7 +1035,7 @@ longname3489 => K9
longname1491 => KA
longname4947 => KAa
longname1545 => KB
-exp2 => KBa
+exp1 => KBa
longname1599 => KC
longname1653 => KD
longname1707 => KE
@@ -1128,6 +1128,7 @@ longname3490 => L9
longname1492 => LA
longname4948 => LAa
longname1546 => LB
+exp2 => LBa
longname1600 => LC
longname1654 => LD
longname1708 => LE
@@ -1220,6 +1221,7 @@ longname3491 => M9
longname1493 => MA
longname4949 => MAa
longname1547 => MB
+event1 => MBa
longname1601 => MC
longname1655 => MD
longname1709 => ME
@@ -5002,6 +5004,8 @@ longname1426 => zz
longname4882 => zza
(module
(type $FUNCSIG$v (func))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "a" (global $import$global0 i32))
(import "env" "__memory_base" (global $import$global1 i32))
(import "env" "__table_base" (global $import$global2 i32))
@@ -10005,8 +10009,11 @@ longname4882 => zza
(import "env" "HBa" (func $internal4998))
(import "env" "IBa" (func $internal4999))
(import "other" "anything" (func $internalInfinity))
- (export "JBa" (func $foo1))
- (export "KBa" (func $foo2))
+ (import "env" "JBa" (event $eventname1 (attr 0) (param i32)))
+ (event $event1 (attr 0) (param i32 i32))
+ (export "KBa" (func $foo1))
+ (export "LBa" (func $foo2))
+ (export "MBa" (event $event1))
(func $foo1 (; 5000 ;) (type $FUNCSIG$v)
(nop)
)
diff --git a/test/passes/minify-imports-and-exports.wast b/test/passes/minify-imports-and-exports_all-features.wast
index ce0c46f95..2db91c2ad 100644
--- a/test/passes/minify-imports-and-exports.wast
+++ b/test/passes/minify-imports-and-exports_all-features.wast
@@ -5002,9 +5002,11 @@
(import "env" "__memory_base" (global i32))
(import "env" "__table_base" (global i32))
(import "other" "anything" (func $internalInfinity))
+ (import "env" "eventname1" (event $eventname1 (attr 0) (param i32)))
(export "exp1" (func $foo1))
(export "exp2" (func $foo2))
(func $foo1)
(func $foo2)
+ (export "event1" (event $event1))
+ (event $event1 (attr 0) (param i32 i32))
)
-
diff --git a/test/passes/minify-imports.txt b/test/passes/minify-imports_all-features.txt
index 45e295c67..024018bc2 100644
--- a/test/passes/minify-imports.txt
+++ b/test/passes/minify-imports_all-features.txt
@@ -942,6 +942,7 @@ longname3488 => J9
longname1490 => JA
longname4946 => JAa
longname1544 => JB
+eventname1 => JBa
longname1598 => JC
longname1652 => JD
longname1706 => JE
@@ -5000,6 +5001,8 @@ longname1426 => zz
longname4882 => zza
(module
(type $FUNCSIG$v (func))
+ (type $FUNCSIG$vi (func (param i32)))
+ (type $FUNCSIG$vii (func (param i32 i32)))
(import "env" "a" (global $import$global0 i32))
(import "env" "__memory_base" (global $import$global1 i32))
(import "env" "__table_base" (global $import$global2 i32))
@@ -10003,8 +10006,11 @@ longname4882 => zza
(import "env" "HBa" (func $internal4998))
(import "env" "IBa" (func $internal4999))
(import "other" "anything" (func $internalInfinity))
+ (import "env" "JBa" (event $eventname1 (attr 0) (param i32)))
+ (event $event1 (attr 0) (param i32 i32))
(export "foo1" (func $foo1))
(export "foo2" (func $foo2))
+ (export "event1" (event $event1))
(func $foo1 (; 5000 ;) (type $FUNCSIG$v)
(nop)
)
diff --git a/test/passes/minify-imports.wast b/test/passes/minify-imports_all-features.wast
index b24173163..26c8062ba 100644
--- a/test/passes/minify-imports.wast
+++ b/test/passes/minify-imports_all-features.wast
@@ -5002,9 +5002,11 @@
(import "env" "__memory_base" (global i32))
(import "env" "__table_base" (global i32))
(import "other" "anything" (func $internalInfinity))
+ (import "env" "eventname1" (event $eventname1 (attr 0) (param i32)))
(export "foo1" (func $foo1))
(export "foo2" (func $foo2))
+ (export "event1" (event $event1))
(func $foo1)
(func $foo2)
+ (event $event1 (attr 0) (param i32 i32))
)
-
diff --git a/test/passes/remove-unused-module-elements_enable-threads.txt b/test/passes/remove-unused-module-elements_all-features.txt
index 5db1ba5e6..3d80f96e9 100644
--- a/test/passes/remove-unused-module-elements_enable-threads.txt
+++ b/test/passes/remove-unused-module-elements_all-features.txt
@@ -278,3 +278,8 @@
)
)
)
+(module
+ (type $FUNCSIG$vj (func (param i64)))
+ (event $e1 (attr 0) (param i64))
+ (export "e1" (event $e1))
+)
diff --git a/test/passes/remove-unused-module-elements_enable-threads.wast b/test/passes/remove-unused-module-elements_all-features.wast
index 8e07fb9c1..3d0248848 100644
--- a/test/passes/remove-unused-module-elements_enable-threads.wast
+++ b/test/passes/remove-unused-module-elements_all-features.wast
@@ -261,4 +261,11 @@
)
)
)
-
+(module ;; non-exported events can be removed
+ (type $0 (func (param i32)))
+ (event $e0 (attr 0) (type $0))
+ (event $e1 (attr 0) (param i64))
+ (export "e1" (event $e1))
+ (import "env" "e" (event $e2 (attr 0) (param i32)))
+ (func $f (; 0 ;) (type $0))
+)
diff --git a/test/passes/remove-unused-nonfunction-module-elements_enable-threads.txt b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt
index 140cf61e6..e08bf1eb2 100644
--- a/test/passes/remove-unused-nonfunction-module-elements_enable-threads.txt
+++ b/test/passes/remove-unused-nonfunction-module-elements_all-features.txt
@@ -329,3 +329,12 @@
)
)
)
+(module
+ (type $0 (func (param i32)))
+ (type $FUNCSIG$vj (func (param i64)))
+ (event $e1 (attr 0) (param i64))
+ (export "e1" (event $e1))
+ (func $f (; 0 ;) (type $0) (param $0 i32)
+ (nop)
+ )
+)
diff --git a/test/passes/remove-unused-nonfunction-module-elements_enable-threads.wast b/test/passes/remove-unused-nonfunction-module-elements_all-features.wast
index 4c1944c12..36bc79e82 100644
--- a/test/passes/remove-unused-nonfunction-module-elements_enable-threads.wast
+++ b/test/passes/remove-unused-nonfunction-module-elements_all-features.wast
@@ -261,4 +261,11 @@
)
)
)
-
+(module ;; non-exported events can be removed
+ (type $0 (func (param i32)))
+ (event $e0 (attr 0) (type $0))
+ (event $e1 (attr 0) (param i64))
+ (export "e1" (event $e1))
+ (import "env" "e" (event $e2 (attr 0) (param i32)))
+ (func $f (; 0 ;) (type $0))
+)
diff --git a/test/passes/translate-to-fuzz_all-features.txt b/test/passes/translate-to-fuzz_all-features.txt
index fe24e738e..c3fd77b20 100644
--- a/test/passes/translate-to-fuzz_all-features.txt
+++ b/test/passes/translate-to-fuzz_all-features.txt
@@ -1,33 +1,26 @@
(module
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vifidi (func (param i32 f32 i32 f64 i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$vj (func (param i64)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vd (func (param f64)))
- (type $FUNCSIG$vjVdddV (func (param i64 v128 f64 f64 f64 v128)))
- (type $FUNCSIG$ddVff (func (param f64 v128 f32 f32) (result f64)))
- (type $FUNCSIG$VdVjf (func (param f64 v128 i64 f32) (result v128)))
- (type $FUNCSIG$v (func))
- (type $FUNCSIG$jjiV (func (param i64 i32 v128) (result i64)))
(import "fuzzing-support" "log-i32" (func $log-i32 (param i32)))
(import "fuzzing-support" "log-i64" (func $log-i64 (param i64)))
(import "fuzzing-support" "log-f32" (func $log-f32 (param f32)))
(import "fuzzing-support" "log-f64" (func $log-f64 (param f64)))
- (memory $0 1 1)
+ (memory $0 (shared 1 1))
(data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3")
- (table $0 8 funcref)
- (elem (i32.const 0) $func_6 $func_6 $func_6 $func_6 $func_9 $func_9 $func_9 $func_9)
- (global $global$0 (mut i32) (i32.const 975664160))
- (global $global$1 (mut i32) (i32.const -536870912))
- (global $global$2 (mut f32) (f32.const 2147483648))
- (global $global$3 (mut f32) (f32.const 1448959360))
+ (table $0 3 3 funcref)
+ (elem (i32.const 0) $func_5 $func_5 $func_5)
+ (global $global$0 (mut i32) (i32.const 975663930))
+ (global $global$1 (mut i32) (i32.const 2066300474))
+ (global $global$2 (mut i64) (i64.const 20510))
+ (global $global$3 (mut f32) (f32.const -2147483648))
(global $hangLimit (mut i32) (i32.const 10))
+ (event $event$0 (attr 0) (param i32 f32 i32 f64 i32))
(export "hashMemory" (func $hashMemory))
(export "func_5" (func $func_5))
- (export "func_6" (func $func_6))
- (export "func_7" (func $func_7))
- (export "func_7_invoker" (func $func_7_invoker))
- (export "func_9" (func $func_9))
(export "hangLimitInitializer" (func $hangLimitInitializer))
(func $hashMemory (; 4 ;) (type $FUNCSIG$i) (result i32)
(local $0 i32)
@@ -260,171 +253,18 @@
)
(local.get $0)
)
- (func $func_5 (; 5 ;) (type $FUNCSIG$vjVdddV) (param $0 i64) (param $1 v128) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 v128)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0
- (call $log-f64
- (loop $label$1 (result f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$2 (result f64)
- (call $log-i32
- (call $hashMemory)
- )
- (local.get $2)
- )
- )
- )
- (call $log-i32
- (call $hashMemory)
- )
- )
- )
- (func $func_6 (; 6 ;) (type $FUNCSIG$ddVff) (param $0 f64) (param $1 v128) (param $2 f32) (param $3 f32) (result f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0 (result f64)
- (call $log-i32
- (i32.const 84215045)
- )
- (f64.const 8)
- )
- )
- (func $func_7 (; 7 ;) (type $FUNCSIG$VdVjf) (param $0 f64) (param $1 v128) (param $2 i64) (param $3 f32) (result v128)
- (local $4 i32)
- (local $5 f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $1)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (local.tee $1
- (local.tee $1
- (v128.const i32x4 0x6d484708 0x13e740fc 0x5849037f 0xe4000000)
- )
- )
- )
- (func $func_7_invoker (; 8 ;) (type $FUNCSIG$v)
- (drop
- (call $func_7
- (f64.const 16986)
- (v128.const i32x4 0x00000000 0x00000010 0xffffe000 0xffffffff)
- (i64.const -12)
- (f32.const 7243)
- )
- )
- (drop
- (call $func_7
- (f64.const -65536)
- (v128.const i32x4 0x00007d1f 0x00000200 0xffff0000 0x7fffffff)
- (i64.const 288230376151711744)
- (f32.const 128)
- )
- )
- (call $log-i32
- (call $hashMemory)
- )
- (drop
- (call $func_7
- (f64.const -nan:0xfffffffffffb5)
- (v128.const i32x4 0x00000000 0x403a0000 0x00000000 0xb8100000)
- (i64.const 66)
- (f32.const -nan:0x7fffb0)
- )
- )
- )
- (func $func_9 (; 9 ;) (type $FUNCSIG$jjiV) (param $0 i64) (param $1 i32) (param $2 v128) (result i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (i64.const 8)
- )
- (func $func_10 (; 10 ;) (param $0 v128) (param $1 i64) (param $2 i64) (result v128)
+ (func $func_5 (; 5 ;) (type $FUNCSIG$vj) (param $0 i64)
+ (local $1 f64)
+ (local $2 i32)
(local $3 i64)
(local $4 v128)
- (local $5 f64)
- (local $6 f32)
- (local $7 v128)
- (local $8 f64)
- (local $9 i64)
- (local $10 f32)
- (local $11 i32)
- (local $12 f32)
- (local $13 i32)
- (local $14 v128)
- (local $15 v128)
- (local $16 f64)
+ (local $5 f32)
(block
(if
(i32.eqz
(global.get $hangLimit)
)
- (return
- (v128.const i32x4 0x80000000 0x80000001 0xffffffa1 0x00000000)
- )
+ (return)
)
(global.set $hangLimit
(i32.sub
@@ -434,300 +274,193 @@
)
)
(block $label$0
- (local.set $8
- (f64.const 5382)
+ (br_if $label$0
+ (i32.const 1376786182)
)
- (if
- (i32.eqz
- (local.tee $11
- (loop $label$72 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $15)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (i32.const -127)
- )
- )
- )
- (block $label$19
- (block $label$20
- (loop $label$21
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (v128.const i32x4 0x4598b000 0x4f000000 0x5f000000 0x4d30d0b0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (nop)
- )
- (local.set $11
- (local.tee $13
- (i32.const 3088)
- )
- )
- )
- (return
- (local.get $0)
- )
- )
- (block $label$43
- (loop $label$44
- (block
- (if
+ (local.set $4
+ (v128.const i32x4 0x0e0a0e0d 0x0709060c 0x764b6f6f 0x00040000)
+ )
+ (local.set $4
+ (if (result v128)
+ (i32.eqz
+ (if (result i32)
+ (if (result i32)
(i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $4)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block
- (block $label$45
- (if
- (i32.eqz
- (i32.const 536870912)
- )
- (local.set $11
- (local.get $13)
- )
- (block $label$46
- (global.set $global$3
- (f32.const 269239296)
- )
- (local.tee $16
- (local.tee $16
- (block $label$47
- (br $label$46)
+ (if (result i32)
+ (i32.eqz
+ (if
+ (i32.const 1329942351)
+ (local.tee $2
+ (local.tee $2
+ (loop $label$38
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (local.get $2)
+ )
+ (block $label$39
+ (nop)
+ (br $label$0)
+ )
+ (block $label$40
+ (local.set $4
+ (v128.const i32x4 0x05050505 0x46190000 0xc6800000 0x4a031a19)
+ )
+ (br $label$0)
+ )
+ )
+ )
+ )
+ )
+ (block $label$41
+ (nop)
+ (br $label$0)
)
)
)
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (block $label$47
+ (local.set $2
+ (local.get $2)
)
+ (br $label$0)
)
- (loop $label$48
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
+ (block $label$48 (result i32)
+ (loop $label$49
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
)
- (return
- (local.get $4)
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
)
)
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (block
+ (local.set $5
+ (f32.const 9.625223197211503e-38)
)
- )
- )
- (block
- (local.set $11
- (local.tee $13
- (i32.const 2097152)
- )
- )
- (br_if $label$48
- (i32.eqz
- (local.tee $11
- (loop $label$49 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (br_if $label$49
+ (if (result i32)
+ (block $label$57
+ (local.set $5
+ (local.tee $5
+ (block $label$58 (result f32)
+ (local.set $4
+ (local.get $4)
+ )
+ (local.get $5)
)
)
)
- (block (result i32)
- (local.set $10
- (local.tee $12
- (local.tee $6
- (local.tee $12
- (local.get $12)
- )
+ (br $label$0)
+ )
+ (if (result i32)
+ (i32.const 1376786182)
+ (block $label$60
+ (if
+ (block $label$61 (result i32)
+ (i32.const 925442358)
+ )
+ (block $label$62
+ (br_if $label$62
+ (i32.const 256)
)
)
- )
- (br_if $label$49
- (i32.const 512)
- )
- (loop $label$50 (result i32)
- (block
+ (block $label$63
(if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (v128.const i32x4 0x0000002a 0xf801141f 0xfe1c005c 0xf1f27f14)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (local.get $2)
+ (local.set $1
+ (local.get $1)
)
- )
- )
- (block $label$51 (result i32)
- (local.set $11
- (if (result i32)
- (i32.eqz
- (if (result i32)
- (if (result i32)
- (if (result i32)
- (i32.eqz
- (i32.const 170)
- )
- (i32.const 170)
- (i32.const 16)
- )
- (local.tee $11
- (local.get $13)
- )
- (block $label$52
- (local.set $13
- (local.get $11)
- )
- (br $label$44)
- )
- )
- (block $label$53
- (loop $label$54
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $14)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block
- (nop)
- (br_if $label$54
- (i32.eqz
- (local.get $13)
- )
- )
- (local.set $2
- (i64.const 112)
- )
- )
- )
- (br $label$49)
+ (block $label$67
+ (if
+ (i32.eqz
+ (i32.const 0)
+ )
+ (block $label$68
+ (local.set $1
+ (local.get $1)
)
- (local.tee $11
- (local.tee $13
- (local.get $11)
+ (block $label$69
+ (nop)
+ (local.set $4
+ (local.get $4)
)
)
)
- )
- (block $label$55 (result i32)
- (br_if $label$48
- (local.tee $11
- (local.tee $13
- (local.get $13)
+ (if
+ (i32.eqz
+ (br_if $label$48
+ (i32.const 32768)
+ (local.get $2)
)
)
- )
- (br_if $label$51
- (local.tee $11
- (local.tee $13
- (i32.const -62)
- )
+ (local.set $4
+ (v128.const i32x4 0xffffff81 0xffffffeb 0x80000000 0x74273131)
)
- (if (result i32)
- (i32.const 86)
- (block $label$56 (result i32)
- (br_if $label$56
- (local.get $13)
- (i32.const -84)
- )
- )
- (loop $label$57 (result i32)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $14)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (i32.const 34176355)
- )
+ (local.set $2
+ (local.get $2)
)
)
)
- (block $label$58
- (local.set $14
- (v128.const i32x4 0x0f0c0d04 0x0a020d43 0x1402026d 0x47130847)
- )
- (br $label$49)
+ (local.set $0
+ (i64.const -2097152)
)
)
)
- (loop $label$59
+ (local.set $1
+ (local.get $1)
+ )
+ )
+ )
+ (br $label$0)
+ )
+ (block $label$70 (result i32)
+ (loop $label$71 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result i32)
+ (loop $label$72
(block
(if
(i32.eqz
(global.get $hangLimit)
)
- (return
- (v128.const i32x4 0x00000000 0x43e00000 0x00000000 0xc1f00000)
- )
+ (return)
)
(global.set $hangLimit
(i32.sub
@@ -736,16 +469,21 @@
)
)
)
- (block $label$60
- (loop $label$61
+ (local.set $4
+ (local.tee $4
+ (local.get $4)
+ )
+ )
+ )
+ (br_if $label$71
+ (i32.eqz
+ (loop $label$73
(block
(if
(i32.eqz
(global.get $hangLimit)
)
- (return
- (v128.const i32x4 0x00007272 0x00000000 0x00000001 0x80000000)
- )
+ (return)
)
(global.set $hangLimit
(i32.sub
@@ -754,97 +492,127 @@
)
)
)
- (block $label$62
- (local.set $3
- (i64.const -2048)
- )
- (i64.store16 offset=3 align=1
- (i32.and
- (local.tee $13
- (local.tee $13
- (local.tee $13
- (i32.const 64)
- )
- )
- )
- (i32.const 15)
- )
- (local.tee $9
- (loop $label$63 (result i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (v128.const i32x4 0x80000000 0x1e1e141e 0x00008000 0x000e010b)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block (result i64)
- (local.set $9
- (local.get $3)
- )
- (br_if $label$63
- (i32.const -256)
- )
- (block $label$64 (result i64)
- (local.set $16
- (f64.const 2147483648)
- )
- (local.get $1)
- )
- )
- )
- )
+ (block $label$74
+ (local.set $4
+ (v128.const i32x4 0xf8f8ff00 0x000000a5 0x0000000e 0xffff00ff)
)
+ (br $label$73)
)
)
- (return
- (local.get $4)
- )
)
)
+ (i32.const -131072)
+ )
+ )
+ )
+ )
+ (if (result i32)
+ (local.get $2)
+ (block $label$75
+ (call $log-i32
+ (local.tee $2
+ (i32.const 5)
)
)
+ (br $label$49)
+ )
+ (block $label$76 (result i32)
+ (nop)
+ (local.tee $2
+ (i32.const 1276448839)
+ )
)
)
)
)
+ (local.set $2
+ (local.get $2)
+ )
+ )
+ )
+ (loop $label$90
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
)
- (local.tee $13
- (local.tee $11
- (block $label$65
- (local.set $16
- (f64.const 5.487989131676445e-139)
+ (block
+ (local.set $1
+ (local.get $1)
+ )
+ (br_if $label$90
+ (i32.eqz
+ (local.tee $2
+ (i32.const -93)
)
- (br $label$44)
)
)
+ (nop)
)
)
+ (local.get $2)
)
)
- (local.set $5
- (local.get $5)
+ (block $label$91 (result i32)
+ (local.set $5
+ (block $label$92 (result f32)
+ (local.set $1
+ (loop $label$19 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result f64)
+ (nop)
+ (br_if $label$19
+ (i32.eqz
+ (i32.const -129)
+ )
+ )
+ (local.tee $1
+ (f64.const -nan:0xffffffffffff0)
+ )
+ )
+ )
+ )
+ (local.get $5)
+ )
+ )
+ (local.get $2)
)
- (local.set $11
- (local.get $11)
+ (block $label$95 (result i32)
+ (local.get $2)
)
)
)
- (unreachable)
+ (local.get $4)
+ (block $label$96 (result v128)
+ (v128.const i32x4 0x80800000 0xdf800000 0xcf000000 0x4f800000)
+ )
)
)
)
)
- (func $hangLimitInitializer (; 11 ;)
+ (func $hangLimitInitializer (; 6 ;)
(global.set $hangLimit
(i32.const 10)
)
diff --git a/test/passes/translate-to-fuzz_all-features.wast b/test/passes/translate-to-fuzz_all-features.wast
index 5b378f2b2..ae1761899 100644
--- a/test/passes/translate-to-fuzz_all-features.wast
+++ b/test/passes/translate-to-fuzz_all-features.wast
@@ -1,4 +1,4 @@
-(module # fake module here, for test harness, but it's really not needed
+(module # fake module here, for test harness, but it is really not needed
..
any
3INPUT
diff --git a/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.txt b/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.txt
index 294b4f986..57afb02b7 100644
--- a/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.txt
+++ b/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.txt
@@ -1,35 +1,24 @@
(module
(type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$vifidi (func (param i32 f32 i32 f64 i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$vj (func (param i64)))
(type $FUNCSIG$vf (func (param f32)))
(type $FUNCSIG$vd (func (param f64)))
- (type $FUNCSIG$vjVdddV (func (param i64 v128 f64 f64 f64 v128)))
- (type $FUNCSIG$ddVff (func (param f64 v128 f32 f32) (result f64)))
- (type $FUNCSIG$VdVjf (func (param f64 v128 i64 f32) (result v128)))
- (type $FUNCSIG$v (func))
- (type $FUNCSIG$jjiV (func (param i64 i32 v128) (result i64)))
- (type $FUNCSIG$VVjj (func (param v128 i64 i64) (result v128)))
(import "fuzzing-support" "log-i32" (func $log-i32 (param i32)))
(import "fuzzing-support" "log-i64" (func $log-i64 (param i64)))
(import "fuzzing-support" "log-f32" (func $log-f32 (param f32)))
(import "fuzzing-support" "log-f64" (func $log-f64 (param f64)))
- (memory $0 1 1)
+ (memory $0 (shared 1 1))
(data (i32.const 0) "N\0fN\f5\f9\b1\ff\fa\eb\e5\fe\a7\ec\fb\fc\f4\a6\e4\ea\f0\ae\e3")
- (table $0 8 8 funcref)
- (elem (i32.const 0) $func_6 $func_6 $func_6 $func_6 $func_9 $func_9 $func_9 $func_9)
- (global $global$0 (mut i32) (i32.const 975664160))
- (global $global$1 (mut i32) (i32.const -536870912))
- (global $global$2 (mut f32) (f32.const 2147483648))
- (global $global$3 (mut f32) (f32.const 1448959360))
+ (table $0 0 funcref)
+ (global $global$0 (mut i32) (i32.const 975663930))
+ (global $global$1 (mut i32) (i32.const 2066300474))
+ (global $global$2 (mut i64) (i64.const 20510))
+ (global $global$3 (mut f32) (f32.const -2147483648))
(global $hangLimit (mut i32) (i32.const 10))
+ (event $event$0 (attr 0) (param i32 f32 i32 f64 i32))
(export "hashMemory" (func $hashMemory))
- (export "func_5" (func $func_5))
- (export "func_6" (func $func_6))
- (export "func_7" (func $func_7))
- (export "func_7_invoker" (func $func_7_invoker))
- (export "func_9" (func $func_9))
- (export "func_10" (func $func_10))
(export "hangLimitInitializer" (func $hangLimitInitializer))
(func $hashMemory (; 4 ;) (type $FUNCSIG$i) (result i32)
(local $0 i32)
@@ -262,7 +251,12 @@
)
(local.get $0)
)
- (func $func_5 (; 5 ;) (type $FUNCSIG$vjVdddV) (param $0 i64) (param $1 v128) (param $2 f64) (param $3 f64) (param $4 f64) (param $5 v128)
+ (func $func_5 (; 5 ;) (param $0 i64)
+ (local $1 f64)
+ (local $2 i32)
+ (local $3 i64)
+ (local $4 v128)
+ (local $5 f32)
(block
(if
(i32.eqz
@@ -278,173 +272,612 @@
)
)
(block $label$0
- (call $log-f64
- (loop $label$1 (result f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return)
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (br_if $label$0
+ (i32.eqz
+ (local.tee $2
+ (local.tee $2
+ (local.tee $2
+ (local.tee $2
+ (local.get $2)
+ )
)
)
)
- (block $label$2 (result f64)
- (call $log-i32
- (call $hashMemory)
- )
- (local.get $2)
- )
- )
- )
- (call $log-i32
- (call $hashMemory)
- )
- )
- )
- (func $func_6 (; 6 ;) (type $FUNCSIG$ddVff) (param $0 f64) (param $1 v128) (param $2 f32) (param $3 f32) (result f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (block $label$0 (result f64)
- (call $log-i32
- (i32.const 84215045)
- )
- (f64.const 8)
- )
- )
- (func $func_7 (; 7 ;) (type $FUNCSIG$VdVjf) (param $0 f64) (param $1 v128) (param $2 i64) (param $3 f32) (result v128)
- (local $4 i32)
- (local $5 f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $1)
)
)
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (local.tee $1
- (local.tee $1
- (v128.const i32x4 0x6d484708 0x13e740fc 0x5849037f 0xe4000000)
- )
- )
- )
- (func $func_7_invoker (; 8 ;) (type $FUNCSIG$v)
- (drop
- (call $func_7
- (f64.const 16986)
- (v128.const i32x4 0x00000000 0x00000010 0xffffe000 0xffffffff)
- (i64.const -12)
- (f32.const 7243)
- )
- )
- (drop
- (call $func_7
- (f64.const -65536)
- (v128.const i32x4 0x00007d1f 0x00000200 0xffff0000 0x7fffffff)
- (i64.const 288230376151711744)
- (f32.const 128)
- )
- )
- (call $log-i32
- (call $hashMemory)
- )
- (drop
- (call $func_7
- (f64.const 0)
- (v128.const i32x4 0x00000000 0x403a0000 0x00000000 0xb8100000)
- (i64.const 66)
- (f32.const 0)
- )
- )
- )
- (func $func_9 (; 9 ;) (type $FUNCSIG$jjiV) (param $0 i64) (param $1 i32) (param $2 v128) (result i64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $0)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
- )
- )
- )
- (i64.const 8)
- )
- (func $func_10 (; 10 ;) (type $FUNCSIG$VVjj) (param $0 v128) (param $1 i64) (param $2 i64) (result v128)
- (local $3 i64)
- (local $4 v128)
- (local $5 f64)
- (local $6 f32)
- (local $7 v128)
- (local $8 f64)
- (local $9 i64)
- (local $10 f32)
- (local $11 i32)
- (local $12 f32)
- (local $13 i32)
- (local $14 v128)
- (local $15 v128)
- (local $16 f64)
- (block
- (if
- (i32.eqz
- (global.get $hangLimit)
- )
- (return
- (local.get $14)
- )
- )
- (global.set $hangLimit
- (i32.sub
- (global.get $hangLimit)
- (i32.const 1)
+ (local.set $4
+ (v128.const i32x4 0x0e0a0e0d 0x0709060c 0x764b6f6f 0x00040000)
+ )
+ (local.set $4
+ (if (result v128)
+ (i32.eqz
+ (if (result i32)
+ (if (result i32)
+ (i32.eqz
+ (if (result i32)
+ (i32.eqz
+ (if
+ (i32.eqz
+ (if (result i32)
+ (i32.eqz
+ (if (result i32)
+ (i32.eqz
+ (if (result i32)
+ (local.get $2)
+ (loop $label$1 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result i32)
+ (block $label$2
+ (local.set $3
+ (i64.const 15662)
+ )
+ (local.set $2
+ (local.get $2)
+ )
+ )
+ (br_if $label$1
+ (local.get $2)
+ )
+ (if (result i32)
+ (i32.eqz
+ (local.get $2)
+ )
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ )
+ (block $label$3 (result i32)
+ (local.tee $2
+ (i32.const 286267661)
+ )
+ )
+ )
+ )
+ (block $label$4
+ (loop $label$5
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block
+ (block $label$6
+ (if
+ (i32.eqz
+ (loop $label$7 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (i32.const 6506)
+ )
+ )
+ (block $label$8
+ (local.set $2
+ (local.tee $2
+ (local.get $2)
+ )
+ )
+ (local.set $5
+ (local.get $5)
+ )
+ )
+ (block $label$9
+ (if
+ (local.tee $2
+ (if (result i32)
+ (local.get $2)
+ (local.get $2)
+ (loop $label$10 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result i32)
+ (nop)
+ (br_if $label$10
+ (i32.eqz
+ (i32.const 64)
+ )
+ )
+ (local.tee $2
+ (loop $label$11 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (i32.const 512)
+ )
+ )
+ )
+ )
+ )
+ )
+ (local.set $3
+ (local.get $3)
+ )
+ (loop $label$12
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (local.set $1
+ (local.get $1)
+ )
+ )
+ )
+ (local.set $2
+ (i32.const 170)
+ )
+ )
+ )
+ (call $log-i32
+ (local.get $2)
+ )
+ )
+ (br_if $label$5
+ (i32.eqz
+ (i32.const 2376257)
+ )
+ )
+ (local.set $4
+ (local.tee $4
+ (v128.const i32x4 0xfff70000 0x007f700e 0x07420400 0x8000007f)
+ )
+ )
+ )
+ )
+ (block $label$13
+ (if
+ (i32.eqz
+ (block $label$14 (result i32)
+ (local.set $4
+ (v128.const i32x4 0x80000000 0x00000080 0xfffffffc 0x00007fff)
+ )
+ (i32.const -123)
+ )
+ )
+ (local.set $1
+ (local.get $1)
+ )
+ (local.set $5
+ (local.get $5)
+ )
+ )
+ (br $label$0)
+ )
+ )
+ (block $label$17 (result i32)
+ (i64.atomic.store offset=3
+ (i32.const 640629291)
+ (local.tee $0
+ (i64.const -16)
+ )
+ )
+ (if (result i32)
+ (block $label$18
+ (local.set $1
+ (loop $label$19 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result f64)
+ (nop)
+ (br_if $label$19
+ (i32.eqz
+ (local.get $2)
+ )
+ )
+ (local.tee $1
+ (f64.const 0)
+ )
+ )
+ )
+ )
+ (return)
+ )
+ (local.tee $2
+ (local.get $2)
+ )
+ (block $label$20
+ (loop $label$21
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (local.set $1
+ (local.get $1)
+ )
+ )
+ (return)
+ )
+ )
+ )
+ )
+ )
+ (block $label$22 (result i32)
+ (local.set $5
+ (f32.const 10160664)
+ )
+ (if (result i32)
+ (i32.eqz
+ (i32.const 0)
+ )
+ (block $label$23
+ (local.set $1
+ (loop $label$24 (result f64)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block (result f64)
+ (local.set $3
+ (local.get $0)
+ )
+ (br_if $label$24
+ (i32.const -9)
+ )
+ (f64.const -18446744073709551615)
+ )
+ )
+ )
+ (br $label$0)
+ )
+ (block $label$25 (result i32)
+ (loop $label$26
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block
+ (local.set $2
+ (local.get $2)
+ )
+ (br_if $label$26
+ (i32.eqz
+ (if (result i32)
+ (br_if $label$25
+ (i32.const -8)
+ (local.get $2)
+ )
+ (local.get $2)
+ (block $label$29 (result i32)
+ (call $log-i32
+ (call $hashMemory)
+ )
+ (loop $label$30 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (local.get $2)
+ )
+ )
+ )
+ )
+ )
+ (local.set $5
+ (local.get $5)
+ )
+ )
+ )
+ (local.get $2)
+ )
+ )
+ )
+ (block $label$35
+ (local.set $1
+ (f64.const 1414944843)
+ )
+ (br $label$0)
+ )
+ )
+ )
+ (local.tee $2
+ (local.tee $2
+ (loop $label$38
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (if
+ (i32.eqz
+ (local.get $2)
+ )
+ (block $label$39
+ (nop)
+ (br $label$0)
+ )
+ (block $label$40
+ (local.set $1
+ (local.get $1)
+ )
+ (br $label$0)
+ )
+ )
+ )
+ )
+ )
+ (block $label$41
+ (memory.copy
+ (loop $label$42 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (if (result i32)
+ (loop $label$43 (result i32)
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block $label$44 (result i32)
+ (local.set $3
+ (i64.const 2097574720517510216)
+ )
+ (if (result i32)
+ (i32.eqz
+ (local.get $2)
+ )
+ (i32.const 1296450369)
+ (local.tee $2
+ (i32.const -14)
+ )
+ )
+ )
+ )
+ (block $label$45
+ (local.set $2
+ (i32.const 235407412)
+ )
+ (br $label$0)
+ )
+ (block $label$46 (result i32)
+ (local.set $2
+ (local.tee $2
+ (local.tee $2
+ (local.tee $2
+ (i32.const 1179009606)
+ )
+ )
+ )
+ )
+ (i32.const 1073741824)
+ )
+ )
+ )
+ (local.get $2)
+ (i32.const 1073741824)
+ )
+ (return)
+ )
+ )
+ )
+ (local.get $2)
+ (local.get $2)
+ )
+ )
+ (block $label$47
+ (local.set $2
+ (local.get $2)
+ )
+ (br $label$0)
+ )
+ (block $label$48 (result i32)
+ (loop $label$49
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (local.set $5
+ (local.get $5)
+ )
+ )
+ (loop $label$90
+ (block
+ (if
+ (i32.eqz
+ (global.get $hangLimit)
+ )
+ (return)
+ )
+ (global.set $hangLimit
+ (i32.sub
+ (global.get $hangLimit)
+ (i32.const 1)
+ )
+ )
+ )
+ (block
+ (local.set $1
+ (local.get $1)
+ )
+ (local.set $2
+ (local.get $2)
+ )
+ (nop)
+ )
+ )
+ (local.get $2)
+ )
+ )
+ (block $label$91 (result i32)
+ (local.set $5
+ (block $label$92 (result f32)
+ (f32.const 6)
+ )
+ )
+ (local.get $2)
+ )
+ (local.get $2)
+ )
+ )
+ (v128.const i32x4 0xffffffc0 0x00001f16 0x00008000 0x505c1a13)
+ (v128.const i32x4 0xc7007b11 0x721d0901 0x01810043 0x441f1201)
)
)
)
- (return
- (local.get $14)
- )
)
- (func $hangLimitInitializer (; 11 ;)
+ (func $hangLimitInitializer (; 6 ;)
(global.set $hangLimit
(i32.const 10)
)
)
- (func $deNan32 (; 12 ;) (param $0 f32) (result f32)
+ (func $deNan32 (; 7 ;) (param $0 f32) (result f32)
(if (result f32)
(f32.eq
(local.get $0)
@@ -454,7 +887,7 @@
(f32.const 0)
)
)
- (func $deNan64 (; 13 ;) (param $0 f64) (result f64)
+ (func $deNan64 (; 8 ;) (param $0 f64) (result f64)
(if (result f64)
(f64.eq
(local.get $0)
diff --git a/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.wast b/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.wast
index cbf25fde1..3dab8874e 100644
--- a/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.wast
+++ b/test/passes/translate-to-fuzz_no-fuzz-nans_all-features.wast
@@ -1,4 +1,4 @@
-(module # fake module here, for test harness, but it's really not needed
+(module # fake module here, for test harness, but it is really not needed
..
any
3INPUT
diff --git a/test/spec/events.wast b/test/spec/events.wast
new file mode 100644
index 000000000..80a6b11fe
--- /dev/null
+++ b/test/spec/events.wast
@@ -0,0 +1,43 @@
+;; Test events
+
+(module
+ (event (attr 0) (param i32))
+ (event $e (attr 0) (param i32 f32))
+
+ (event $e-params0 (attr 0) (param i32 f32))
+ (event $e-params1 (attr 0) (param i32) (param f32))
+
+ (event $e-export (export "ex0") (attr 0) (param i32))
+ (event $e-import (import "env" "im0") (attr 0) (param i32))
+
+ (import "env" "im1" (event (attr 0) (param i32 f32)))
+ (export "ex1" (event $e))
+)
+
+(assert_invalid
+ (module (event $e (attr 0) (param i32) (result i32)))
+ "Event type's result type should be none"
+)
+
+(assert_invalid
+ (module (event $e (attr 0)))
+ "There should be 1 or more values in an event type"
+)
+
+(assert_invalid
+ (module (event $e (attr 1) (param i32)))
+ "Currently only attribute 0 is supported"
+)
+
+(assert_invalid
+ (module (event $e (attr 0) (param except_ref)))
+ "Values in an event should have integer or float type"
+)
+
+(assert_invalid
+ (module
+ (type $t (param i32))
+ (event $e (attr 0) (type $t) (param i32 f32))
+ "type and param don't match"
+ )
+)