summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/Outlining.cpp12
-rw-r--r--src/passes/stringify-walker-impl.h7
-rw-r--r--src/passes/stringify-walker.h14
3 files changed, 23 insertions, 10 deletions
diff --git a/src/passes/Outlining.cpp b/src/passes/Outlining.cpp
index f799d2c7a..51d000745 100644
--- a/src/passes/Outlining.cpp
+++ b/src/passes/Outlining.cpp
@@ -100,8 +100,20 @@ struct ReconstructStringifyWalker
existingBuilder.push(curr->iff->condition);
ASSERT_OK(existingBuilder.visitIfStart(curr->iff));
DBG(desc = "If Start for ");
+ } else if (reason.getElseStart()) {
+ ASSERT_OK(existingBuilder.visitElse());
+ DBG(desc = "Else Start at ");
} else if (reason.getEnd()) {
ASSERT_OK(existingBuilder.visitEnd());
+ // Outlining performs an unnested walk of the Wasm module, visiting
+ // each scope one at a time. IRBuilder, in contrast, expects to
+ // visit several nested scopes at a time. Thus, calling end() finalizes
+ // the control flow and places it on IRBuilder's internal stack, ready for
+ // the enclosing scope to consume its expressions off the stack. Since
+ // outlining walks unnested, the enclosing scope never arrives to retrieve
+ // its expressions off the stack, so we must call build() after visitEnd()
+ // to clear the internal stack IRBuilder manages.
+ ASSERT_OK(existingBuilder.build());
DBG(desc = "End for ");
} else {
DBG(desc = "addUniqueSymbol for unimplemented control flow ");
diff --git a/src/passes/stringify-walker-impl.h b/src/passes/stringify-walker-impl.h
index 8ed166d75..cca2a3405 100644
--- a/src/passes/stringify-walker-impl.h
+++ b/src/passes/stringify-walker-impl.h
@@ -43,7 +43,7 @@ template<typename SubType>
inline void StringifyWalker<SubType>::scan(SubType* self, Expression** currp) {
Expression* curr = *currp;
if (Properties::isControlFlowStructure(curr)) {
- self->controlFlowQueue.push(currp);
+ self->controlFlowQueue.push(curr);
self->pushTask(doVisitExpression, currp);
// The if-condition is a value child consumed by the if control flow, which
// makes the if-condition a true sibling rather than part of its contents in
@@ -60,9 +60,8 @@ inline void StringifyWalker<SubType>::scan(SubType* self, Expression** currp) {
// of control flow.
template<typename SubType> void StringifyWalker<SubType>::dequeueControlFlow() {
auto& queue = controlFlowQueue;
- Expression** currp = queue.front();
+ Expression* curr = queue.front();
queue.pop();
- Expression* curr = *currp;
// TODO: Issue #5796, Make a ControlChildIterator
switch (curr->_id) {
@@ -80,7 +79,7 @@ template<typename SubType> void StringifyWalker<SubType>::dequeueControlFlow() {
addUniqueSymbol(SeparatorReason::makeIfStart(iff));
Super::walk(iff->ifTrue);
if (iff->ifFalse) {
- addUniqueSymbol(SeparatorReason::makeElseStart(iff));
+ addUniqueSymbol(SeparatorReason::makeElseStart());
Super::walk(iff->ifFalse);
}
addUniqueSymbol(SeparatorReason::makeEnd());
diff --git a/src/passes/stringify-walker.h b/src/passes/stringify-walker.h
index eb4a4482b..6f50f58d4 100644
--- a/src/passes/stringify-walker.h
+++ b/src/passes/stringify-walker.h
@@ -82,9 +82,7 @@ struct StringifyWalker
If* iff;
};
- struct ElseStart {
- If* iff;
- };
+ struct ElseStart {};
struct LoopStart {
Loop* loop;
@@ -119,8 +117,8 @@ struct StringifyWalker
static SeparatorReason makeIfStart(If* iff) {
return SeparatorReason(IfStart{iff});
}
- static SeparatorReason makeElseStart(If* iff) {
- return SeparatorReason(ElseStart{iff});
+ static SeparatorReason makeElseStart() {
+ return SeparatorReason(ElseStart{});
}
static SeparatorReason makeLoopStart(Loop* loop) {
return SeparatorReason(LoopStart{loop});
@@ -170,7 +168,11 @@ struct StringifyWalker
return o << "~~~Undefined in operator<< overload~~~";
}
- std::queue<Expression**> controlFlowQueue;
+ // To ensure control flow children are walked consistently during outlining,
+ // we push a copy of the control flow expression. This avoids an issue where
+ // control flow no longer points to the same expression after being
+ // outlined into a new function.
+ std::queue<Expression*> controlFlowQueue;
/*
* To initiate the walk, subclasses should call walkModule with a pointer to