#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <deque>
#include <list>
#include <map>
#include <memory>
#include <set>
#include "support/insert_ordered.h"
#include "wasm-builder.h"
#include "wasm.h"
namespace CFG {
class RelooperBuilder : public wasm::Builder {
wasm::Index labelHelper;
public:
RelooperBuilder(wasm::Module& wasm, wasm::Index labelHelper)
: wasm::Builder(wasm), labelHelper(labelHelper) {}
wasm::LocalGet* makeGetLabel() {
return makeLocalGet(labelHelper, wasm::Type::i32);
}
wasm::LocalSet* makeSetLabel(wasm::Index value) {
return makeLocalSet(labelHelper, makeConst(wasm::Literal(int32_t(value))));
}
wasm::Binary* makeCheckLabel(wasm::Index value) {
return makeBinary(
wasm::EqInt32, makeGetLabel(), makeConst(wasm::Literal(int32_t(value))));
}
wasm::Break* makeBlockBreak(int id) {
return wasm::Builder::makeBreak(getBlockBreakName(id));
}
wasm::Break* makeShapeContinue(int id) {
return wasm::Builder::makeBreak(getShapeContinueName(id));
}
wasm::Name getBlockBreakName(int id) {
return wasm::Name(std::string("block$") + std::to_string(id) + "$break");
}
wasm::Name getShapeContinueName(int id) {
return wasm::Name(std::string("shape$") + std::to_string(id) + "$continue");
}
};
struct Relooper;
struct Block;
struct Shape;
struct Branch {
enum FlowType {
Direct = 0, Break = 1,
Continue = 2
};
Shape* Ancestor = nullptr;
Branch::FlowType Type;
wasm::Expression* Condition;
std::unique_ptr<std::vector<wasm::Index>> SwitchValues;
wasm::Expression* Code;
Branch(wasm::Expression* ConditionInit, wasm::Expression* CodeInit = nullptr);
Branch(std::vector<wasm::Index>&& ValuesInit,
wasm::Expression* CodeInit = nullptr);
wasm::Expression*
Render(RelooperBuilder& Builder, Block* Target, bool SetLabel);
};
using BlockSet = wasm::InsertOrderedSet<Block*>;
using BlockBranchMap = wasm::InsertOrderedMap<Block*, Branch*>;
struct Block {
Relooper* relooper;
BlockBranchMap BranchesOut;
BlockSet BranchesIn;
BlockBranchMap ProcessedBranchesOut;
BlockSet ProcessedBranchesIn;
Shape* Parent = nullptr; int Id = -1; wasm::Expression* Code;
wasm::Expression* SwitchCondition;
bool IsCheckedMultipleEntry;
Block(Relooper* relooper,
wasm::Expression* CodeInit,
wasm::Expression* SwitchConditionInit = nullptr);
void AddBranchTo(Block* Target,
wasm::Expression* Condition,
wasm::Expression* Code = nullptr);
void AddSwitchBranchTo(Block* Target,
std::vector<wasm::Index>&& Values,
wasm::Expression* Code = nullptr);
wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop);
};
struct SimpleShape;
struct MultipleShape;
struct LoopShape;
struct Shape {
int Id = -1;
Shape* Next = nullptr;
Shape* Natural;
enum ShapeType { Simple, Multiple, Loop };
ShapeType Type;
Shape(ShapeType TypeInit) : Type(TypeInit) {}
virtual ~Shape() = default;
virtual wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) = 0;
static SimpleShape* IsSimple(Shape* It) {
return It && It->Type == Simple ? (SimpleShape*)It : NULL;
}
static MultipleShape* IsMultiple(Shape* It) {
return It && It->Type == Multiple ? (MultipleShape*)It : NULL;
}
static LoopShape* IsLoop(Shape* It) {
return It && It->Type == Loop ? (LoopShape*)It : NULL;
}
};
struct SimpleShape : public Shape {
Block* Inner = nullptr;
SimpleShape() : Shape(Simple) {}
wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) override;
};
using IdShapeMap = std::map<int, Shape*>;
struct MultipleShape : public Shape {
IdShapeMap InnerMap;
MultipleShape() : Shape(Multiple) {}
wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) override;
};
struct LoopShape : public Shape {
Shape* Inner = nullptr;
BlockSet Entries;
LoopShape() : Shape(Loop) {}
wasm::Expression* Render(RelooperBuilder& Builder, bool InLoop) override;
};
struct Relooper {
wasm::Module* Module;
std::deque<std::unique_ptr<Block>> Blocks;
std::deque<std::unique_ptr<Branch>> Branches;
std::deque<std::unique_ptr<Shape>> Shapes;
Shape* Root;
bool MinSize;
int BlockIdCounter;
int ShapeIdCounter;
Relooper(wasm::Module* ModuleInit);
Block* AddBlock(wasm::Expression* CodeInit,
wasm::Expression* SwitchConditionInit = nullptr);
Branch* AddBranch(wasm::Expression* ConditionInit,
wasm::Expression* CodeInit);
Branch* AddBranch(std::vector<wasm::Index>&& ValuesInit,
wasm::Expression* CodeInit = nullptr);
SimpleShape* AddSimpleShape();
MultipleShape* AddMultipleShape();
LoopShape* AddLoopShape();
void Calculate(Block* Entry);
wasm::Expression* Render(RelooperBuilder& Builder);
void SetMinSize(bool MinSize_) { MinSize = MinSize_; }
};
using BlockBlockSetMap = wasm::InsertOrderedMap<Block*, BlockSet>;
#ifdef RELOOPER_DEBUG
struct Debugging {
static void Dump(Block* Curr, const char* prefix = NULL);
static void Dump(BlockSet& Blocks, const char* prefix = NULL);
static void Dump(Shape* S, const char* prefix = NULL);
};
#endif
}