use crate::decompiler::ir::{BinOp, Literal, UnaryOp};
use crate::instruction::{Instruction, OpCode, Operand};
pub(super) fn syscall_effect(instr: &Instruction) -> (usize, bool) {
if let Some(Operand::Syscall(hash)) = &instr.operand {
if let Some(info) = crate::syscalls::lookup(*hash) {
return (info.param_count as usize, info.returns_value);
}
}
(0, true)
}
pub(super) fn literal_for_push(op: OpCode, instr: &Instruction) -> Option<Literal> {
use OpCode::*;
match op {
Push0 => Some(Literal::Int(0)),
Push1 => Some(Literal::Int(1)),
Push2 => Some(Literal::Int(2)),
Push3 => Some(Literal::Int(3)),
Push4 => Some(Literal::Int(4)),
Push5 => Some(Literal::Int(5)),
Push6 => Some(Literal::Int(6)),
Push7 => Some(Literal::Int(7)),
Push8 => Some(Literal::Int(8)),
Push9 => Some(Literal::Int(9)),
Push10 => Some(Literal::Int(10)),
Push11 => Some(Literal::Int(11)),
Push12 => Some(Literal::Int(12)),
Push13 => Some(Literal::Int(13)),
Push14 => Some(Literal::Int(14)),
Push15 => Some(Literal::Int(15)),
Push16 => Some(Literal::Int(16)),
PushM1 => Some(Literal::Int(-1)),
PushT => Some(Literal::Bool(true)),
PushF => Some(Literal::Bool(false)),
PushNull => Some(Literal::Null),
Pushint8 | Pushint16 | Pushint32 | Pushint64 => match &instr.operand {
Some(Operand::I8(v)) => Some(Literal::Int(i64::from(*v))),
Some(Operand::I16(v)) => Some(Literal::Int(i64::from(*v))),
Some(Operand::I32(v)) => Some(Literal::Int(i64::from(*v))),
Some(Operand::I64(v)) => Some(Literal::Int(*v)),
_ => None,
},
Pushint128 | Pushint256 => match &instr.operand {
Some(Operand::Bytes(b)) => Some(Literal::BigInt(hex::encode(b))),
_ => None,
},
Pushdata1 | Pushdata2 | Pushdata4 => match &instr.operand {
Some(Operand::Bytes(b)) => Some(Literal::Bytes(b.clone())),
_ => None,
},
_ => None,
}
}
pub(super) fn binary_op_for(op: OpCode) -> Option<BinOp> {
use OpCode::*;
Some(match op {
Add => BinOp::Add,
Sub => BinOp::Sub,
Mul => BinOp::Mul,
Div => BinOp::Div,
Mod => BinOp::Mod,
Pow => BinOp::Pow,
Shl => BinOp::Shl,
Shr => BinOp::Shr,
And => BinOp::And,
Or => BinOp::Or,
Xor => BinOp::Xor,
Equal | Numequal => BinOp::Eq,
Notequal | Numnotequal => BinOp::Ne,
Lt => BinOp::Lt,
Le => BinOp::Le,
Gt => BinOp::Gt,
Ge => BinOp::Ge,
Booland => BinOp::LogicalAnd,
Boolor => BinOp::LogicalOr,
_ => return None,
})
}
pub(super) fn unary_op_for(op: OpCode) -> Option<UnaryOp> {
use OpCode::*;
Some(match op {
Inc => UnaryOp::Inc,
Dec => UnaryOp::Dec,
Negate => UnaryOp::Neg,
Abs => UnaryOp::Abs,
Sign => UnaryOp::Sign,
Not => UnaryOp::LogicalNot,
Invert => UnaryOp::Not,
_ => return None,
})
}
pub(super) fn mnemonic(op: OpCode) -> String {
format!("{op:?}").to_lowercase()
}