<commit_before>//=======================================================================
// Copyright <NAME> 2011-2013.
// 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 <boost/range/adaptors.hpp>

#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "Variable.hpp"

#include "ltac/prologue.hpp"
#include "ltac/Utils.hpp"
#include "ltac/Printer.hpp"
#include "ltac/Address.hpp"
#include "ltac/Instruction.hpp"
#include "ltac/Jump.hpp"

using namespace eddic;

namespace {

std::set<ltac::Register> parameter_registers(eddic::Function& function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::Register> overriden_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function.standard() || configuration->option_defined("fparameter-allocation")){
        unsigned int maxInt = descriptor->numberOfIntParamRegisters();

        for(auto& parameter : function.parameters()){
            auto type = parameter.type();
            unsigned int position = function.parameter_position_by_type(parameter.name());

            if(mtac::is_single_int_register(type) && position <= maxInt){
                overriden_registers.insert(ltac::Register(descriptor->int_param_register(position)));
            }
        }
    }

    return overriden_registers;
}

std::set<ltac::FloatRegister> float_parameter_registers(eddic::Function& function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::FloatRegister> overriden_float_registers;
    
    auto descriptor = getPlatformDescriptor(platform);

    if(function.standard() || configuration->option_defined("fparameter-allocation")){
        unsigned int maxFloat = descriptor->numberOfFloatParamRegisters();

        for(auto& parameter : function.parameters()){
            auto type = parameter.type();
            unsigned int position = function.parameter_position_by_type(parameter.name());

            if(mtac::is_single_float_register(type) && position <= maxFloat){
                overriden_float_registers.insert(ltac::FloatRegister(descriptor->float_param_register(position)));
            }
        }
    }

    return overriden_float_registers;
}

bool callee_save(Function& definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition.return_type();
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return registers
    if((return_type == INT || return_type == BOOL || return_type == CHAR) && reg.reg == descriptor->int_return_register1()){
        return false;
    } else if(return_type == STRING && (reg.reg == descriptor->int_return_register1() || reg.reg == descriptor->int_return_register2())){
        return false;
    } else if(return_type->is_pointer() && reg.reg == descriptor->int_return_register1()){ 
        return false;
    }

    auto parameters = parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

bool callee_save(eddic::Function& definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition.return_type();
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return register
    if(return_type == FLOAT && reg.reg == descriptor->float_return_register()){
        return false;
    } 

    auto parameters = float_parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

void callee_save_registers(mtac::Function& function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function.is_main()){
        for(auto& reg : function.use_registers()){
            if(callee_save(function.definition(), reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::PUSH, reg);
            }
        }

        for(auto& float_reg : function.use_float_registers()){
            if(callee_save(function.definition(), float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform)));
                ltac::add_instruction(bb, ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg);
            }
        }
    }
}

void callee_restore_registers(mtac::Function& function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function.is_main()){
        for(auto& float_reg : boost::adaptors::reverse(function.use_float_registers())){
            if(callee_save(function.definition(), float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0));
                ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform)));
            }
        }

        for(auto& reg : boost::adaptors::reverse(function.use_registers())){
            if(callee_save(function.definition(), reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::POP, reg);
            }
        }
    }
}
<commit_msg>Position correctly save registers<commit_after>//=======================================================================
// Copyright <NAME> 2011-2013.
// 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 <boost/range/adaptors.hpp>

#include "GlobalContext.hpp"
#include "FunctionContext.hpp"
#include "Type.hpp"
#include "Variable.hpp"

#include "ltac/prologue.hpp"
#include "ltac/Utils.hpp"
#include "ltac/Printer.hpp"
#include "ltac/Address.hpp"
#include "ltac/Instruction.hpp"
#include "ltac/Jump.hpp"

using namespace eddic;

namespace {

std::set<ltac::Register> parameter_registers(eddic::Function& function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::Register> overriden_registers;

    auto descriptor = getPlatformDescriptor(platform);

    if(function.standard() || configuration->option_defined("fparameter-allocation")){
        unsigned int maxInt = descriptor->numberOfIntParamRegisters();

        for(auto& parameter : function.parameters()){
            auto type = parameter.type();
            unsigned int position = function.parameter_position_by_type(parameter.name());

            if(mtac::is_single_int_register(type) && position <= maxInt){
                overriden_registers.insert(ltac::Register(descriptor->int_param_register(position)));
            }
        }
    }

    return overriden_registers;
}

std::set<ltac::FloatRegister> float_parameter_registers(eddic::Function& function, Platform platform, std::shared_ptr<Configuration> configuration){
    std::set<ltac::FloatRegister> overriden_float_registers;
    
    auto descriptor = getPlatformDescriptor(platform);

    if(function.standard() || configuration->option_defined("fparameter-allocation")){
        unsigned int maxFloat = descriptor->numberOfFloatParamRegisters();

        for(auto& parameter : function.parameters()){
            auto type = parameter.type();
            unsigned int position = function.parameter_position_by_type(parameter.name());

            if(mtac::is_single_float_register(type) && position <= maxFloat){
                overriden_float_registers.insert(ltac::FloatRegister(descriptor->float_param_register(position)));
            }
        }
    }

    return overriden_float_registers;
}

bool callee_save(Function& definition, ltac::Register reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition.return_type();
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return registers
    if((return_type == INT || return_type == BOOL || return_type == CHAR) && reg.reg == descriptor->int_return_register1()){
        return false;
    } else if(return_type == STRING && (reg.reg == descriptor->int_return_register1() || reg.reg == descriptor->int_return_register2())){
        return false;
    } else if(return_type->is_pointer() && reg.reg == descriptor->int_return_register1()){ 
        return false;
    }

    auto parameters = parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

bool callee_save(eddic::Function& definition, ltac::FloatRegister reg, Platform platform, std::shared_ptr<Configuration> configuration){
    auto return_type = definition.return_type();
    auto descriptor = getPlatformDescriptor(platform);

    //Do not save the return register
    if(return_type == FLOAT && reg.reg == descriptor->float_return_register()){
        return false;
    } 

    auto parameters = float_parameter_registers(definition, platform, configuration);

    //Do not save the parameters registers, they are saved by the caller if necessary
    if(parameters.count(reg)){
        return false;
    }

    return true;
}

void callee_save_registers(mtac::Function& function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function.is_main()){
        bool omit_fp = configuration->option_defined("fomit-frame-pointer");

        auto it = bb->l_statements.begin()+1;
        if(!omit_fp){
            ++it;
        }

        for(auto& reg : function.use_registers()){
            if(callee_save(function.definition(), reg, platform, configuration)){
                bb->l_statements.insert(it, std::make_shared<ltac::Instruction>(ltac::Operator::PUSH, reg));
                ++it;
            }
        }

        for(auto& float_reg : function.use_float_registers()){
            if(callee_save(function.definition(), float_reg, platform, configuration)){
                bb->l_statements.insert(it, std::make_shared<ltac::Instruction>(ltac::Operator::SUB, ltac::SP, static_cast<int>(FLOAT->size(platform))));
                ++it;
                bb->l_statements.insert(it, std::make_shared<ltac::Instruction>(ltac::Operator::FMOV, ltac::Address(ltac::SP, 0), float_reg));
                ++it;
            }
        }
    }
}

void callee_restore_registers(mtac::Function& function, mtac::basic_block_p bb, Platform platform, std::shared_ptr<Configuration> configuration){
    //Save registers for all other functions than main
    if(!function.is_main()){
        for(auto& float_reg : boost::adaptors::reverse(function.use_float_registers())){
            if(callee_save(function.definition(), float_reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::FMOV, float_reg, ltac::Address(ltac::SP, 0));
                ltac::add_instruction(bb, ltac::Operator::ADD, ltac::SP, static_cast<int>(FLOAT->size(platform)));
            }
        }

        for(auto& reg : boost::adaptors::reverse(function.use_registers())){
            if(callee_save(function.definition(), reg, platform, configuration)){
                ltac::add_instruction(bb, ltac::Operator::POP, reg);
            }
        }
    }
}

{'fraction_non_alphanumeric': 0.14787554366008698, 'fraction_numerical': 0.0034292405486784877, 'mean_word_length': 3.850709939148073, 'pattern_counts': {'":': 0, '<': 38, '<?xml version=': 0, '>': 67, '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': '7281727', 'n_tokens_mistral': 3423, 'n_tokens_neox': 3256, 'n_words': 660}