use sway_error::{
error::CompileError,
handler::{ErrorEmitted, Handler},
};
use sway_types::Span;
use crate::asm_lang::allocated_ops::{AllocatedInstruction, AllocatedOp};
pub(crate) fn check_script_opcodes(
handler: &Handler,
ops: &[AllocatedOp],
) -> Result<(), ErrorEmitted> {
use AllocatedInstruction::*;
handler.scope(|handler| {
for op in ops {
match &op.opcode {
GM(_, imm) if (1..=2).contains(&imm.value()) => {
handler.emit_err(CompileError::GMFromExternalContext {
span: get_op_span(op),
});
}
MINT(..) => {
handler.emit_err(CompileError::MintFromExternalContext {
span: get_op_span(op),
});
}
BURN(..) => {
handler.emit_err(CompileError::BurnFromExternalContext {
span: get_op_span(op),
});
}
SWW(..) | SRW(..) | SRWQ(..) | SWWQ(..) => {
handler.emit_err(CompileError::ContractStorageFromExternalContext {
span: get_op_span(op),
});
}
_ => (),
}
}
Ok(())
})
}
pub(crate) fn check_predicate_opcodes(
handler: &Handler,
ops: &[AllocatedOp],
) -> Result<(), ErrorEmitted> {
use AllocatedInstruction::*;
handler.scope(|handler| {
for op in ops.iter() {
let invalid_opcode = |name_str: &str| {
handler.emit_err(CompileError::InvalidOpcodeFromPredicate {
opcode: name_str.to_string(),
span: get_op_span(op),
});
};
match op.opcode.clone() {
BAL(..) => invalid_opcode("BAL"),
BHEI(..) => invalid_opcode("BHEI"),
BHSH(..) => invalid_opcode("BHSH"),
BURN(..) => invalid_opcode("BURN"),
CALL(..) => invalid_opcode("CALL"),
CB(..) => invalid_opcode("CB"),
CCP(..) => invalid_opcode("CCP"),
CROO(..) => invalid_opcode("CROO"),
CSIZ(..) => invalid_opcode("CSIZ"),
GM(_, imm) if (1..=2).contains(&imm.value()) => {
handler.emit_err(CompileError::GMFromExternalContext {
span: get_op_span(op),
});
}
LOG(..) => invalid_opcode("LOG"),
LOGD(..) => invalid_opcode("LOGD"),
MINT(..) => invalid_opcode("MINT"),
RETD(..) => invalid_opcode("RETD"),
SMO(..) => invalid_opcode("SMO"),
SRW(..) => invalid_opcode("SRW"),
SRWQ(..) => invalid_opcode("SRWQ"),
SWW(..) => invalid_opcode("SWW"),
SWWQ(..) => invalid_opcode("SWWQ"),
TIME(..) => invalid_opcode("TIME"),
TR(..) => invalid_opcode("TR"),
TRO(..) => invalid_opcode("TRO"),
_ => (),
};
}
Ok(())
})
}
fn get_op_span(op: &AllocatedOp) -> Span {
let default_span =
sway_types::span::Span::new("no span found for opcode".into(), 0, 1, None).unwrap();
op.owning_span
.clone()
.unwrap_or_else(|| default_span.clone())
}