use super::*;
use crate::{
asm_generation::fuel::{
compiler_constants::DATA_SECTION_REGISTER,
data_section::{DataId, DataSection},
},
fuel_prelude::fuel_asm::{self, op},
};
use either::Either;
use std::fmt::{self, Write};
use sway_types::span::Span;
const COMMENT_START_COLUMN: usize = 30;
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
pub enum AllocatedRegister {
Allocated(u8),
Constant(super::ConstantRegister),
}
impl fmt::Display for AllocatedRegister {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AllocatedRegister::Allocated(name) => write!(fmtr, "$r{name}"),
AllocatedRegister::Constant(name) => {
write!(fmtr, "{name}")
}
}
}
}
impl AllocatedRegister {
fn to_reg_id(&self) -> fuel_asm::RegId {
match self {
AllocatedRegister::Allocated(a) => fuel_asm::RegId::new(a + 16),
AllocatedRegister::Constant(constant) => constant.to_reg_id(),
}
}
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug)]
pub(crate) enum AllocatedOpcode {
ADD(AllocatedRegister, AllocatedRegister, AllocatedRegister),
ADDI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
AND(AllocatedRegister, AllocatedRegister, AllocatedRegister),
ANDI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
DIV(AllocatedRegister, AllocatedRegister, AllocatedRegister),
DIVI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
EQ(AllocatedRegister, AllocatedRegister, AllocatedRegister),
EXP(AllocatedRegister, AllocatedRegister, AllocatedRegister),
EXPI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
GT(AllocatedRegister, AllocatedRegister, AllocatedRegister),
LT(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MLOG(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MOD(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MODI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
MOVE(AllocatedRegister, AllocatedRegister),
MOVI(AllocatedRegister, VirtualImmediate18),
MROO(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MUL(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MULI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
NOOP,
NOT(AllocatedRegister, AllocatedRegister),
OR(AllocatedRegister, AllocatedRegister, AllocatedRegister),
ORI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
SLL(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SLLI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
SRL(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SRLI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
SUB(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SUBI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
XOR(AllocatedRegister, AllocatedRegister, AllocatedRegister),
XORI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
JMP(AllocatedRegister),
JI(VirtualImmediate24),
JNE(AllocatedRegister, AllocatedRegister, AllocatedRegister),
JNEI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
JNZI(AllocatedRegister, VirtualImmediate18),
RET(AllocatedRegister),
ALOC(AllocatedRegister),
CFEI(VirtualImmediate24),
CFSI(VirtualImmediate24),
LB(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
LW(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
MCL(AllocatedRegister, AllocatedRegister),
MCLI(AllocatedRegister, VirtualImmediate18),
MCP(AllocatedRegister, AllocatedRegister, AllocatedRegister),
MCPI(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
MEQ(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
SB(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
SW(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
BAL(AllocatedRegister, AllocatedRegister, AllocatedRegister),
BHEI(AllocatedRegister),
BHSH(AllocatedRegister, AllocatedRegister),
BURN(AllocatedRegister),
CALL(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
CB(AllocatedRegister),
CCP(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
CROO(AllocatedRegister, AllocatedRegister),
CSIZ(AllocatedRegister, AllocatedRegister),
LDC(AllocatedRegister, AllocatedRegister, AllocatedRegister),
LOG(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
LOGD(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
MINT(AllocatedRegister),
RETD(AllocatedRegister, AllocatedRegister),
RVRT(AllocatedRegister),
SMO(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
SCWQ(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SRW(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SRWQ(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
SWW(AllocatedRegister, AllocatedRegister, AllocatedRegister),
SWWQ(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
TIME(AllocatedRegister, AllocatedRegister),
TR(AllocatedRegister, AllocatedRegister, AllocatedRegister),
TRO(
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
AllocatedRegister,
),
ECR(AllocatedRegister, AllocatedRegister, AllocatedRegister),
K256(AllocatedRegister, AllocatedRegister, AllocatedRegister),
S256(AllocatedRegister, AllocatedRegister, AllocatedRegister),
FLAG(AllocatedRegister),
GM(AllocatedRegister, VirtualImmediate18),
GTF(AllocatedRegister, AllocatedRegister, VirtualImmediate12),
BLOB(VirtualImmediate24),
DataSectionOffsetPlaceholder,
DataSectionRegisterLoadPlaceholder,
LWDataId(AllocatedRegister, DataId),
Undefined,
}
impl AllocatedOpcode {
pub(crate) fn def_registers(&self) -> BTreeSet<&AllocatedRegister> {
use AllocatedOpcode::*;
(match self {
ADD(r1, _r2, _r3) => vec![r1],
ADDI(r1, _r2, _i) => vec![r1],
AND(r1, _r2, _r3) => vec![r1],
ANDI(r1, _r2, _i) => vec![r1],
DIV(r1, _r2, _r3) => vec![r1],
DIVI(r1, _r2, _i) => vec![r1],
EQ(r1, _r2, _r3) => vec![r1],
EXP(r1, _r2, _r3) => vec![r1],
EXPI(r1, _r2, _i) => vec![r1],
GT(r1, _r2, _r3) => vec![r1],
LT(r1, _r2, _r3) => vec![r1],
MLOG(r1, _r2, _r3) => vec![r1],
MOD(r1, _r2, _r3) => vec![r1],
MODI(r1, _r2, _i) => vec![r1],
MOVE(r1, _r2) => vec![r1],
MOVI(r1, _i) => vec![r1],
MROO(r1, _r2, _r3) => vec![r1],
MUL(r1, _r2, _r3) => vec![r1],
MULI(r1, _r2, _i) => vec![r1],
NOOP => vec![],
NOT(r1, _r2) => vec![r1],
OR(r1, _r2, _r3) => vec![r1],
ORI(r1, _r2, _i) => vec![r1],
SLL(r1, _r2, _r3) => vec![r1],
SLLI(r1, _r2, _i) => vec![r1],
SRL(r1, _r2, _r3) => vec![r1],
SRLI(r1, _r2, _i) => vec![r1],
SUB(r1, _r2, _r3) => vec![r1],
SUBI(r1, _r2, _i) => vec![r1],
XOR(r1, _r2, _r3) => vec![r1],
XORI(r1, _r2, _i) => vec![r1],
JMP(_r1) => vec![],
JI(_im) => vec![],
JNE(_r1, _r2, _r3) => vec![],
JNEI(_r1, _r2, _i) => vec![],
JNZI(_r1, _i) => vec![],
RET(_r1) => vec![],
ALOC(_r1) => vec![],
CFEI(_imm) => vec![],
CFSI(_imm) => vec![],
LB(r1, _r2, _i) => vec![r1],
LW(r1, _r2, _i) => vec![r1],
MCL(_r1, _r2) => vec![],
MCLI(_r1, _imm) => vec![],
MCP(_r1, _r2, _r3) => vec![],
MCPI(_r1, _r2, _imm) => vec![],
MEQ(r1, _r2, _r3, _r4) => vec![r1],
SB(_r1, _r2, _i) => vec![],
SW(_r1, _r2, _i) => vec![],
BAL(r1, _r2, _r3) => vec![r1],
BHEI(r1) => vec![r1],
BHSH(_r1, _r2) => vec![],
BURN(_r1) => vec![],
CALL(_r1, _r2, _r3, _r4) => vec![],
CB(_r1) => vec![],
CCP(_r1, _r2, _r3, _r4) => vec![],
CROO(_r1, _r2) => vec![],
CSIZ(r1, _r2) => vec![r1],
LDC(_r1, _r2, _r3) => vec![],
LOG(_r1, _r2, _r3, _r4) => vec![],
LOGD(_r1, _r2, _r3, _r4) => vec![],
MINT(_r1) => vec![],
RETD(_r1, _r2) => vec![],
RVRT(_r1) => vec![],
SMO(_r1, _r2, _r3, _r4) => vec![],
SCWQ(_r1, r2, _r3) => vec![r2],
SRW(r1, r2, _r3) => vec![r1, r2],
SRWQ(_r1, r2, _r3, _r4) => vec![r2],
SWW(_r1, r2, _r3) => vec![r2],
SWWQ(_r1, r2, _r3, _r4) => vec![r2],
TIME(r1, _r2) => vec![r1],
TR(_r1, _r2, _r3) => vec![],
TRO(_r1, _r2, _r3, _r4) => vec![],
ECR(_r1, _r2, _r3) => vec![],
K256(_r1, _r2, _r3) => vec![],
S256(_r1, _r2, _r3) => vec![],
FLAG(_r1) => vec![],
GM(r1, _imm) => vec![r1],
GTF(r1, _r2, _i) => vec![r1],
BLOB(_imm) => vec![],
DataSectionOffsetPlaceholder => vec![],
DataSectionRegisterLoadPlaceholder => vec![&AllocatedRegister::Constant(
ConstantRegister::DataSectionStart,
)],
LWDataId(r1, _i) => vec![r1],
Undefined => vec![],
})
.into_iter()
.collect()
}
}
impl fmt::Display for AllocatedOpcode {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
use AllocatedOpcode::*;
match self {
ADD(a, b, c) => write!(fmtr, "add {a} {b} {c}"),
ADDI(a, b, c) => write!(fmtr, "addi {a} {b} {c}"),
AND(a, b, c) => write!(fmtr, "and {a} {b} {c}"),
ANDI(a, b, c) => write!(fmtr, "andi {a} {b} {c}"),
DIV(a, b, c) => write!(fmtr, "div {a} {b} {c}"),
DIVI(a, b, c) => write!(fmtr, "divi {a} {b} {c}"),
EQ(a, b, c) => write!(fmtr, "eq {a} {b} {c}"),
EXP(a, b, c) => write!(fmtr, "exp {a} {b} {c}"),
EXPI(a, b, c) => write!(fmtr, "expi {a} {b} {c}"),
GT(a, b, c) => write!(fmtr, "gt {a} {b} {c}"),
LT(a, b, c) => write!(fmtr, "lt {a} {b} {c}"),
MLOG(a, b, c) => write!(fmtr, "mlog {a} {b} {c}"),
MOD(a, b, c) => write!(fmtr, "mod {a} {b} {c}"),
MODI(a, b, c) => write!(fmtr, "modi {a} {b} {c}"),
MOVE(a, b) => write!(fmtr, "move {a} {b}"),
MOVI(a, b) => write!(fmtr, "movi {a} {b}"),
MROO(a, b, c) => write!(fmtr, "mroo {a} {b} {c}"),
MUL(a, b, c) => write!(fmtr, "mul {a} {b} {c}"),
MULI(a, b, c) => write!(fmtr, "muli {a} {b} {c}"),
NOOP => write!(fmtr, "noop"),
NOT(a, b) => write!(fmtr, "not {a} {b}"),
OR(a, b, c) => write!(fmtr, "or {a} {b} {c}"),
ORI(a, b, c) => write!(fmtr, "ori {a} {b} {c}"),
SLL(a, b, c) => write!(fmtr, "sll {a} {b} {c}"),
SLLI(a, b, c) => write!(fmtr, "slli {a} {b} {c}"),
SRL(a, b, c) => write!(fmtr, "srl {a} {b} {c}"),
SRLI(a, b, c) => write!(fmtr, "srli {a} {b} {c}"),
SUB(a, b, c) => write!(fmtr, "sub {a} {b} {c}"),
SUBI(a, b, c) => write!(fmtr, "subi {a} {b} {c}"),
XOR(a, b, c) => write!(fmtr, "xor {a} {b} {c}"),
XORI(a, b, c) => write!(fmtr, "xori {a} {b} {c}"),
JMP(a) => write!(fmtr, "jmp {a}"),
JI(a) => write!(fmtr, "ji {a}"),
JNE(a, b, c) => write!(fmtr, "jne {a} {b} {c}"),
JNEI(a, b, c) => write!(fmtr, "jnei {a} {b} {c}"),
JNZI(a, b) => write!(fmtr, "jnzi {a} {b}"),
RET(a) => write!(fmtr, "ret {a}"),
ALOC(a) => write!(fmtr, "aloc {a}"),
CFEI(a) => write!(fmtr, "cfei {a}"),
CFSI(a) => write!(fmtr, "cfsi {a}"),
LB(a, b, c) => write!(fmtr, "lb {a} {b} {c}"),
LW(a, b, c) => write!(fmtr, "lw {a} {b} {c}"),
MCL(a, b) => write!(fmtr, "mcl {a} {b}"),
MCLI(a, b) => write!(fmtr, "mcli {a} {b}"),
MCP(a, b, c) => write!(fmtr, "mcp {a} {b} {c}"),
MCPI(a, b, c) => write!(fmtr, "mcpi {a} {b} {c}"),
MEQ(a, b, c, d) => write!(fmtr, "meq {a} {b} {c} {d}"),
SB(a, b, c) => write!(fmtr, "sb {a} {b} {c}"),
SW(a, b, c) => write!(fmtr, "sw {a} {b} {c}"),
BAL(a, b, c) => write!(fmtr, "bal {a} {b} {c}"),
BHEI(a) => write!(fmtr, "bhei {a}"),
BHSH(a, b) => write!(fmtr, "bhsh {a} {b}"),
BURN(a) => write!(fmtr, "burn {a}"),
CALL(a, b, c, d) => write!(fmtr, "call {a} {b} {c} {d}"),
CB(a) => write!(fmtr, "cb {a}"),
CCP(a, b, c, d) => write!(fmtr, "ccp {a} {b} {c} {d}"),
CROO(a, b) => write!(fmtr, "croo {a} {b}"),
CSIZ(a, b) => write!(fmtr, "csiz {a} {b}"),
LDC(a, b, c) => write!(fmtr, "ldc {a} {b} {c}"),
LOG(a, b, c, d) => write!(fmtr, "log {a} {b} {c} {d}"),
LOGD(a, b, c, d) => write!(fmtr, "logd {a} {b} {c} {d}"),
MINT(a) => write!(fmtr, "mint {a}"),
RETD(a, b) => write!(fmtr, "retd {a} {b}"),
RVRT(a) => write!(fmtr, "rvrt {a}"),
SMO(a, b, c, d) => write!(fmtr, "smo {a} {b} {c} {d}"),
SCWQ(a, b, c) => write!(fmtr, "scwq {a} {b} {c}"),
SRW(a, b, c) => write!(fmtr, "srw {a} {b} {c}"),
SRWQ(a, b, c, d) => write!(fmtr, "srwq {a} {b} {c} {d}"),
SWW(a, b, c) => write!(fmtr, "sww {a} {b} {c}"),
SWWQ(a, b, c, d) => write!(fmtr, "swwq {a} {b} {c} {d}"),
TIME(a, b) => write!(fmtr, "time {a} {b}"),
TR(a, b, c) => write!(fmtr, "tr {a} {b} {c}"),
TRO(a, b, c, d) => write!(fmtr, "tro {a} {b} {c} {d}"),
ECR(a, b, c) => write!(fmtr, "ecr {a} {b} {c}"),
K256(a, b, c) => write!(fmtr, "k256 {a} {b} {c}"),
S256(a, b, c) => write!(fmtr, "s256 {a} {b} {c}"),
FLAG(a) => write!(fmtr, "flag {a}"),
GM(a, b) => write!(fmtr, "gm {a} {b}"),
GTF(a, b, c) => write!(fmtr, "gtf {a} {b} {c}"),
BLOB(a) => write!(fmtr, "blob {a}"),
DataSectionOffsetPlaceholder => {
write!(
fmtr,
"DATA_SECTION_OFFSET[0..32]\nDATA_SECTION_OFFSET[32..64]"
)
}
DataSectionRegisterLoadPlaceholder => write!(fmtr, "lw $ds $is 1"),
LWDataId(a, b) => write!(fmtr, "lw {a} {b}"),
Undefined => write!(fmtr, "undefined op"),
}
}
}
#[derive(Clone, Debug)]
pub struct AllocatedOp {
pub(crate) opcode: AllocatedOpcode,
pub(crate) comment: String,
pub(crate) owning_span: Option<Span>,
}
impl fmt::Display for AllocatedOp {
fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut op_and_comment = self.opcode.to_string();
if !self.comment.is_empty() {
while op_and_comment.len() < COMMENT_START_COLUMN {
op_and_comment.push(' ');
}
write!(op_and_comment, "; {}", self.comment)?;
}
write!(fmtr, "{op_and_comment}")
}
}
type DoubleWideData = [u8; 8];
impl AllocatedOp {
pub(crate) fn to_fuel_asm(
&self,
offset_to_data_section: u64,
data_section: &mut DataSection,
) -> Either<Vec<fuel_asm::Instruction>, DoubleWideData> {
use AllocatedOpcode::*;
Either::Left(vec![match &self.opcode {
ADD(a, b, c) => op::ADD::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
ADDI(a, b, c) => op::ADDI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
AND(a, b, c) => op::AND::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
ANDI(a, b, c) => op::ANDI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
DIV(a, b, c) => op::DIV::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
DIVI(a, b, c) => op::DIVI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
EQ(a, b, c) => op::EQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
EXP(a, b, c) => op::EXP::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
EXPI(a, b, c) => op::EXPI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
GT(a, b, c) => op::GT::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
LT(a, b, c) => op::LT::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MLOG(a, b, c) => op::MLOG::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MOD(a, b, c) => op::MOD::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MODI(a, b, c) => op::MODI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
MOVE(a, b) => op::MOVE::new(a.to_reg_id(), b.to_reg_id()).into(),
MOVI(a, b) => op::MOVI::new(a.to_reg_id(), b.value.into()).into(),
MROO(a, b, c) => op::MROO::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MUL(a, b, c) => op::MUL::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MULI(a, b, c) => op::MULI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
NOOP => op::NOOP::new().into(),
NOT(a, b) => op::NOT::new(a.to_reg_id(), b.to_reg_id()).into(),
OR(a, b, c) => op::OR::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
ORI(a, b, c) => op::ORI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
SLL(a, b, c) => op::SLL::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SLLI(a, b, c) => op::SLLI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
SRL(a, b, c) => op::SRL::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SRLI(a, b, c) => op::SRLI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
SUB(a, b, c) => op::SUB::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SUBI(a, b, c) => op::SUBI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
XOR(a, b, c) => op::XOR::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
XORI(a, b, c) => op::XORI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
JMP(a) => op::JMP::new(a.to_reg_id()).into(),
JI(a) => op::JI::new(a.value.into()).into(),
JNE(a, b, c) => op::JNE::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
JNEI(a, b, c) => op::JNEI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
JNZI(a, b) => op::JNZI::new(a.to_reg_id(), b.value.into()).into(),
RET(a) => op::RET::new(a.to_reg_id()).into(),
ALOC(a) => op::ALOC::new(a.to_reg_id()).into(),
CFEI(a) => op::CFEI::new(a.value.into()).into(),
CFSI(a) => op::CFSI::new(a.value.into()).into(),
LB(a, b, c) => op::LB::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
LW(a, b, c) => op::LW::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
MCL(a, b) => op::MCL::new(a.to_reg_id(), b.to_reg_id()).into(),
MCLI(a, b) => op::MCLI::new(a.to_reg_id(), b.value.into()).into(),
MCP(a, b, c) => op::MCP::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
MCPI(a, b, c) => op::MCPI::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
MEQ(a, b, c, d) => {
op::MEQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
SB(a, b, c) => op::SB::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
SW(a, b, c) => op::SW::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
BAL(a, b, c) => op::BAL::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
BHEI(a) => op::BHEI::new(a.to_reg_id()).into(),
BHSH(a, b) => op::BHSH::new(a.to_reg_id(), b.to_reg_id()).into(),
BURN(a) => op::BURN::new(a.to_reg_id()).into(),
CALL(a, b, c, d) => {
op::CALL::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
CB(a) => op::CB::new(a.to_reg_id()).into(),
CCP(a, b, c, d) => {
op::CCP::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
CROO(a, b) => op::CROO::new(a.to_reg_id(), b.to_reg_id()).into(),
CSIZ(a, b) => op::CSIZ::new(a.to_reg_id(), b.to_reg_id()).into(),
LDC(a, b, c) => op::LDC::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
LOG(a, b, c, d) => {
op::LOG::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
LOGD(a, b, c, d) => {
op::LOGD::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
MINT(a) => op::MINT::new(a.to_reg_id()).into(),
RETD(a, b) => op::RETD::new(a.to_reg_id(), b.to_reg_id()).into(),
RVRT(a) => op::RVRT::new(a.to_reg_id()).into(),
SMO(a, b, c, d) => {
op::SMO::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
SCWQ(a, b, c) => op::SCWQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SRW(a, b, c) => op::SRW::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SRWQ(a, b, c, d) => {
op::SRWQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
SWW(a, b, c) => op::SWW::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
SWWQ(a, b, c, d) => {
op::SWWQ::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
TIME(a, b) => op::TIME::new(a.to_reg_id(), b.to_reg_id()).into(),
TR(a, b, c) => op::TR::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
TRO(a, b, c, d) => {
op::TRO::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id(), d.to_reg_id()).into()
}
ECR(a, b, c) => op::ECR::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
K256(a, b, c) => op::K256::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
S256(a, b, c) => op::S256::new(a.to_reg_id(), b.to_reg_id(), c.to_reg_id()).into(),
FLAG(a) => op::FLAG::new(a.to_reg_id()).into(),
GM(a, b) => op::GM::new(a.to_reg_id(), b.value.into()).into(),
GTF(a, b, c) => op::GTF::new(a.to_reg_id(), b.to_reg_id(), c.value.into()).into(),
BLOB(a) => {
return Either::Left(
std::iter::repeat(op::NOOP::new().into())
.take(a.value as usize)
.collect(),
)
}
DataSectionOffsetPlaceholder => {
return Either::Right(offset_to_data_section.to_be_bytes())
}
DataSectionRegisterLoadPlaceholder => op::LW::new(
fuel_asm::RegId::new(DATA_SECTION_REGISTER),
ConstantRegister::InstructionStart.to_reg_id(),
1.into(),
)
.into(),
LWDataId(a, b) => {
return Either::Left(realize_lw(a, b, data_section, offset_to_data_section))
}
Undefined => unreachable!("Sway cannot generate undefined ASM opcodes"),
}])
}
}
fn realize_lw(
dest: &AllocatedRegister,
data_id: &DataId,
data_section: &mut DataSection,
offset_to_data_section: u64,
) -> Vec<fuel_asm::Instruction> {
let offset_bytes = data_section.data_id_to_offset(data_id) as u64;
let offset_words = offset_bytes / 8;
let offset = match VirtualImmediate12::new(offset_words, Span::new(" ".into(), 0, 0, None).unwrap()) {
Ok(value) => value,
Err(_) => panic!("Unable to offset into the data section more than 2^12 bits. Unsupported data section length.")
};
let has_copy_type = data_section.has_copy_type(data_id).expect(
"Internal miscalculation in data section -- data id did not match up to any actual data",
);
if !has_copy_type {
let pointer_offset_from_instruction_start = offset_to_data_section + offset_bytes;
let data_id_for_pointer =
data_section.append_pointer(pointer_offset_from_instruction_start);
let mut buf = Vec::with_capacity(2);
buf.append(&mut realize_lw(
dest,
&data_id_for_pointer,
data_section,
offset_to_data_section,
));
buf.push(
fuel_asm::op::ADD::new(
dest.to_reg_id(),
dest.to_reg_id(),
ConstantRegister::InstructionStart.to_reg_id(),
)
.into(),
);
buf
} else {
vec![fuel_asm::op::LW::new(
dest.to_reg_id(),
fuel_asm::RegId::new(DATA_SECTION_REGISTER),
offset.value.into(),
)
.into()]
}
}