add helper JumpInstr class
MODIFY
ir/function.cpp
ir/function.cpp
@@ -157,51 +157,41 @@ ostream& operator<<(ostream &os, const Function &f) {
void CFG::edge_iterator::next() {
- // jump to next BB with a terminator that is not a return instruction
- while (it != end && dynamic_cast<Return*>(&(*it)->back())) {
- ++it;
+ // jump to next BB with a terminator that is a jump
+ while (true) {
+ if (bbi == bbe)
+ return;
+
+ if (auto instr = dynamic_cast<JumpInstr*>(&(*bbi)->back())) {
+ ti = instr->targets().begin();
+ te = instr->targets().end();
+ return;
+ }
+
+ ++bbi;
}
}
CFG::edge_iterator::edge_iterator(vector<BasicBlock*>::iterator &&it,
vector<BasicBlock*>::iterator &&end)
- : it(move(it)), end(move(end)) {
+ : bbi(move(it)), bbe(move(end)) {
next();
}
tuple<const BasicBlock&, const BasicBlock&, const Instr&>
CFG::edge_iterator::operator*() const {
- const BasicBlock *dst;
- auto instr = &(*it)->back();
- if (auto br = dynamic_cast<Branch*>(instr)) {
- dst = idx == 0 ? &br->getTrue() : br->getFalse();
- } else if (auto sw = dynamic_cast<Switch*>(instr)) {
- dst = idx == 0 ? &sw->getDefault() : &sw->getTarget(idx-1).second;
- } else {
- UNREACHABLE();
- }
- return { **it, *dst, *instr };
+ return { **bbi, *ti, (*bbi)->back() };
}
void CFG::edge_iterator::operator++(void) {
- auto instr = &(*it)->back();
- auto inc = [&](bool next_bb) {
- if (next_bb) {
- idx = 0;
- ++it;
+ if (++ti == te) {
+ ++bbi;
next();
- } else {
- ++idx;
}
- };
-
- if (auto br = dynamic_cast<Branch*>(instr)) {
- inc(idx > 0 || !br->getFalse());
- } else if (auto sw = dynamic_cast<Switch*>(instr)) {
- inc(idx == sw->getNumTargets());
- } else {
- UNREACHABLE();
}
+
+bool CFG::edge_iterator::operator!=(edge_iterator &rhs) const {
+ return bbi != rhs.bbi && (bbi == bbe || rhs.bbi == rhs.bbe || ti != rhs.ti);
}
static string_view bb_dot_name(const string &name) {

MODIFY
ir/function.h
ir/function.h
@@ -133,8 +133,8 @@ public:
CFG(Function &f) : f(f) {}
class edge_iterator {
- std::vector<BasicBlock*>::iterator it, end;
- unsigned idx = 0;
+ std::vector<BasicBlock*>::iterator bbi, bbe;
+ JumpInstr::target_iterator ti, te;
void next();
public:
edge_iterator(std::vector<BasicBlock*>::iterator &&it,
@@ -142,7 +142,7 @@ public:
std::tuple<const BasicBlock&, const BasicBlock&, const Instr&>
operator*() const;
void operator++(void);
- bool operator!=(edge_iterator &rhs) const { return it != rhs.it; }
+ bool operator!=(edge_iterator &rhs) const;
};
edge_iterator begin() const {

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -607,6 +607,29 @@ unique_ptr<Instr> Phi::dup(const string &suffix) const {
}
+const BasicBlock& JumpInstr::target_iterator::operator*() const {
+ if (auto br = dynamic_cast<Branch*>(instr))
+ return idx == 0 ? br->getTrue() : *br->getFalse();
+
+ if (auto sw = dynamic_cast<Switch*>(instr))
+ return idx == 0 ? sw->getDefault() : sw->getTarget(idx-1).second;
+
+ UNREACHABLE();
+}
+
+JumpInstr::target_iterator JumpInstr::it_helper::end() const {
+ unsigned idx;
+ if (auto br = dynamic_cast<Branch*>(instr)) {
+ idx = br->getFalse() ? 2 : 1;
+ } else if (auto sw = dynamic_cast<Switch*>(instr)) {
+ idx = sw->getNumTargets() + 1;
+ } else {
+ UNREACHABLE();
+ }
+ return { instr, idx };
+}
+
+
void Branch::print(ostream &os) const {
os << "br ";
if (cond)

MODIFY
ir/instr.h
ir/instr.h
@@ -162,14 +162,41 @@ public:
};
-class Branch final : public Instr {
+class JumpInstr : public Instr {
+public:
+ JumpInstr(Type &type, std::string &&name) : Instr(type, std::move(name)) {}
+
+ class target_iterator {
+ JumpInstr *instr;
+ unsigned idx;
+ public:
+ target_iterator() {}
+ target_iterator(JumpInstr *instr, unsigned idx) : instr(instr), idx(idx) {}
+ const BasicBlock& operator*() const;
+ target_iterator& operator++(void) { ++idx; return *this; }
+ bool operator!=(target_iterator &rhs) const { return idx != rhs.idx; }
+ bool operator==(target_iterator &rhs) const { return !(*this != rhs); }
+ };
+
+ class it_helper {
+ JumpInstr *instr;
+ public:
+ it_helper(JumpInstr *instr) : instr(instr) {}
+ target_iterator begin() const { return { instr, 0 }; }
+ target_iterator end() const;
+ };
+ it_helper targets() { return this; }
+};
+
+
+class Branch final : public JumpInstr {
Value *cond = nullptr;
const BasicBlock &dst_true, *dst_false = nullptr;
public:
- Branch(const BasicBlock &dst) : Instr(Type::voidTy, "br"), dst_true(dst) {}
+ Branch(const BasicBlock &dst) : JumpInstr(Type::voidTy, "br"), dst_true(dst) {}
Branch(Value &cond, const BasicBlock &dst_true, const BasicBlock &dst_false)
- : Instr(Type::voidTy, "br"), cond(&cond), dst_true(dst_true),
+ : JumpInstr(Type::voidTy, "br"), cond(&cond), dst_true(dst_true),
dst_false(&dst_false) {}
auto& getTrue() const { return dst_true; }
@@ -181,14 +208,14 @@ public:
};
-class Switch final : public Instr {
+class Switch final : public JumpInstr {
Value &value;
const BasicBlock &default_target;
std::vector<std::pair<Value&, const BasicBlock&>> targets;
public:
Switch(Value &value, const BasicBlock &default_target)
- : Instr(Type::voidTy, "switch"), value(value),
+ : JumpInstr(Type::voidTy, "switch"), value(value),
default_target(default_target) {}
void addTarget(Value &val, const BasicBlock &target);

add helper JumpInstr class