diff --git a/include/blocks/basic_blocks.h b/include/blocks/basic_blocks.h new file mode 100644 index 0000000..c9e92de --- /dev/null +++ b/include/blocks/basic_blocks.h @@ -0,0 +1,22 @@ +#ifndef BASIC_BLOCKS_H +#define BASIC_BLOCKS_H +#include "blocks/block_visitor.h" +#include "blocks/stmt.h" +#include +#include +#include + +class basic_block { + public: + basic_block(std::string label): name(label) {}; + + std::vector> predecessor; + std::vector> successor; + block::expr::Ptr branch_expr; + block::stmt::Ptr parent; + std::string name; +}; + +std::vector> generate_basic_blocks(block::stmt_block::Ptr ast); + +#endif \ No newline at end of file diff --git a/include/blocks/loop_finder.h b/include/blocks/loop_finder.h index 317cca8..841cd41 100644 --- a/include/blocks/loop_finder.h +++ b/include/blocks/loop_finder.h @@ -2,6 +2,7 @@ #define LOOP_FINDER_H #include "blocks/block_visitor.h" #include "blocks/stmt.h" +#include "blocks/basic_blocks.h" namespace block { class loop_finder : public block_visitor { diff --git a/src/blocks/basic_blocks.cpp b/src/blocks/basic_blocks.cpp new file mode 100644 index 0000000..2457703 --- /dev/null +++ b/src/blocks/basic_blocks.cpp @@ -0,0 +1,157 @@ +#include "blocks/basic_blocks.h" +#include + +using namespace block; + +std::vector> generate_basic_blocks(block::stmt_block::Ptr ast) { + std::deque> work_list; + std::vector> return_list; + int basic_block_count = 0; + + // step 1: fill the work_list + for (auto st: ast->stmts) { + auto bb = std::make_shared(std::to_string(basic_block_count)); + bb->parent = st; + work_list.push_back(bb); + basic_block_count++; + } + + // step 2: add successors + for (unsigned i = 0; work_list.size() != 0 && i < work_list.size() - 1; i++) { + work_list[i]->successor.push_back(work_list[i+1]); + } + + // step 3: process blocks + while (work_list.size()) { + auto bb = work_list.front(); + + if (isa(bb->parent)) { + stmt_block::Ptr stmt_block_ = to(bb->parent); + bb->name = "stmt" + bb->name; + + if (stmt_block_->stmts.size() > 0) { + std::vector> stmt_block_list; + + for (auto st: stmt_block_->stmts) { + stmt_block_list.push_back(std::make_shared(std::to_string(basic_block_count++))); + stmt_block_list.back()->parent = st; + } + + for (unsigned i = 0; stmt_block_list.size() != 0 && i < stmt_block_list.size() - 1; i++) { + stmt_block_list[i]->successor.push_back(stmt_block_list[i+1]); + } + + stmt_block_list.back()->successor.push_back(bb->successor.front()); + bb->successor.clear(); + bb->successor.push_back(stmt_block_list.front()); + + return_list.push_back(bb); + work_list.pop_front(); + work_list.insert(work_list.begin(), stmt_block_list.begin(), stmt_block_list.end()); + } + else { + return_list.push_back(bb); + work_list.pop_front(); + } + } + else if (isa(bb->parent)) { + bb->name = "if" + bb->name; + + if_stmt::Ptr if_stmt_ = to(bb->parent); + // assign the if condition to the basic block + bb->branch_expr = if_stmt_->cond; + + // create a exit block + auto exit_bb = std::make_shared("exit" + std::to_string(basic_block_count)); + // assign it a empty stmt_block as parent + exit_bb->parent = std::make_shared(); + // check if this is the last block, if yes the successor will be empty + if (bb->successor.size()) { + // set the successor to the block that if_stmt pointer to earlier + exit_bb->successor.push_back(bb->successor.front()); + // clear the successor block from the if_stmt + bb->successor.clear(); + } + // remove the if from the work_list + work_list.pop_front(); + // push the exit block to the work_list + work_list.push_front(exit_bb); + + // if there is a then_stmt, create a basic block for it + if (to(if_stmt_->then_stmt)->stmts.size() != 0) { + auto then_bb = std::make_shared(std::to_string(++basic_block_count)); + // set the parent of this block as the then stmts + then_bb->parent = if_stmt_->then_stmt; + // set the successor of this block to be the exit block + then_bb->successor.push_back(exit_bb); + // set the successor of the original if_stmt block to be this then block + bb->successor.push_back(then_bb); + // push the block to the work_list, to expand it further + work_list.push_front(then_bb); + } + // if there is a else_stmt, create a basic block for it + if (to(if_stmt_->else_stmt)->stmts.size() != 0) { + auto else_bb = std::make_shared(std::to_string(++basic_block_count)); + // set the parent of this block as the else stmts + else_bb->parent = if_stmt_->else_stmt; + // set the successor of this block to be the exit block + else_bb->successor.push_back(exit_bb); + // set the successor of the orignal if_stmt block to be this else block + bb->successor.push_back(else_bb); + // push the block to the work_list, to expand it further + work_list.insert(work_list.begin() + 1, else_bb); + } + + // if there is no else block, then have the exit block as successor as well. + if (bb->successor.size() <= 1) bb->successor.push_back(exit_bb); + + return_list.push_back(bb); + } + else if (isa(bb->parent)) { + bb->name = "expr" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "decl" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "label" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "goto" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + else if (isa(bb->parent)) { + bb->name = "return" + bb->name; + return_list.push_back(bb); + work_list.pop_front(); + } + + basic_block_count++; + } + + // step 4: resolve goto calls to successors of labels + for (auto bb: return_list) { + if (isa(bb->parent)) { + auto goto_source = std::find_if(return_list.begin(), return_list.end(), + [bb](std::shared_ptr bb_l) { + if (isa(bb_l->parent)) { + return to(bb_l->parent)->label1 == to(bb->parent)->label1; + } + return false; + }); + if (goto_source != return_list.end()) { + bb->successor.clear(); + bb->successor.push_back(*goto_source); + } + } + } + + return return_list; +} \ No newline at end of file diff --git a/src/blocks/loop_finder.cpp b/src/blocks/loop_finder.cpp index 4b382ad..464d7b8 100644 --- a/src/blocks/loop_finder.cpp +++ b/src/blocks/loop_finder.cpp @@ -129,22 +129,39 @@ static void trim_from_parents(std::vector &parents, std::vector } void loop_finder::visit(stmt_block::Ptr a) { - // Check if this block has a label - while (1) { - label_stmt::Ptr found_label = nullptr; - for (auto stmt : a->stmts) { - if (isa(stmt)) { - found_label = to(stmt); - } + std::vector> BBs = generate_basic_blocks(a); + + std::cout << "++++++ basic blocks ++++++ \n"; + for (auto bb: BBs) { + std::cout << bb->name << ":" << "\n"; + if (bb->branch_expr) { + std::cout << " "; + bb->branch_expr->dump(std::cout, 0); } - if (found_label == nullptr) - break; - visit_label(found_label, a); - } - // Once all labels are done, visit the instructions normally - for (auto stmt : a->stmts) { - stmt->accept(this); + std::cout << " "; + std::cout << "br "; + for (auto branches: bb->successor) { + std::cout << branches->name << ", "; + } + std::cout << "\n"; } + std::cout << "++++++ basic blocks ++++++ \n"; + + // while (1) { + // label_stmt::Ptr found_label = nullptr; + // for (auto stmt : a->stmts) { + // if (isa(stmt)) { + // found_label = to(stmt); + // } + // } + // if (found_label == nullptr) + // break; + // visit_label(found_label, a); + // } + // // Once all labels are done, visit the instructions normally + // for (auto stmt : a->stmts) { + // stmt->accept(this); + // } } void loop_finder::visit_label(label_stmt::Ptr a, stmt_block::Ptr parent) {