// Check first that all branch instructions point to valid labels
for (auto it = usedLabels->begin(); it != usedLabels->end(); ++it)
GBE_ASSERTM(*it != LABEL_IS_POINTED, "A label is used and not defined");
- // std::cout << *fn << std::endl;
fn->computeCFG();
GBE_DELETE(usedLabels);
const StackElem elem = fnStack.back();
}
void Function::computeCFG(void) {
- // Clear possible previously computed CFG
- this->foreachBlock([this](BasicBlock &bb) {
+ // Clear possible previously computed CFG and compute the direct
+ // predecessors and successors
+ BasicBlock *prev = NULL;
+ this->foreachBlock([this, &prev](BasicBlock &bb) {
bb.successors.clear();
bb.predecessors.clear();
+ if (prev != NULL) {
+ prev->nextBlock = &bb;
+ bb.prevBlock = prev;
+ }
+ prev = &bb;
});
+
// Update it. Do not forget that a branch can also jump to the next block
BasicBlock *jumpToNext = NULL;
this->foreachBlock([this, &jumpToNext](BasicBlock &bb) {
BasicBlock::BasicBlock(Function &fn) : fn(fn) {
this->first = this->last = NULL;
+ this->nextBlock = this->prevBlock = NULL;
}
BasicBlock::~BasicBlock(void) {
this->foreach([this] (Instruction &insn) {
});
}
+#define DECL_GET_PRED \
+ if (predecessor != NULL) return predecessor; \
+ if (stayInBlock == true) return NULL; \
+ const BasicBlock *parent = this->getParent(); \
+ const BasicBlock *prev = parent->getPrevBlock(); \
+ while (prev) { \
+ Instruction *last = prev->getLastInstruction(); \
+ if (last) return last; \
+ prev = prev->getPrevBlock(); \
+ } \
+ return NULL;
+
+ Instruction *Instruction::getPredecessor(bool stayInBlock) {
+ DECL_GET_PRED;
+ }
+ const Instruction *Instruction::getPredecessor(bool stayInBlock) const {
+ DECL_GET_PRED;
+ }
+
+#undef DECL_GET_PRED
+
+#define DECL_GET_SUCC \
+ if (successor != NULL) return successor; \
+ if (stayInBlock == true) return NULL; \
+ const BasicBlock *parent = this->getParent(); \
+ const BasicBlock *next = parent->getNextBlock(); \
+ while (next) { \
+ Instruction *first = next->getFirstInstruction(); \
+ if (first) return first; \
+ next = next->getNextBlock(); \
+ } \
+ return NULL;
+
+ Instruction *Instruction::getSuccessor(bool stayInBlock) {
+ DECL_GET_SUCC;
+ }
+ const Instruction *Instruction::getSuccessor(bool stayInBlock) const {
+ DECL_GET_SUCC;
+ }
+
+#undef DECL_GET_SUCC
+
} /* namespace ir */
} /* namespace gbe */
/*! Get the parent function */
Function &getParent(void) { return fn; }
const Function &getParent(void) const { return fn; }
- /*! Get the successors */
+ /*! Get the next and previous allocated block */
+ BasicBlock *getNextBlock(void) const { return this->nextBlock; }
+ BasicBlock *getPrevBlock(void) const { return this->prevBlock; }
+ /*! Get the first and last instructions */
+ Instruction *getFirstInstruction(void) const { return this->first; }
+ Instruction *getLastInstruction(void) const { return this->last; }
+ /*! Get successors and predecessors */
const BlockSet &getSuccessorSet(void) const { return successors; }
- /*! Get the predecessors */
const BlockSet &getPredecessorSet(void) const { return predecessors; }
private:
friend class Function; //!< Owns the basic blocks
BlockSet predecessors; //!< Incoming blocks
BlockSet successors; //!< Outgoing blocks
+ BasicBlock *nextBlock; //!< Block allocated just after this one
+ BasicBlock *prevBlock; //!< Block allocated just before this one
Instruction *first; //!< First instruction in the block
Instruction *last; //!< Last instruction in the block
Function &fn; //!< Function the block belongs to
/*! Get the register of the given destination */
RegisterData getSrcData(uint32_t ID = 0u) const;
/*! Get / set the previous instruction in the stream */
- Instruction *getPredecessor(void) { return predecessor; }
- const Instruction *getPredecessor(void) const { return predecessor; }
+ Instruction *getPredecessor(bool stayInBlock = true);
+ const Instruction *getPredecessor(bool stayInBlock = true) const;
void setPredecessor(Instruction *insn) { this->predecessor = insn; }
/*! Get / set the next instruction in the stream */
- Instruction *getSuccessor(void) { return successor; }
- const Instruction *getSuccessor(void) const { return successor; }
+ Instruction *getSuccessor(bool stayInBlock = true);
+ const Instruction *getSuccessor(bool stayInBlock = true) const;
void setSuccessor(Instruction *insn) { this->successor = insn; }
/*! Get / set the parent basic block */
BasicBlock *getParent(void) { return parent; }