summaryrefslogtreecommitdiff
path: root/src/cfg/Relooper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/cfg/Relooper.h')
-rw-r--r--src/cfg/Relooper.h32
1 files changed, 19 insertions, 13 deletions
diff --git a/src/cfg/Relooper.h b/src/cfg/Relooper.h
index 3040b0fc2..74a95c8bf 100644
--- a/src/cfg/Relooper.h
+++ b/src/cfg/Relooper.h
@@ -27,10 +27,11 @@ added since the original academic paper [1] was published about it.
#include <stdarg.h>
#include <stdlib.h>
-#include <map>
#include <deque>
-#include <set>
#include <list>
+#include <map>
+#include <memory>
+#include <set>
#include "wasm.h"
#include "wasm-builder.h"
@@ -52,10 +53,10 @@ public:
wasm::Binary* makeCheckLabel(wasm::Index value) {
return makeBinary(wasm::EqInt32, makeGetLabel(), makeConst(wasm::Literal(int32_t(value))));
}
- wasm::Break* makeBreak(int id) {
+ wasm::Break* makeShapeBreak(int id) {
return wasm::Builder::makeBreak(getBreakName(id));
}
- wasm::Break* makeContinue(int id) {
+ wasm::Break* makeShapeContinue(int id) {
return wasm::Builder::makeBreak(getContinueName(id));
}
@@ -82,20 +83,19 @@ struct Branch {
Shape *Ancestor; // If not NULL, this shape is the relevant one for purposes of getting to the target block. We break or continue on it
Branch::FlowType Type; // If Ancestor is not NULL, this says whether to break or continue
- // A branch either has a condition expression if the block ends in ifs, or if the block ends in a switch, then an index, which
- // becomes the index in the table of the switch.
- union {
- wasm::Expression* Condition; // The condition for which we branch. For example, "my_var == 1". Conditions are checked one by one. One of the conditions should have NULL as the condition, in which case it is the default
- wasm::Index Index; // The index in the table of the switch that we correspond do
- };
+ // A branch either has a condition expression if the block ends in ifs, or if the block ends in a switch, then a list of indexes, which
+ // becomes the indexes in the table of the switch. If not a switch, the condition can be any expression.
+ wasm::Expression* Condition;
+ std::unique_ptr<std::vector<wasm::Index>> SwitchValues; // switches are rare, so have just a pointer here
wasm::Expression* Code; // If provided, code that is run right before the branch is taken. This is useful for phis
Branch(wasm::Expression* ConditionInit, wasm::Expression* CodeInit = nullptr);
- Branch(wasm::Index IndexInit, wasm::Expression* CodeInit = nullptr);
+
+ Branch(std::vector<wasm::Index>&& ValuesInit, wasm::Expression* CodeInit = nullptr);
// Emits code for branch
- wasm::Expression* Render(RelooperBuilder& Builder, Block *Target, bool SetLabel);
+ wasm::Expression* Render(RelooperBuilder& Builder, Block *Target, bool SetLabel);
};
// like std::set, except that begin() -> end() iterates in the
@@ -226,8 +226,14 @@ struct Block {
Block(wasm::Expression* CodeInit, wasm::Expression* SwitchConditionInit = nullptr);
~Block();
+ // Add a branch: if the condition holds we branch (or if null, we branch if all others failed)
+ // Note that there can be only one branch from A to B (if you need multiple conditions for the branch,
+ // create a more interesting expression in the Condition).
void AddBranchTo(Block *Target, wasm::Expression* Condition, wasm::Expression* Code = nullptr);
- void AddBranchTo(Block *Target, wasm::Index Index, wasm::Expression* Code = nullptr);
+
+ // Add a switch branch: if the switch condition is one of these values, we branch (or if the list is empty, we are the default)
+ // Note that there can be only one branch from A to B (if you need multiple values for the branch, that's what the array and default are for).
+ void AddSwitchBranchTo(Block *Target, std::vector<wasm::Index>&& Values, wasm::Expression* Code = nullptr);
// Emit code for the block, including its contents and branchings out
wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop);