summaryrefslogtreecommitdiff
path: root/src/passes/Asyncify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/Asyncify.cpp')
-rw-r--r--src/passes/Asyncify.cpp53
1 files changed, 49 insertions, 4 deletions
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index 365891db4..7b2d57574 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -921,9 +921,6 @@ struct AsyncifyFlow : public Pass {
// If the function cannot change our state, we have nothing to do -
// we will never unwind or rewind the stack here.
if (!analyzer->needsInstrumentation(func)) {
- if (analyzer->asserts) {
- addAssertsInNonInstrumented(func);
- }
return;
}
// Rewrite the function body.
@@ -947,7 +944,6 @@ struct AsyncifyFlow : public Pass {
private:
std::unique_ptr<AsyncifyBuilder> builder;
-
Module* module;
Function* func;
@@ -1216,6 +1212,41 @@ private:
// don't want it to be seen by asyncify itself.
return builder->makeCall(ASYNCIFY_GET_CALL_INDEX, {}, Type::none);
}
+};
+
+// Add asserts in non-instrumented code.
+struct AsyncifyAssertInNonInstrumented : public Pass {
+ bool isFunctionParallel() override { return true; }
+
+ ModuleAnalyzer* analyzer;
+ Type pointerType;
+ Name asyncifyMemory;
+
+ std::unique_ptr<Pass> create() override {
+ return std::make_unique<AsyncifyAssertInNonInstrumented>(
+ analyzer, pointerType, asyncifyMemory);
+ }
+
+ AsyncifyAssertInNonInstrumented(ModuleAnalyzer* analyzer,
+ Type pointerType,
+ Name asyncifyMemory)
+ : analyzer(analyzer), pointerType(pointerType),
+ asyncifyMemory(asyncifyMemory) {}
+
+ void runOnFunction(Module* module_, Function* func) override {
+ // FIXME: This looks like it was never right, as it should ignore the top-
+ // most runtime, but it will actually instrument it (as it needs no
+ // instrumentation, like random code - but the top-most runtime is
+ // actually a place that needs neither instrumentation *nor*
+ // assertions, as the assertions will error when it changes the
+ // state).
+ if (!analyzer->needsInstrumentation(func)) {
+ module = module_;
+ builder =
+ make_unique<AsyncifyBuilder>(*module, pointerType, asyncifyMemory);
+ addAssertsInNonInstrumented(func);
+ }
+ }
// Given a function that is not instrumented - because we proved it doesn't
// need it, or depending on the only-list / remove-list - add assertions that
@@ -1275,6 +1306,10 @@ private:
walker.oldState = oldState;
walker.walk(func->body);
}
+
+private:
+ std::unique_ptr<AsyncifyBuilder> builder;
+ Module* module;
};
// Instrument local saving/restoring.
@@ -1689,6 +1724,16 @@ struct Asyncify : public Pass {
runner.setValidateGlobally(false);
runner.run();
}
+ if (asserts) {
+ // Add asserts in non-instrumented code. Note we do not use an
+ // instrumented pass runner here as we do want to run on all functions.
+ PassRunner runner(module);
+ runner.add(make_unique<AsyncifyAssertInNonInstrumented>(
+ &analyzer, pointerType, asyncifyMemory));
+ runner.setIsNested(true);
+ runner.setValidateGlobally(false);
+ runner.run();
+ }
// Next, add local saving/restoring logic. We optimize before doing this,
// to undo the extra code generated by flattening, and to arrive at the
// minimal amount of locals (which is important as we must save and