sway-core 0.35.3

Sway core language.
Documentation
use crate::fuel_prelude::fuel_asm;
use std::fmt;

/// Represents virtual registers that have yet to be allocated.
/// Note that only the Virtual variant will be allocated, and the Constant variant refers to
/// reserved registers.
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
pub enum VirtualRegister {
    Virtual(String),
    Constant(ConstantRegister),
}

impl From<&VirtualRegister> for VirtualRegister {
    fn from(register: &VirtualRegister) -> VirtualRegister {
        register.clone()
    }
}

impl From<ConstantRegister> for VirtualRegister {
    fn from(constant_register: ConstantRegister) -> Self {
        VirtualRegister::Constant(constant_register)
    }
}

impl fmt::Display for VirtualRegister {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            VirtualRegister::Virtual(name) => write!(f, "$r{name}"),
            VirtualRegister::Constant(name) => {
                write!(f, "{name}")
            }
        }
    }
}

#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
/// These are the special registers defined in the spec
pub enum ConstantRegister {
    // Below are VM-reserved registers
    Zero,
    One,
    Overflow,
    ProgramCounter,
    StackStartPointer,
    StackPointer,
    FramePointer,
    HeapPointer,
    Error,
    GlobalGas,
    ContextGas,
    Balance,
    InstructionStart,
    ReturnValue,
    ReturnLength,
    Flags,

    // Below are compiler-reserved registers
    DataSectionStart,
    CallReturnAddress,
    CallReturnValue,
    Scratch,

    // Registers for the first NUM_ARG_REGISTERS function arguments.
    FuncArg0,
    FuncArg1,
    FuncArg2,
    FuncArg3,
    FuncArg4,
    FuncArg5,
}

use crate::asm_generation::fuel::compiler_constants;

impl ConstantRegister {
    pub(crate) fn to_reg_id(self) -> fuel_asm::RegId {
        use ConstantRegister::*;
        match self {
            Zero => fuel_asm::RegId::ZERO,
            One => fuel_asm::RegId::ONE,
            Overflow => fuel_asm::RegId::OF,
            ProgramCounter => fuel_asm::RegId::PC,
            StackStartPointer => fuel_asm::RegId::SSP,
            StackPointer => fuel_asm::RegId::SP,
            FramePointer => fuel_asm::RegId::FP,
            HeapPointer => fuel_asm::RegId::HP,
            Error => fuel_asm::RegId::ERR,
            GlobalGas => fuel_asm::RegId::GGAS,
            ContextGas => fuel_asm::RegId::CGAS,
            Balance => fuel_asm::RegId::BAL,
            InstructionStart => fuel_asm::RegId::IS,
            ReturnValue => fuel_asm::RegId::RET,
            ReturnLength => fuel_asm::RegId::RETL,
            Flags => fuel_asm::RegId::FLAG,

            DataSectionStart => fuel_asm::RegId::new(compiler_constants::DATA_SECTION_REGISTER),
            CallReturnAddress => fuel_asm::RegId::new(compiler_constants::RETURN_ADDRESS_REGISTER),
            CallReturnValue => fuel_asm::RegId::new(compiler_constants::RETURN_VALUE_REGISTER),
            Scratch => fuel_asm::RegId::new(compiler_constants::SCRATCH_REGISTER),

            FuncArg0 => fuel_asm::RegId::new(compiler_constants::ARG_REG0),
            FuncArg1 => fuel_asm::RegId::new(compiler_constants::ARG_REG1),
            FuncArg2 => fuel_asm::RegId::new(compiler_constants::ARG_REG2),
            FuncArg3 => fuel_asm::RegId::new(compiler_constants::ARG_REG3),
            FuncArg4 => fuel_asm::RegId::new(compiler_constants::ARG_REG4),
            FuncArg5 => fuel_asm::RegId::new(compiler_constants::ARG_REG5),
        }
    }

    pub(crate) const ARG_REGS: [ConstantRegister; compiler_constants::NUM_ARG_REGISTERS as usize] = [
        ConstantRegister::FuncArg0,
        ConstantRegister::FuncArg1,
        ConstantRegister::FuncArg2,
        ConstantRegister::FuncArg3,
        ConstantRegister::FuncArg4,
        ConstantRegister::FuncArg5,
    ];
}

impl fmt::Display for ConstantRegister {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use ConstantRegister::*;
        let text = match self {
            Zero => "$zero",
            One => "$one",
            Overflow => "$of",
            ProgramCounter => "$pc",
            StackStartPointer => "$ssp",
            StackPointer => "$sp",
            FramePointer => "$fp",
            HeapPointer => "$hp",
            Error => "$err",
            GlobalGas => "$ggas",
            ContextGas => "$cgas",
            Balance => "$bal",
            InstructionStart => "$is",
            ReturnValue => "$ret",
            ReturnLength => "$retl",
            Flags => "$flag",
            // two `$` signs denotes this is a compiler-reserved register and not a
            // VM-reserved register
            DataSectionStart => "$$ds",
            CallReturnAddress => "$$reta",
            CallReturnValue => "$$retv",
            Scratch => "$$tmp",
            FuncArg0 => "$$arg0",
            FuncArg1 => "$$arg1",
            FuncArg2 => "$$arg2",
            FuncArg3 => "$$arg3",
            FuncArg4 => "$$arg4",
            FuncArg5 => "$$arg5",
        };
        write!(f, "{text}")
    }
}