<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)
//=======================================================================

#ifndef INTEL_STATEMENT_COMPILER_H
#define INTEL_STATEMENT_COMPILER_H

#include <memory>
#include <unordered_set>

#include "assert.hpp"
#include "Utils.hpp"
#include "Registers.hpp"
#include "Compiler.hpp"
#include "PlatformDescriptor.hpp"

#include "tac/Utils.hpp"

using namespace eddic;

namespace eddic {

namespace as {

template<typename Register, typename FloatRegister>
struct IntelStatementCompiler {
    //The current function being compiled
    std::shared_ptr<tac::Function> function;
    
    AssemblyFileWriter& writer;
    Registers<Register> registers;
    Registers<FloatRegister> float_registers;

    std::unordered_set<std::shared_ptr<tac::BasicBlock>> blockUsage;

    std::unordered_set<std::shared_ptr<Variable>> written;

    bool last;
    bool ended;

    tac::Statement current;
    tac::Statement next;
   
    IntelStatementCompiler(AssemblyFileWriter& w, std::vector<Register> r, std::vector<FloatRegister> fr, std::shared_ptr<tac::Function> f) : function(f), writer(w), 
            registers(r, std::make_shared<Variable>("__fake_int__", newSimpleType(BaseType::INT), Position(PositionType::TEMPORARY))),
            float_registers(fr, std::make_shared<Variable>("__fake_float__", newSimpleType(BaseType::FLOAT), Position(PositionType::TEMPORARY))) {
        last = ended = false;        
    } 
    
    virtual void div(std::shared_ptr<tac::Quadruple> quadruple) = 0;
    virtual void mod(std::shared_ptr<tac::Quadruple> quadruple) = 0;
    
    virtual std::string getMnemonicSize() = 0;
    virtual std::string getFloatPrefix() = 0;
    
    virtual std::string getFloatMove() = 0;
    virtual std::string getFloatToInteger() = 0;
    virtual std::string getIntegerToFloat() = 0;
    virtual std::string getFloatAdd() = 0;
    virtual std::string getFloatSub() = 0;
    virtual std::string getFloatMul() = 0;
    virtual std::string getFloatDiv() = 0;
    virtual std::string getSizedMove() = 0;
   
    /* Management of parameter passing in registers */ 
    virtual Register getIntParamRegister(unsigned int position) = 0;
    virtual FloatRegister getFloatParamRegister(unsigned int position) = 0;
    
    virtual Register getReturnRegister1() = 0;
    virtual Register getReturnRegister2() = 0;
    virtual Register getStackPointerRegister() = 0;
    virtual Register getBasePointerRegister() = 0;

    bool isFloatVar(std::shared_ptr<Variable> variable){
        return variable->type() == BaseType::FLOAT;
    }
    
    bool isIntVar(std::shared_ptr<Variable> variable){
        return variable->type() == BaseType::INT;
    }

    //TODO Verify these two functions
    void allocateStackSpace(unsigned int space){
        writer.stream() << "sub " << getStackPointerRegister() << ", " << space << std::endl;
    }

    void deallocateStackSpace(unsigned int space){
        writer.stream() << "add " << getStackPointerRegister() << ", " << space << std::endl;
    }
    
    std::string toString(std::shared_ptr<Variable> variable, int offset){
        auto position = variable->position();

        assert(!position.isTemporary());

        if(position.isStack()){
            return "[" + regToString(getBasePointerRegister()) + " + " + ::toString(-position.offset() + offset) + "]";
        } else if(position.isParameter()){
            //The case of array is special because only the address is passed, not the complete array
            if(variable->type().isArray())
            {
                Register reg = getReg();

                writer.stream() << "mov " << reg << ", [" + regToString(getBasePointerRegister()) + " + " << ::toString(position.offset()) << "]" << std::endl;

                registers.release(reg);

                return "[" + reg + "+" + ::toString(offset) + "]";
            } 
            //In the other cases, the value is passed, so we can compute the offset directly
            else {
                return "[" + regToString(getBasePointerRegister()) + " + " + ::toString(position.offset() + offset) + "]";
            }
        } else if(position.isGlobal()){
            return "[V" + position.name() + "+" + ::toString(offset) + "]";
        } 

        assert(false && "Should never get there");
    }
    
    std::string toString(std::shared_ptr<Variable> variable, tac::Argument offset){
        if(auto* ptr = boost::get<int>(&offset)){
            return toString(variable, *ptr);
        }
        
        assert(boost::get<std::shared_ptr<Variable>>(&offset));

        auto* offsetVariable = boost::get<std::shared_ptr<Variable>>(&offset);
        auto position = variable->position();

        auto offsetReg = getReg(*offsetVariable);
        
        assert(!position.isTemporary());
        
        if(position.isStack()){
            return "[" + regToString(getBasePointerRegister()) + " + " + ::toString(-1 * (position.offset())) + "]";//TODO Verify
        } else if(position.isParameter()){
            Register reg = getReg();
            
            writer.stream() << "mov " << reg << ", [" + regToString(getBasePointerRegister()) + " + " << ::toString(position.offset()) << "]" << std::endl;

            registers.release(reg);

            return "[" + reg + "+" + offsetReg + "]";
        } else if(position.isGlobal()){
            return "[" + offsetReg + "+V" + position.name() + "]";
        } 

        assert(false && "Should never get there");
    }
    <commit_msg>Fix bug with offset calculations when the variable is on the stack<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)
//=======================================================================

#ifndef INTEL_STATEMENT_COMPILER_H
#define INTEL_STATEMENT_COMPILER_H

#include <memory>
#include <unordered_set>

#include "assert.hpp"
#include "Utils.hpp"
#include "Registers.hpp"
#include "Compiler.hpp"
#include "PlatformDescriptor.hpp"

#include "tac/Utils.hpp"

using namespace eddic;

namespace eddic {

namespace as {

template<typename Register, typename FloatRegister>
struct IntelStatementCompiler {
    //The current function being compiled
    std::shared_ptr<tac::Function> function;
    
    AssemblyFileWriter& writer;
    Registers<Register> registers;
    Registers<FloatRegister> float_registers;

    std::unordered_set<std::shared_ptr<tac::BasicBlock>> blockUsage;

    std::unordered_set<std::shared_ptr<Variable>> written;

    bool last;
    bool ended;

    tac::Statement current;
    tac::Statement next;
   
    IntelStatementCompiler(AssemblyFileWriter& w, std::vector<Register> r, std::vector<FloatRegister> fr, std::shared_ptr<tac::Function> f) : function(f), writer(w), 
            registers(r, std::make_shared<Variable>("__fake_int__", newSimpleType(BaseType::INT), Position(PositionType::TEMPORARY))),
            float_registers(fr, std::make_shared<Variable>("__fake_float__", newSimpleType(BaseType::FLOAT), Position(PositionType::TEMPORARY))) {
        last = ended = false;        
    } 
    
    virtual void div(std::shared_ptr<tac::Quadruple> quadruple) = 0;
    virtual void mod(std::shared_ptr<tac::Quadruple> quadruple) = 0;
    
    virtual std::string getMnemonicSize() = 0;
    virtual std::string getFloatPrefix() = 0;
    
    virtual std::string getFloatMove() = 0;
    virtual std::string getFloatToInteger() = 0;
    virtual std::string getIntegerToFloat() = 0;
    virtual std::string getFloatAdd() = 0;
    virtual std::string getFloatSub() = 0;
    virtual std::string getFloatMul() = 0;
    virtual std::string getFloatDiv() = 0;
    virtual std::string getSizedMove() = 0;
   
    /* Management of parameter passing in registers */ 
    virtual Register getIntParamRegister(unsigned int position) = 0;
    virtual FloatRegister getFloatParamRegister(unsigned int position) = 0;
    
    virtual Register getReturnRegister1() = 0;
    virtual Register getReturnRegister2() = 0;
    virtual Register getStackPointerRegister() = 0;
    virtual Register getBasePointerRegister() = 0;

    bool isFloatVar(std::shared_ptr<Variable> variable){
        return variable->type() == BaseType::FLOAT;
    }
    
    bool isIntVar(std::shared_ptr<Variable> variable){
        return variable->type() == BaseType::INT;
    }

    //TODO Verify these two functions
    void allocateStackSpace(unsigned int space){
        writer.stream() << "sub " << getStackPointerRegister() << ", " << space << std::endl;
    }

    void deallocateStackSpace(unsigned int space){
        writer.stream() << "add " << getStackPointerRegister() << ", " << space << std::endl;
    }
    
    std::string toString(std::shared_ptr<Variable> variable, int offset){
        auto position = variable->position();

        assert(!position.isTemporary());

        if(position.isStack()){
            return "[" + regToString(getBasePointerRegister()) + " + " + ::toString(-position.offset() + offset) + "]";
        } else if(position.isParameter()){
            //The case of array is special because only the address is passed, not the complete array
            if(variable->type().isArray())
            {
                Register reg = getReg();

                writer.stream() << "mov " << reg << ", [" + regToString(getBasePointerRegister()) + " + " << ::toString(position.offset()) << "]" << std::endl;

                registers.release(reg);

                return "[" + reg + "+" + ::toString(offset) + "]";
            } 
            //In the other cases, the value is passed, so we can compute the offset directly
            else {
                return "[" + regToString(getBasePointerRegister()) + " + " + ::toString(position.offset() + offset) + "]";
            }
        } else if(position.isGlobal()){
            return "[V" + position.name() + "+" + ::toString(offset) + "]";
        } 

        assert(false && "Should never get there");
    }
    
    std::string toString(std::shared_ptr<Variable> variable, tac::Argument offset){
        if(auto* ptr = boost::get<int>(&offset)){
            return toString(variable, *ptr);
        }
        
        auto position = variable->position();
        assert(!position.isTemporary());
        
        assert(boost::get<std::shared_ptr<Variable>>(&offset));

        auto offsetVariable = boost::get<std::shared_ptr<Variable>>(offset);
        auto offsetReg = getReg(offsetVariable);
        
        if(position.isStack()){
            return "[" + regToString(getBasePointerRegister()) + " + " + regToString(offsetReg) + " + " + ::toString(-1 * (position.offset())) + "]";
        } else if(position.isParameter()){
            Register reg = getReg();
            
            writer.stream() << "mov " << reg << ", [" + regToString(getBasePointerRegister()) + " + " << ::toString(position.offset()) << "]" << std::endl;

            registers.release(reg);

            return "[" + reg + "+" + offsetReg + "]";
        } else if(position.isGlobal()){
            return "[" + offsetReg + "+V" + position.name() + "]";
        } 

        assert(false && "Should never get there");
    }
    
{'fraction_non_alphanumeric': 0.1671140358472595, 'fraction_numerical': 0.005368430167114036, 'mean_word_length': 3.1546762589928057, 'pattern_counts': {'":': 0, '<': 145, '<?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': '3417542', 'n_tokens_mistral': 3307, 'n_tokens_neox': 3186, 'n_words': 710}