<commit_before>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>
#include <unordered_map>

#include <boost/variant.hpp>

#include "mtac/BasicBlockExtractor.hpp"
#include "mtac/Program.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

template<typename T>
bool isReturn(T statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        return (*ptr)->op == mtac::Operator::RETURN;
    }

    return false;
}

void mtac::BasicBlockExtractor::extract(std::shared_ptr<mtac::Program> program) const {
    for(auto& function : program->functions){
        std::unordered_map<std::string, std::shared_ptr<BasicBlock>> labels;
       
        //The first is always a leader 
        bool nextIsLeader = true;

        //First separate the statements into basic blocks
        for(auto& statement : function->getStatements()){
            if(auto* ptr = boost::get<std::string>(&statement)){
                function->newBasicBlock();

                labels[*ptr] = function->currentBasicBlock();

                nextIsLeader = false;
            } else {
                if(nextIsLeader || (boost::get<std::shared_ptr<mtac::Call>>(&statement) && !safe(boost::get<std::shared_ptr<mtac::Call>>(statement)))){
                    function->newBasicBlock();
                    nextIsLeader = false;
                }

                if(boost::get<std::shared_ptr<mtac::IfFalse>>(&statement) || boost::get<std::shared_ptr<mtac::If>>(&statement) || 
                        isReturn(statement) || boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
                    nextIsLeader = true;
                } 

                function->currentBasicBlock()->add(statement);
            }
        }

        //Then, replace all the the labels by reference to basic blocks
        for(auto& block : function->getBasicBlocks()){
            for(auto& statement : block->statements){
                if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                }
            }
        }

        function->getStatements().clear();
    }
}<commit_msg>Introduce and ENTRY and EXIT basic block to the function<commit_after>//=======================================================================
// Copyright <NAME> 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <string>
#include <unordered_map>

#include <boost/variant.hpp>

#include "mtac/BasicBlockExtractor.hpp"
#include "mtac/Program.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

template<typename T>
bool isReturn(T statement){
    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        return (*ptr)->op == mtac::Operator::RETURN;
    }

    return false;
}

void mtac::BasicBlockExtractor::extract(std::shared_ptr<mtac::Program> program) const {
    for(auto& function : program->functions){
        std::unordered_map<std::string, std::shared_ptr<BasicBlock>> labels;
       
        //The first is always a leader 
        bool nextIsLeader = true;

        //First separate the statements into basic blocks
        for(auto& statement : function->getStatements()){
            if(auto* ptr = boost::get<std::string>(&statement)){
                function->newBasicBlock();

                labels[*ptr] = function->currentBasicBlock();

                nextIsLeader = false;
            } else {
                if(nextIsLeader || (boost::get<std::shared_ptr<mtac::Call>>(&statement) && !safe(boost::get<std::shared_ptr<mtac::Call>>(statement)))){
                    function->newBasicBlock();
                    nextIsLeader = false;
                }

                if(boost::get<std::shared_ptr<mtac::IfFalse>>(&statement) || boost::get<std::shared_ptr<mtac::If>>(&statement) || 
                        isReturn(statement) || boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
                    nextIsLeader = true;
                } 

                function->currentBasicBlock()->add(statement);
            }
        }

        //Then, replace all the the labels by reference to basic blocks
        for(auto& block : function->getBasicBlocks()){
            for(auto& statement : block->statements){
                if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Goto>>(&statement)){
                   (*ptr)->block = labels[(*ptr)->label];
                }
            }
        }

        function->getBasicBlocks().push_front(std::make_shared<mtac::BasicBlock>(-1));
        function->getBasicBlocks().push_back(std::make_shared<mtac::BasicBlock>(-2));

        function->getStatements().clear();
    }
}
{'fraction_non_alphanumeric': 0.19975597001917378, 'fraction_numerical': 0.0038347568415548197, 'mean_word_length': 2.6995486782720826, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3846331', 'n_tokens_mistral': 1643, 'n_tokens_neox': 1544, 'n_words': 279}