diff --git a/androscalpel/src/instructions.rs b/androscalpel/src/instructions.rs index a141920..f0b8850 100644 --- a/androscalpel/src/instructions.rs +++ b/androscalpel/src/instructions.rs @@ -15,7 +15,6 @@ use androscalpel_serializer::Instruction as InsFormat; use androscalpel_serializer::Serializable; use anyhow::anyhow; -use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; use std::collections::{HashMap, HashSet}; @@ -32,8 +31,9 @@ const I32_MIN_AS_I64: i64 = i32::MIN as i64; const I32_MAX_AS_I64: i64 = i32::MAX as i64; const U16_MAX_AS_USIZE: usize = u16::MAX as usize; -// TODO: impl PartialEq and Eq for call site to derive them here +// TODO: impl Eq for call site to derive here? #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +#[pyclass] pub enum Instruction { /// Waste a cycle. Nop {}, @@ -888,62 +888,20 @@ impl Visitable for Instruction { obj: _, field, } => v.visit_field_id(field), - Self::SGet { - to: _, - field, - } => v.visit_field_id(field), - Self::SGetWide { - to: _, - field, - } => v.visit_field_id(field), - Self::SGetObject { - to: _, - field, - } => v.visit_field_id(field), - Self::SGetBoolean { - to: _, - field, - } => v.visit_field_id(field),, - Self::SGetByte { - to: _, - field, - } => v.visit_field_id(field),, - Self::SGetChar { - to: _, - field, - } => v.visit_field_id(field),, - Self::SGetShort { - to: _, - field, - } => v.visit_field_id(field),, - Self::SPut { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutWide { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutObject { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutBoolean { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutByte { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutChar { - from: _, - field, - } => v.visit_field_id(field),, - Self::SPutShort { - from: _, - field, - } => v.visit_field_id(field),, + Self::SGet { to: _, field } => v.visit_field_id(field), + Self::SGetWide { to: _, field } => v.visit_field_id(field), + Self::SGetObject { to: _, field } => v.visit_field_id(field), + Self::SGetBoolean { to: _, field } => v.visit_field_id(field), + Self::SGetByte { to: _, field } => v.visit_field_id(field), + Self::SGetChar { to: _, field } => v.visit_field_id(field), + Self::SGetShort { to: _, field } => v.visit_field_id(field), + Self::SPut { from: _, field } => v.visit_field_id(field), + Self::SPutWide { from: _, field } => v.visit_field_id(field), + Self::SPutObject { from: _, field } => v.visit_field_id(field), + Self::SPutBoolean { from: _, field } => v.visit_field_id(field), + Self::SPutByte { from: _, field } => v.visit_field_id(field), + Self::SPutChar { from: _, field } => v.visit_field_id(field), + Self::SPutShort { from: _, field } => v.visit_field_id(field), Self::InvokeVirtual { method, args: _ } => v.visit_method_id(method), Self::InvokeSuper { method, args: _ } => v.visit_method_id(method), Self::InvokeDirect { method, args: _ } => v.visit_method_id(method), @@ -1238,608 +1196,2214 @@ impl Visitable for Instruction { } Ok(()) } - Self::Label { name: _ } => todo!(), + Self::Label { name: _ } => Ok(()), } } } impl VisitableMut for Instruction { - fn default_visit_mut(self, _visitor: &mut V) -> Result { + fn default_visit_mut(self, v: &mut V) -> Result { match self { Self::Nop {} => Ok(self), - Self::Move(_ins) => todo!(), - Self::MoveWide(_ins) => todo!(), - Self::MoveObject(_ins) => todo!(), - Self::MoveResult(_ins) => todo!(), - Self::MoveResultWide(_ins) => todo!(), - Self::MoveException(_ins) => todo!(), - Self::MoveResultObject(_ins) => todo!(), - Self::ReturnVoid(_ins) => todo!(), - Self::Return(_ins) => todo!(), - Self::ReturnWide(_ins) => todo!(), - Self::ReturnObject(_ins) => todo!(), - Self::Const(_ins) => todo!(), - Self::ConstWide(_ins) => todo!(), - Self::ConstString(_ins) => todo!(), - Self::ConstClass(_ins) => todo!(), - Self::MonitorEnter(_ins) => todo!(), - Self::MonitorExit(_ins) => todo!(), - Self::CheckCast(_ins) => todo!(), - Self::InstanceOf(_ins) => todo!(), - Self::ArrayLength(_ins) => todo!(), - Self::NewInstance(_ins) => todo!(), - Self::NewArray(_ins) => todo!(), - Self::FilledNewArray(_ins) => todo!(), - Self::FillArrayData(_ins) => todo!(), - Self::Throw(_ins) => todo!(), - Self::Goto(_ins) => todo!(), - Self::Switch(_ins) => todo!(), - Self::CmpLFloat(_ins) => todo!(), - Self::CmpGFloat(_ins) => todo!(), - Self::CmpLDouble(_ins) => todo!(), - Self::CmpGDouble(_ins) => todo!(), - Self::CmpLong(_ins) => todo!(), - Self::IfEq(_ins) => todo!(), - Self::IfNe(_ins) => todo!(), - Self::IfLt(_ins) => todo!(), - Self::IfGe(_ins) => todo!(), - Self::IfGt(_ins) => todo!(), - Self::IfLe(_ins) => todo!(), - Self::IfEqZ(_ins) => todo!(), - Self::IfNeZ(_ins) => todo!(), - Self::IfLtZ(_ins) => todo!(), - Self::IfGeZ(_ins) => todo!(), - Self::IfGtZ(_ins) => todo!(), - Self::IfLeZ(_ins) => todo!(), - Self::AGet(_ins) => todo!(), - Self::AGetWide(_ins) => todo!(), - Self::AGetObject(_ins) => todo!(), - Self::AGetBoolean(_ins) => todo!(), - Self::AGetByte(_ins) => todo!(), - Self::AGetChar(_ins) => todo!(), - Self::AGetShort(_ins) => todo!(), - Self::APut(_ins) => todo!(), - Self::APutWide(_ins) => todo!(), - Self::APutObject(_ins) => todo!(), - Self::APutBoolean(_ins) => todo!(), - Self::APutByte(_ins) => todo!(), - Self::APutChar(_ins) => todo!(), - Self::APutShort(_ins) => todo!(), - Self::IGet(_ins) => todo!(), - Self::IGetWide(_ins) => todo!(), - Self::IGetObject(_ins) => todo!(), - Self::IGetBoolean(_ins) => todo!(), - Self::IGetByte(_ins) => todo!(), - Self::IGetChar(_ins) => todo!(), - Self::IGetShort(_ins) => todo!(), - Self::IPut(_ins) => todo!(), - Self::IPutWide(_ins) => todo!(), - Self::IPutObject(_ins) => todo!(), - Self::IPutBoolean(_ins) => todo!(), - Self::IPutByte(_ins) => todo!(), - Self::IPutChar(_ins) => todo!(), - Self::IPutShort(_ins) => todo!(), - Self::SGet(_ins) => todo!(), - Self::SGetWide(_ins) => todo!(), - Self::SGetObject(_ins) => todo!(), - Self::SGetBoolean(_ins) => todo!(), - Self::SGetByte(_ins) => todo!(), - Self::SGetChar(_ins) => todo!(), - Self::SGetShort(_ins) => todo!(), - Self::SPut(_ins) => todo!(), - Self::SPutWide(_ins) => todo!(), - Self::SPutObject(_ins) => todo!(), - Self::SPutBoolean(_ins) => todo!(), - Self::SPutByte(_ins) => todo!(), - Self::SPutChar(_ins) => todo!(), - Self::SPutShort(_ins) => todo!(), - Self::InvokeVirtual(_ins) => todo!(), - Self::InvokeSuper(_ins) => todo!(), - Self::InvokeDirect(_ins) => todo!(), - Self::InvokeStatic(_ins) => todo!(), - Self::InvokeInterface(_ins) => todo!(), - Self::NegInt(_ins) => todo!(), - Self::NotInt(_ins) => todo!(), - Self::NegLong(_ins) => todo!(), - Self::NotLong(_ins) => todo!(), - Self::NegFloat(_ins) => todo!(), - Self::NegDouble(_ins) => todo!(), - Self::IntToLong(_ins) => todo!(), - Self::IntToFloat(_ins) => todo!(), - Self::IntToDouble(_ins) => todo!(), - Self::LongToInt(_ins) => todo!(), - Self::LongToFloat(_ins) => todo!(), - Self::LongToDouble(_ins) => todo!(), - Self::FloatToInt(_ins) => todo!(), - Self::FloatToLong(_ins) => todo!(), - Self::FloatToDouble(_ins) => todo!(), - Self::DoubleToInt(_ins) => todo!(), - Self::DoubleToLong(_ins) => todo!(), - Self::DoubleToFloat(_ins) => todo!(), - Self::IntToByte(_ins) => todo!(), - Self::IntToChar(_ins) => todo!(), - Self::IntToShort(_ins) => todo!(), - Self::AddInt(_ins) => todo!(), - Self::SubInt(_ins) => todo!(), - Self::MulInt(_ins) => todo!(), - Self::DivInt(_ins) => todo!(), - Self::RemInt(_ins) => todo!(), - Self::AndInt(_ins) => todo!(), - Self::OrInt(_ins) => todo!(), - Self::XorInt(_ins) => todo!(), - Self::ShlInt(_ins) => todo!(), - Self::ShrInt(_ins) => todo!(), - Self::UshrInt(_ins) => todo!(), - Self::AddLong(_ins) => todo!(), - Self::SubLong(_ins) => todo!(), - Self::MulLong(_ins) => todo!(), - Self::DivLong(_ins) => todo!(), - Self::RemLong(_ins) => todo!(), - Self::AndLong(_ins) => todo!(), - Self::OrLong(_ins) => todo!(), - Self::XorLong(_ins) => todo!(), - Self::ShlLong(_ins) => todo!(), - Self::ShrLong(_ins) => todo!(), - Self::UshrLong(_ins) => todo!(), - Self::AddFloat(_ins) => todo!(), - Self::SubFloat(_ins) => todo!(), - Self::MulFloat(_ins) => todo!(), - Self::DivFloat(_ins) => todo!(), - Self::RemFloat(_ins) => todo!(), - Self::AddDouble(_ins) => todo!(), - Self::SubDouble(_ins) => todo!(), - Self::MulDouble(_ins) => todo!(), - Self::DivDouble(_ins) => todo!(), - Self::RemDouble(_ins) => todo!(), - Self::AddInt2Addr(_ins) => todo!(), - Self::SubInt2Addr(_ins) => todo!(), - Self::MulInt2Addr(_ins) => todo!(), - Self::DivInt2Addr(_ins) => todo!(), - Self::RemInt2Addr(_ins) => todo!(), - Self::AndInt2Addr(_ins) => todo!(), - Self::OrInt2Addr(_ins) => todo!(), - Self::XorInt2Addr(_ins) => todo!(), - Self::ShlInt2Addr(_ins) => todo!(), - Self::ShrInt2Addr(_ins) => todo!(), - Self::UshrInt2Addr(_ins) => todo!(), - Self::AddLong2Addr(_ins) => todo!(), - Self::SubLong2Addr(_ins) => todo!(), - Self::MulLong2Addr(_ins) => todo!(), - Self::DivLong2Addr(_ins) => todo!(), - Self::RemLong2Addr(_ins) => todo!(), - Self::AndLong2Addr(_ins) => todo!(), - Self::OrLong2Addr(_ins) => todo!(), - Self::XorLong2Addr(_ins) => todo!(), - Self::ShlLong2Addr(_ins) => todo!(), - Self::ShrLong2Addr(_ins) => todo!(), - Self::UshrLong2Addr(_ins) => todo!(), - Self::AddFloat2Addr(_ins) => todo!(), - Self::SubFloat2Addr(_ins) => todo!(), - Self::MulFloat2Addr(_ins) => todo!(), - Self::DivFloat2Addr(_ins) => todo!(), - Self::RemFloat2Addr(_ins) => todo!(), - Self::AddDouble2Addr(_ins) => todo!(), - Self::SubDouble2Addr(_ins) => todo!(), - Self::MulDouble2Addr(_ins) => todo!(), - Self::DivDouble2Addr(_ins) => todo!(), - Self::RemDouble2Addr(_ins) => todo!(), - Self::AddIntLit(_ins) => todo!(), - Self::RsubIntLit(_ins) => todo!(), - Self::MulIntLit(_ins) => todo!(), - Self::DivIntLit(_ins) => todo!(), - Self::RemIntLit(_ins) => todo!(), - Self::AndIntLit(_ins) => todo!(), - Self::OrIntLit(_ins) => todo!(), - Self::XorIntLit(_ins) => todo!(), - Self::ShlIntLit(_ins) => todo!(), - Self::ShrIntLit(_ins) => todo!(), - Self::UshrIntLit(_ins) => todo!(), - Self::InvokePolymorphic(_ins) => todo!(), - Self::InvokeCustom(_ins) => todo!(), - Self::ConstMethodHandle(_ins) => todo!(), - Self::ConstMethodType(_ins) => todo!(), - Self::Try(_ins) => todo!(), - Self::Label(_ins) => todo!(), + Self::Move { from: _, to: _ } => Ok(self), + Self::MoveWide { from: _, to: _ } => Ok(self), + Self::MoveObject { from: _, to: _ } => Ok(self), + Self::MoveResult { to: _ } => Ok(self), + Self::MoveResultWide { to: _ } => Ok(self), + Self::MoveException { to: _ } => Ok(self), + Self::MoveResultObject { to: _ } => Ok(self), + Self::ReturnVoid {} => Ok(self), + Self::Return { reg: _ } => Ok(self), + Self::ReturnWide { reg: _ } => Ok(self), + Self::ReturnObject { reg: _ } => Ok(self), + Self::Const { reg: _, lit: _ } => Ok(self), + Self::ConstWide { reg: _, lit: _ } => Ok(self), + Self::ConstString { reg, lit } => Ok(Self::ConstString { + reg, + lit: v.visit_string(lit)?, + }), + Self::ConstClass { reg, lit } => Ok(Self::ConstClass { + reg, + lit: v.visit_type(lit)?, + }), + Self::MonitorEnter { reg: _ } => Ok(self), + Self::MonitorExit { reg: _ } => Ok(self), + Self::CheckCast { reg, lit } => Ok(Self::CheckCast { + reg, + lit: v.visit_type(lit)?, + }), + Self::InstanceOf { dest, obj, lit } => Ok(Self::InstanceOf { + dest, + obj, + lit: v.visit_type(lit)?, + }), + Self::ArrayLength { dest: _, arr: _ } => Ok(self), + Self::NewInstance { reg, lit } => Ok(Self::NewInstance { + reg, + lit: v.visit_type(lit)?, + }), + Self::NewArray { reg, size_reg, lit } => Ok(Self::NewArray { + reg, + size_reg, + lit: v.visit_type(lit)?, + }), + Self::FilledNewArray { type_, reg_values } => Ok(Self::FilledNewArray { + type_: v.visit_type(type_)?, + reg_values, + }), + Self::FillArrayData { + arr: _, + elt_width: _, + data: _, + } => Ok(self), + Self::Throw { reg: _ } => Ok(self), + Self::Goto { label: _ } => Ok(self), + Self::Switch { + reg: _, + branches: _, + } => Ok(self), + Self::CmpLFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::CmpGFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::CmpLDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::CmpGDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::CmpLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::IfEq { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfNe { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfLt { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfGe { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfGt { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfLe { + a: _, + b: _, + label: _, + } => Ok(self), + Self::IfEqZ { a: _, label: _ } => Ok(self), + Self::IfNeZ { a: _, label: _ } => Ok(self), + Self::IfLtZ { a: _, label: _ } => Ok(self), + Self::IfGeZ { a: _, label: _ } => Ok(self), + Self::IfGtZ { a: _, label: _ } => Ok(self), + Self::IfLeZ { a: _, label: _ } => Ok(self), + Self::AGet { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetWide { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetObject { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetBoolean { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetByte { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetChar { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::AGetShort { + dest: _, + arr: _, + idx: _, + } => Ok(self), + Self::APut { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutWide { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutObject { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutBoolean { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutByte { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutChar { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::APutShort { + from: _, + arr: _, + idx: _, + } => Ok(self), + Self::IGet { to, obj, field } => Ok(Self::IGet { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetWide { to, obj, field } => Ok(Self::IGetWide { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetObject { to, obj, field } => Ok(Self::IGetObject { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetBoolean { to, obj, field } => Ok(Self::IGetBoolean { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetByte { to, obj, field } => Ok(Self::IGetByte { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetChar { to, obj, field } => Ok(Self::IGetChar { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IGetShort { to, obj, field } => Ok(Self::IGetShort { + to, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPut { from, obj, field } => Ok(Self::IPut { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutWide { from, obj, field } => Ok(Self::IPutWide { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutObject { from, obj, field } => Ok(Self::IPutObject { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutBoolean { from, obj, field } => Ok(Self::IPutBoolean { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutByte { from, obj, field } => Ok(Self::IPutByte { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutChar { from, obj, field } => Ok(Self::IPutChar { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::IPutShort { from, obj, field } => Ok(Self::IPutShort { + from, + obj, + field: v.visit_field_id(field)?, + }), + Self::SGet { to, field } => Ok(Self::SGet { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetWide { to, field } => Ok(Self::SGetWide { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetObject { to, field } => Ok(Self::SGetObject { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetBoolean { to, field } => Ok(Self::SGetBoolean { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetByte { to, field } => Ok(Self::SGetByte { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetChar { to, field } => Ok(Self::SGetChar { + to, + field: v.visit_field_id(field)?, + }), + Self::SGetShort { to, field } => Ok(Self::SGetShort { + to, + field: v.visit_field_id(field)?, + }), + Self::SPut { from, field } => Ok(Self::SPut { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutWide { from, field } => Ok(Self::SPutWide { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutObject { from, field } => Ok(Self::SPutObject { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutBoolean { from, field } => Ok(Self::SPutBoolean { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutByte { from, field } => Ok(Self::SPutByte { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutChar { from, field } => Ok(Self::SPutChar { + from, + field: v.visit_field_id(field)?, + }), + Self::SPutShort { from, field } => Ok(Self::SPutShort { + from, + field: v.visit_field_id(field)?, + }), + Self::InvokeVirtual { method, args } => Ok(Self::InvokeVirtual { + method: v.visit_method_id(method)?, + args, + }), + Self::InvokeSuper { method, args } => Ok(Self::InvokeSuper { + method: v.visit_method_id(method)?, + args, + }), + Self::InvokeDirect { method, args } => Ok(Self::InvokeDirect { + method: v.visit_method_id(method)?, + args, + }), + Self::InvokeStatic { method, args } => Ok(Self::InvokeStatic { + method: v.visit_method_id(method)?, + args, + }), + Self::InvokeInterface { method, args } => Ok(Self::InvokeInterface { + method: v.visit_method_id(method)?, + args, + }), + Self::NegInt { dest: _, val: _ } => Ok(self), + Self::NotInt { dest: _, val: _ } => Ok(self), + Self::NegLong { dest: _, val: _ } => Ok(self), + Self::NotLong { dest: _, val: _ } => Ok(self), + Self::NegFloat { dest: _, val: _ } => Ok(self), + Self::NegDouble { dest: _, val: _ } => Ok(self), + Self::IntToLong { dest: _, val: _ } => Ok(self), + Self::IntToFloat { dest: _, val: _ } => Ok(self), + Self::IntToDouble { dest: _, val: _ } => Ok(self), + Self::LongToInt { dest: _, val: _ } => Ok(self), + Self::LongToFloat { dest: _, val: _ } => Ok(self), + Self::LongToDouble { dest: _, val: _ } => Ok(self), + Self::FloatToInt { dest: _, val: _ } => Ok(self), + Self::FloatToLong { dest: _, val: _ } => Ok(self), + Self::FloatToDouble { dest: _, val: _ } => Ok(self), + Self::DoubleToInt { dest: _, val: _ } => Ok(self), + Self::DoubleToLong { dest: _, val: _ } => Ok(self), + Self::DoubleToFloat { dest: _, val: _ } => Ok(self), + Self::IntToByte { dest: _, val: _ } => Ok(self), + Self::IntToChar { dest: _, val: _ } => Ok(self), + Self::IntToShort { dest: _, val: _ } => Ok(self), + Self::AddInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::SubInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::MulInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::DivInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::RemInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AndInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::OrInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::XorInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::ShlInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::ShrInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::UshrInt { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AddLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::SubLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::MulLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::DivLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::RemLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AndLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::OrLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::XorLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::ShlLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::ShrLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::UshrLong { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AddFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::SubFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::MulFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::DivFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::RemFloat { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AddDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::SubDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::MulDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::DivDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::RemDouble { + dest: _, + b: _, + c: _, + } => Ok(self), + Self::AddInt2Addr { dest: _, b: _ } => Ok(self), + Self::SubInt2Addr { dest: _, b: _ } => Ok(self), + Self::MulInt2Addr { dest: _, b: _ } => Ok(self), + Self::DivInt2Addr { dest: _, b: _ } => Ok(self), + Self::RemInt2Addr { dest: _, b: _ } => Ok(self), + Self::AndInt2Addr { dest: _, b: _ } => Ok(self), + Self::OrInt2Addr { dest: _, b: _ } => Ok(self), + Self::XorInt2Addr { dest: _, b: _ } => Ok(self), + Self::ShlInt2Addr { dest: _, b: _ } => Ok(self), + Self::ShrInt2Addr { dest: _, b: _ } => Ok(self), + Self::UshrInt2Addr { dest: _, b: _ } => Ok(self), + Self::AddLong2Addr { dest: _, b: _ } => Ok(self), + Self::SubLong2Addr { dest: _, b: _ } => Ok(self), + Self::MulLong2Addr { dest: _, b: _ } => Ok(self), + Self::DivLong2Addr { dest: _, b: _ } => Ok(self), + Self::RemLong2Addr { dest: _, b: _ } => Ok(self), + Self::AndLong2Addr { dest: _, b: _ } => Ok(self), + Self::OrLong2Addr { dest: _, b: _ } => Ok(self), + Self::XorLong2Addr { dest: _, b: _ } => Ok(self), + Self::ShlLong2Addr { dest: _, b: _ } => Ok(self), + Self::ShrLong2Addr { dest: _, b: _ } => Ok(self), + Self::UshrLong2Addr { dest: _, b: _ } => Ok(self), + Self::AddFloat2Addr { dest: _, b: _ } => Ok(self), + Self::SubFloat2Addr { dest: _, b: _ } => Ok(self), + Self::MulFloat2Addr { dest: _, b: _ } => Ok(self), + Self::DivFloat2Addr { dest: _, b: _ } => Ok(self), + Self::RemFloat2Addr { dest: _, b: _ } => Ok(self), + Self::AddDouble2Addr { dest: _, b: _ } => Ok(self), + Self::SubDouble2Addr { dest: _, b: _ } => Ok(self), + Self::MulDouble2Addr { dest: _, b: _ } => Ok(self), + Self::DivDouble2Addr { dest: _, b: _ } => Ok(self), + Self::RemDouble2Addr { dest: _, b: _ } => Ok(self), + Self::AddIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::RsubIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::MulIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::DivIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::RemIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::AndIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::OrIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::XorIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::ShlIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::ShrIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::UshrIntLit { + dest: _, + b: _, + lit: _, + } => Ok(self), + Self::InvokePolymorphic { + method, + proto, + args, + } => Ok(Self::InvokePolymorphic { + method: v.visit_method_id(method)?, + proto: v.visit_method_type(proto)?, + args, + }), + Self::InvokeCustom { call_site, args } => Ok(Self::InvokeCustom { + call_site: v.visit_call_site(call_site)?, + args, + }), + Self::ConstMethodHandle { handle, to } => Ok(Self::ConstMethodHandle { + handle: v.visit_method_handle(handle)?, + to, + }), + Self::ConstMethodType { proto, to } => Ok(Self::ConstMethodType { + proto: v.visit_method_type(proto)?, + to, + }), + Self::Try { + end_label, + handlers, + default_handler, + } => Ok(Self::Try { + end_label, + handlers: handlers + .into_iter() + .map(|(ty, lab)| v.visit_type(ty).map(|ty| (ty, lab))) + .collect::>()?, + default_handler, + }), + Self::Label { name: _ } => Ok(self), } } } +macro_rules! sanity_check_4_bit_reg { + ($ins_name:tt, $r1:ident, $r2:ident) => {{ + if $r1 & 0b1111_0000 != 0 { + Err(anyhow!( + "{} uses registers indexed on 4 bits, found {}", + $ins_name, + $r1 + )) + } else if $r2 & &0b1111_0000 != 0 { + Err(anyhow!( + "{} uses registers indexed on 4 bits, found {}", + $ins_name, + $r1 + )) + } else { + Ok(()) + } + }}; +} + +macro_rules! sanity_check_22b_or_22s { + ($ins_name:tt, $r1:ident, $r2:ident, $lit:ident) => {{ + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if $r1 & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if $r2 & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *$lit < I8_MIN_AS_I16 || *$lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + Err(anyhow!( + "{}/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits ({}/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits ({}/lit8). Found reg {} and {}, and lit \ + {}", + $ins_name, + $ins_name, + $ins_name, + $r1, + $r2, + $lit, + )) + } else { + Ok(()) + } + }}; +} + +#[pymethods] impl Instruction { + pub fn __eq__(&self, other: &Self) -> bool { + self == other + } + + pub fn to_json(&self) -> Result { + Ok(serde_json::to_string(self)?) + } + + #[staticmethod] + pub fn from_json(json: &str) -> Result { + Ok(serde_json::from_str(json)?) + } + pub fn __str__(&self) -> String { match self { Self::Nop {} => "nop".into(), - Self::Move(ins) => ins.__str__(), - Self::MoveWide(ins) => ins.__str__(), - Self::MoveObject(ins) => ins.__str__(), - Self::MoveResult(ins) => ins.__str__(), - Self::MoveResultWide(ins) => ins.__str__(), - Self::MoveException(ins) => ins.__str__(), - Self::MoveResultObject(ins) => ins.__str__(), - Self::ReturnVoid(ins) => ins.__str__(), - Self::Return(ins) => ins.__str__(), - Self::ReturnWide(ins) => ins.__str__(), - Self::ReturnObject(ins) => ins.__str__(), - Self::Const(ins) => ins.__str__(), - Self::ConstWide(ins) => ins.__str__(), - Self::ConstString(ins) => ins.__str__(), - Self::ConstClass(ins) => ins.__str__(), - Self::MonitorEnter(ins) => ins.__str__(), - Self::MonitorExit(ins) => ins.__str__(), - Self::CheckCast(ins) => ins.__str__(), - Self::InstanceOf(ins) => ins.__str__(), - Self::ArrayLength(ins) => ins.__str__(), - Self::NewInstance(ins) => ins.__str__(), - Self::NewArray(ins) => ins.__str__(), - Self::FilledNewArray(ins) => ins.__str__(), - Self::FillArrayData(ins) => ins.__str__(), - Self::Throw(ins) => ins.__str__(), - Self::Goto(ins) => ins.__str__(), - Self::Switch(ins) => ins.__str__(), - Self::CmpLFloat(ins) => ins.__str__(), - Self::CmpGFloat(ins) => ins.__str__(), - Self::CmpLDouble(ins) => ins.__str__(), - Self::CmpGDouble(ins) => ins.__str__(), - Self::CmpLong(ins) => ins.__str__(), - Self::IfEq(ins) => ins.__str__(), - Self::IfNe(ins) => ins.__str__(), - Self::IfLt(ins) => ins.__str__(), - Self::IfGe(ins) => ins.__str__(), - Self::IfGt(ins) => ins.__str__(), - Self::IfLe(ins) => ins.__str__(), - Self::IfEqZ(ins) => ins.__str__(), - Self::IfNeZ(ins) => ins.__str__(), - Self::IfLtZ(ins) => ins.__str__(), - Self::IfGeZ(ins) => ins.__str__(), - Self::IfGtZ(ins) => ins.__str__(), - Self::IfLeZ(ins) => ins.__str__(), - Self::AGet(ins) => ins.__str__(), - Self::AGetWide(ins) => ins.__str__(), - Self::AGetObject(ins) => ins.__str__(), - Self::AGetBoolean(ins) => ins.__str__(), - Self::AGetByte(ins) => ins.__str__(), - Self::AGetChar(ins) => ins.__str__(), - Self::AGetShort(ins) => ins.__str__(), - Self::APut(ins) => ins.__str__(), - Self::APutWide(ins) => ins.__str__(), - Self::APutObject(ins) => ins.__str__(), - Self::APutBoolean(ins) => ins.__str__(), - Self::APutByte(ins) => ins.__str__(), - Self::APutChar(ins) => ins.__str__(), - Self::APutShort(ins) => ins.__str__(), - Self::IGet(ins) => ins.__str__(), - Self::IGetWide(ins) => ins.__str__(), - Self::IGetObject(ins) => ins.__str__(), - Self::IGetBoolean(ins) => ins.__str__(), - Self::IGetByte(ins) => ins.__str__(), - Self::IGetChar(ins) => ins.__str__(), - Self::IGetShort(ins) => ins.__str__(), - Self::IPut(ins) => ins.__str__(), - Self::IPutWide(ins) => ins.__str__(), - Self::IPutObject(ins) => ins.__str__(), - Self::IPutBoolean(ins) => ins.__str__(), - Self::IPutByte(ins) => ins.__str__(), - Self::IPutChar(ins) => ins.__str__(), - Self::IPutShort(ins) => ins.__str__(), - Self::SGet(ins) => ins.__str__(), - Self::SGetWide(ins) => ins.__str__(), - Self::SGetObject(ins) => ins.__str__(), - Self::SGetBoolean(ins) => ins.__str__(), - Self::SGetByte(ins) => ins.__str__(), - Self::SGetChar(ins) => ins.__str__(), - Self::SGetShort(ins) => ins.__str__(), - Self::SPut(ins) => ins.__str__(), - Self::SPutWide(ins) => ins.__str__(), - Self::SPutObject(ins) => ins.__str__(), - Self::SPutBoolean(ins) => ins.__str__(), - Self::SPutByte(ins) => ins.__str__(), - Self::SPutChar(ins) => ins.__str__(), - Self::SPutShort(ins) => ins.__str__(), - Self::InvokeVirtual(ins) => ins.__str__(), - Self::InvokeSuper(ins) => ins.__str__(), - Self::InvokeDirect(ins) => ins.__str__(), - Self::InvokeStatic(ins) => ins.__str__(), - Self::InvokeInterface(ins) => ins.__str__(), - Self::NegInt(ins) => ins.__str__(), - Self::NotInt(ins) => ins.__str__(), - Self::NegLong(ins) => ins.__str__(), - Self::NotLong(ins) => ins.__str__(), - Self::NegFloat(ins) => ins.__str__(), - Self::NegDouble(ins) => ins.__str__(), - Self::IntToLong(ins) => ins.__str__(), - Self::IntToFloat(ins) => ins.__str__(), - Self::IntToDouble(ins) => ins.__str__(), - Self::LongToInt(ins) => ins.__str__(), - Self::LongToFloat(ins) => ins.__str__(), - Self::LongToDouble(ins) => ins.__str__(), - Self::FloatToInt(ins) => ins.__str__(), - Self::FloatToLong(ins) => ins.__str__(), - Self::FloatToDouble(ins) => ins.__str__(), - Self::DoubleToInt(ins) => ins.__str__(), - Self::DoubleToLong(ins) => ins.__str__(), - Self::DoubleToFloat(ins) => ins.__str__(), - Self::IntToByte(ins) => ins.__str__(), - Self::IntToChar(ins) => ins.__str__(), - Self::IntToShort(ins) => ins.__str__(), - Self::AddInt(ins) => ins.__str__(), - Self::SubInt(ins) => ins.__str__(), - Self::MulInt(ins) => ins.__str__(), - Self::DivInt(ins) => ins.__str__(), - Self::RemInt(ins) => ins.__str__(), - Self::AndInt(ins) => ins.__str__(), - Self::OrInt(ins) => ins.__str__(), - Self::XorInt(ins) => ins.__str__(), - Self::ShlInt(ins) => ins.__str__(), - Self::ShrInt(ins) => ins.__str__(), - Self::UshrInt(ins) => ins.__str__(), - Self::AddLong(ins) => ins.__str__(), - Self::SubLong(ins) => ins.__str__(), - Self::MulLong(ins) => ins.__str__(), - Self::DivLong(ins) => ins.__str__(), - Self::RemLong(ins) => ins.__str__(), - Self::AndLong(ins) => ins.__str__(), - Self::OrLong(ins) => ins.__str__(), - Self::XorLong(ins) => ins.__str__(), - Self::ShlLong(ins) => ins.__str__(), - Self::ShrLong(ins) => ins.__str__(), - Self::UshrLong(ins) => ins.__str__(), - Self::AddFloat(ins) => ins.__str__(), - Self::SubFloat(ins) => ins.__str__(), - Self::MulFloat(ins) => ins.__str__(), - Self::DivFloat(ins) => ins.__str__(), - Self::RemFloat(ins) => ins.__str__(), - Self::AddDouble(ins) => ins.__str__(), - Self::SubDouble(ins) => ins.__str__(), - Self::MulDouble(ins) => ins.__str__(), - Self::DivDouble(ins) => ins.__str__(), - Self::RemDouble(ins) => ins.__str__(), - Self::AddInt2Addr(ins) => ins.__str__(), - Self::SubInt2Addr(ins) => ins.__str__(), - Self::MulInt2Addr(ins) => ins.__str__(), - Self::DivInt2Addr(ins) => ins.__str__(), - Self::RemInt2Addr(ins) => ins.__str__(), - Self::AndInt2Addr(ins) => ins.__str__(), - Self::OrInt2Addr(ins) => ins.__str__(), - Self::XorInt2Addr(ins) => ins.__str__(), - Self::ShlInt2Addr(ins) => ins.__str__(), - Self::ShrInt2Addr(ins) => ins.__str__(), - Self::UshrInt2Addr(ins) => ins.__str__(), - Self::AddLong2Addr(ins) => ins.__str__(), - Self::SubLong2Addr(ins) => ins.__str__(), - Self::MulLong2Addr(ins) => ins.__str__(), - Self::DivLong2Addr(ins) => ins.__str__(), - Self::RemLong2Addr(ins) => ins.__str__(), - Self::AndLong2Addr(ins) => ins.__str__(), - Self::OrLong2Addr(ins) => ins.__str__(), - Self::XorLong2Addr(ins) => ins.__str__(), - Self::ShlLong2Addr(ins) => ins.__str__(), - Self::ShrLong2Addr(ins) => ins.__str__(), - Self::UshrLong2Addr(ins) => ins.__str__(), - Self::AddFloat2Addr(ins) => ins.__str__(), - Self::SubFloat2Addr(ins) => ins.__str__(), - Self::MulFloat2Addr(ins) => ins.__str__(), - Self::DivFloat2Addr(ins) => ins.__str__(), - Self::RemFloat2Addr(ins) => ins.__str__(), - Self::AddDouble2Addr(ins) => ins.__str__(), - Self::SubDouble2Addr(ins) => ins.__str__(), - Self::MulDouble2Addr(ins) => ins.__str__(), - Self::DivDouble2Addr(ins) => ins.__str__(), - Self::RemDouble2Addr(ins) => ins.__str__(), - Self::AddIntLit(ins) => ins.__str__(), - Self::RsubIntLit(ins) => ins.__str__(), - Self::MulIntLit(ins) => ins.__str__(), - Self::DivIntLit(ins) => ins.__str__(), - Self::RemIntLit(ins) => ins.__str__(), - Self::AndIntLit(ins) => ins.__str__(), - Self::OrIntLit(ins) => ins.__str__(), - Self::XorIntLit(ins) => ins.__str__(), - Self::ShlIntLit(ins) => ins.__str__(), - Self::ShrIntLit(ins) => ins.__str__(), - Self::UshrIntLit(ins) => ins.__str__(), - Self::InvokePolymorphic(ins) => ins.__str__(), - Self::InvokeCustom(ins) => ins.__str__(), - Self::ConstMethodHandle(ins) => ins.__str__(), - Self::ConstMethodType(ins) => ins.__str__(), - Self::Try(ins) => ins.__str__(), - Self::Label(ins) => ins.__str__(), + Self::Move { from, to } => { + format!("move {} {}", to, from) + } + Self::MoveWide { from, to } => { + format!("move-wide {} {}", to, from) + } + Self::MoveObject { from, to } => { + format!("move-object {} {}", to, from) + } + Self::MoveResult { to } => { + format!("move-result {}", to) + } + Self::MoveResultWide { to } => { + format!("move-result-wide {}", to) + } + Self::MoveResultObject { to } => { + format!("move-result-object {}", to) + } + Self::MoveException { to } => { + format!("move-exception {}", to) + } + Self::ReturnVoid {} => "return-void".into(), + Self::Return { reg } => { + format!("return {}", reg) + } + Self::ReturnWide { reg } => { + format!("return-wide {}", reg) + } + Self::ReturnObject { reg } => { + format!("return-object {}", reg) + } + Self::Const { lit, reg } => { + format!("const {} {}", reg, lit) + } + Self::ConstWide { lit, reg } => { + format!("const-wide {} {}", reg, lit) + } + Self::ConstString { lit, reg } => { + format!("const-string {} \"{}\"", reg, lit.__str__()) + } + Self::ConstClass { lit, reg } => { + format!("const-class {} \"{}\"", reg, lit.__str__()) + } + Self::MonitorEnter { reg } => { + format!("monitor-enter {}", reg) + } + Self::MonitorExit { reg } => { + format!("monitor-exit {}", reg) + } + Self::CheckCast { lit, reg } => { + format!("check-cast {} {}", reg, lit.__str__()) + } + Self::InstanceOf { lit, dest, obj } => { + format!("instance-of {} {} {}", dest, obj, lit.__str__()) + } + Self::ArrayLength { arr, dest } => { + format!("array-length{} {}", dest, arr,) + } + Self::NewInstance { lit, reg } => { + format!("new-instance {} {}", reg, lit.__str__()) + } + Self::NewArray { lit, size_reg, reg } => { + format!("new-array {} {} {}", reg, size_reg, lit.__str__()) + } + Self::FilledNewArray { reg_values, type_ } => { + let args = if reg_values.len() >= 5 { + format!("{} .. {}", reg_values[0], reg_values[reg_values.len() - 1]) + } else { + reg_values + .iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("filled-new-array {{{}}} {}", args, type_.__str__()) + } + Self::FillArrayData { + arr, + data, + elt_width, + } => { + let data: String = if data.len() / *elt_width as usize == 0 { + "".into() + } else if data.len() / *elt_width as usize <= 2 { + let mut arr = "".into(); + for (i, v) in data.iter().enumerate() { + if i == 0 { + arr += "0x" + } else if i % *elt_width as usize == 0 { + arr += " 0x" + } + arr += format!("{v:02x}").as_str(); + } + arr + } else { + let mut arr = "0x".into(); + for v in &data[..*elt_width as usize] { + arr += format!("{v:02x}").as_str(); + } + arr += " ... 0x"; + for v in &data[data.len() - *elt_width as usize..] { + arr += format!("{v:02x}").as_str(); + } + + arr + }; + format!("fill-array-data {} {}", arr, data) + } + Self::Throw { reg } => { + format!("throw {}", reg) + } + Self::Goto { label } => { + format!("goto {}", label) + } + Self::Switch { branches, reg } => { + let mut branches_str: String = "".into(); + let mut branches: Vec<_> = branches.iter().collect(); + branches.sort_by_key(|(key, _)| **key); + for (key, label) in branches { + branches_str += &format!("\n {key}: goto {label}"); + } + format!("switch {} {}", reg, branches_str) + } + Self::CmpLFloat { b, dest, c } => { + format!("cmpl-float {} {} {}", dest, b, c) + } + Self::CmpGFloat { b, dest, c } => { + format!("cmpg-float {} {} {}", dest, b, c) + } + Self::CmpLDouble { b, dest, c } => { + format!("cmpl-double {} {} {}", dest, b, c) + } + Self::CmpGDouble { b, dest, c } => { + format!("cmpg-double {} {} {}", dest, b, c) + } + Self::CmpLong { b, dest, c } => { + format!("cmp-long {} {} {}", dest, b, c) + } + Self::IfEq { label, a, b } => { + format!("if-eq {} {} {}", a, b, label) + } + Self::IfNe { label, a, b } => { + format!("if-neq {} {} {}", a, b, label) + } + Self::IfLt { label, a, b } => { + format!("if-lt {} {} {}", a, b, label) + } + Self::IfGe { label, a, b } => { + format!("if-ge {} {} {}", a, b, label) + } + Self::IfGt { label, a, b } => { + format!("if-gt {} {} {}", a, b, label) + } + Self::IfLe { label, a, b } => { + format!("if-le {} {} {}", a, b, label) + } + Self::IfEqZ { label, a } => { + format!("if-eqz {} {}", a, label) + } + Self::IfNeZ { label, a } => { + format!("if-neq {} {}", a, label) + } + Self::IfLtZ { label, a } => { + format!("if-lt {} {}", a, label) + } + Self::IfGeZ { label, a } => { + format!("if-ge {} {}", a, label) + } + Self::IfGtZ { label, a } => { + format!("if-gt {} {}", a, label) + } + Self::IfLeZ { label, a } => { + format!("if-le {} {}", a, label) + } + Self::AGet { arr, idx, dest } => { + format!("aget {} {} {}", dest, arr, idx) + } + Self::AGetWide { arr, idx, dest } => { + format!("aget-wide {} {} {}", dest, arr, idx) + } + Self::AGetObject { arr, idx, dest } => { + format!("aget-object {} {} {}", dest, arr, idx) + } + Self::AGetBoolean { arr, idx, dest } => { + format!("aget-boolean {} {} {}", dest, arr, idx) + } + Self::AGetByte { arr, idx, dest } => { + format!("aget-byte {} {} {}", dest, arr, idx) + } + Self::AGetChar { arr, idx, dest } => { + format!("aget-char {} {} {}", dest, arr, idx) + } + Self::AGetShort { arr, idx, dest } => { + format!("aget-short {} {} {}", dest, arr, idx) + } + Self::APut { arr, from, idx } => { + format!("aput {} {} {}", from, arr, idx) + } + Self::APutWide { arr, from, idx } => { + format!("aput-wide {} {} {}", from, arr, idx) + } + Self::APutObject { arr, from, idx } => { + format!("aput-object {} {} {}", from, arr, idx) + } + Self::APutBoolean { arr, from, idx } => { + format!("aput-boolean {} {} {}", from, arr, idx) + } + Self::APutByte { arr, from, idx } => { + format!("aput-byte {} {} {}", from, arr, idx) + } + Self::APutChar { arr, from, idx } => { + format!("aput-char {} {} {}", from, arr, idx) + } + Self::APutShort { arr, from, idx } => { + format!("aput-short {} {} {}", from, arr, idx) + } + Self::IGet { field, to, obj } => { + format!("iget {} {} {}", to, obj, field.__str__()) + } + Self::IGetWide { field, to, obj } => { + format!("iget-wide {} {} {}", to, obj, field.__str__()) + } + Self::IGetObject { field, to, obj } => { + format!("iget-object {} {} {}", to, obj, field.__str__()) + } + Self::IGetBoolean { field, to, obj } => { + format!("iget-boolean {} {} {}", to, obj, field.__str__()) + } + Self::IGetByte { field, to, obj } => { + format!("iget-byte {} {} {}", to, obj, field.__str__()) + } + Self::IGetChar { field, to, obj } => { + format!("iget-char {} {} {}", to, obj, field.__str__()) + } + Self::IGetShort { field, to, obj } => { + format!("iget-short {} {} {}", to, obj, field.__str__()) + } + Self::IPut { field, from, obj } => { + format!("iput {} {} {}", from, obj, field.__str__()) + } + Self::IPutWide { field, from, obj } => { + format!("iput-wide {} {} {}", from, obj, field.__str__()) + } + Self::IPutObject { field, from, obj } => { + format!("iput-object {} {} {}", from, obj, field.__str__()) + } + Self::IPutBoolean { field, from, obj } => { + format!("iput-boolean {} {} {}", from, obj, field.__str__()) + } + Self::IPutByte { field, from, obj } => { + format!("iput-byte {} {} {}", from, obj, field.__str__()) + } + Self::IPutChar { field, from, obj } => { + format!("iput-char {} {} {}", from, obj, field.__str__()) + } + Self::IPutShort { field, from, obj } => { + format!("iput-short {} {} {}", from, obj, field.__str__()) + } + Self::SGet { field, to } => { + format!("sget {} {}", to, field.__str__()) + } + Self::SGetWide { field, to } => { + format!("sget-wide {} {}", to, field.__str__()) + } + Self::SGetObject { field, to } => { + format!("sget-object {} {}", to, field.__str__()) + } + Self::SGetBoolean { field, to } => { + format!("sget-boolean {} {}", to, field.__str__()) + } + Self::SGetByte { field, to } => { + format!("sget-byte {} {}", to, field.__str__()) + } + Self::SGetChar { field, to } => { + format!("sget-char {} {}", to, field.__str__()) + } + Self::SGetShort { field, to } => { + format!("sget-short {} {}", to, field.__str__()) + } + Self::SPut { field, from } => { + format!("sput {} {}", from, field.__str__()) + } + Self::SPutWide { field, from } => { + format!("sput-wide {} {}", from, field.__str__()) + } + Self::SPutObject { field, from } => { + format!("sput-object {} {}", from, field.__str__()) + } + Self::SPutBoolean { field, from } => { + format!("sput-boolean {} {}", from, field.__str__()) + } + Self::SPutByte { field, from } => { + format!("sput-byte {} {}", from, field.__str__()) + } + Self::SPutChar { field, from } => { + format!("sput-char {} {}", from, field.__str__()) + } + Self::SPutShort { field, from } => { + format!("sput-short {} {}", from, field.__str__()) + } + Self::InvokeVirtual { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-virtual {{{}}} {}", args, method.__str__()) + } + Self::InvokeSuper { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-super {{{}}} {}", args, method.__str__()) + } + Self::InvokeDirect { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-direct {{{}}} {}", args, method.__str__()) + } + Self::InvokeStatic { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-static {{{}}} {}", args, method.__str__()) + } + Self::InvokeInterface { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-interface {{{}}} {}", args, method.__str__()) + } + Self::NegInt { val, dest } => { + format!("neg-int {} {}", dest, val) + } + Self::NotInt { val, dest } => { + format!("not-int {} {}", dest, val) + } + Self::NegLong { val, dest } => { + format!("neg-long {} {}", dest, val) + } + Self::NotLong { val, dest } => { + format!("not-long {} {}", dest, val) + } + Self::NegFloat { val, dest } => { + format!("neg-float {} {}", dest, val) + } + Self::NegDouble { val, dest } => { + format!("neg-double {} {}", dest, val) + } + Self::IntToLong { val, dest } => { + format!("int-to-long {} {}", dest, val) + } + Self::IntToFloat { val, dest } => { + format!("int-to-float {} {}", dest, val) + } + Self::IntToDouble { val, dest } => { + format!("int-to-double {} {}", dest, val) + } + Self::LongToInt { val, dest } => { + format!("long-to-int {} {}", dest, val) + } + Self::LongToFloat { val, dest } => { + format!("long-to-float {} {}", dest, val) + } + Self::LongToDouble { val, dest } => { + format!("long-to-double {} {}", dest, val) + } + Self::FloatToInt { val, dest } => { + format!("float-to-int {} {}", dest, val) + } + Self::FloatToLong { val, dest } => { + format!("float-to-long {} {}", dest, val) + } + Self::FloatToDouble { val, dest } => { + format!("float-to-double {} {}", dest, val) + } + Self::DoubleToInt { val, dest } => { + format!("double-to-int {} {}", dest, val) + } + Self::DoubleToLong { val, dest } => { + format!("double-to-long {} {}", dest, val) + } + Self::DoubleToFloat { val, dest } => { + format!("double-to-float {} {}", dest, val) + } + Self::IntToByte { val, dest } => { + format!("int-to-byte {} {}", dest, val) + } + Self::IntToChar { val, dest } => { + format!("int-to-char {} {}", dest, val) + } + Self::IntToShort { val, dest } => { + format!("int-to-short {} {}", dest, val) + } + Self::AddInt { b, dest, c } => { + format!("add-int {} {} {}", dest, b, c) + } + Self::SubInt { b, dest, c } => { + format!("sub-int {} {} {}", dest, b, c) + } + Self::MulInt { b, dest, c } => { + format!("mul-int {} {} {}", dest, b, c) + } + Self::DivInt { b, dest, c } => { + format!("div-int {} {} {}", dest, b, c) + } + Self::RemInt { b, dest, c } => { + format!("rem-int {} {} {}", dest, b, c) + } + Self::AndInt { b, dest, c } => { + format!("and-int {} {} {}", dest, b, c) + } + Self::OrInt { b, dest, c } => { + format!("or-int {} {} {}", dest, b, c) + } + Self::XorInt { b, dest, c } => { + format!("xor-int {} {} {}", dest, b, c) + } + Self::ShlInt { b, dest, c } => { + format!("shl-int {} {} {}", dest, b, c) + } + Self::ShrInt { b, dest, c } => { + format!("shr-int {} {} {}", dest, b, c) + } + Self::UshrInt { b, dest, c } => { + format!("ushr-int {} {} {}", dest, b, c) + } + Self::AddLong { b, dest, c } => { + format!("add-long {} {} {}", dest, b, c) + } + Self::SubLong { b, dest, c } => { + format!("sub-long {} {} {}", dest, b, c) + } + Self::MulLong { b, dest, c } => { + format!("mul-long {} {} {}", dest, b, c) + } + Self::DivLong { b, dest, c } => { + format!("div-long {} {} {}", dest, b, c) + } + Self::RemLong { b, dest, c } => { + format!("rem-long {} {} {}", dest, b, c) + } + Self::AndLong { b, dest, c } => { + format!("and-long {} {} {}", dest, b, c) + } + Self::OrLong { b, dest, c } => { + format!("or-long {} {} {}", dest, b, c) + } + Self::XorLong { b, dest, c } => { + format!("xor-long {} {} {}", dest, b, c) + } + Self::ShlLong { b, dest, c } => { + format!("shl-long {} {} {}", dest, b, c) + } + Self::ShrLong { b, dest, c } => { + format!("shr-long {} {} {}", dest, b, c) + } + Self::UshrLong { b, dest, c } => { + format!("ushr-long {} {} {}", dest, b, c) + } + Self::AddFloat { b, dest, c } => { + format!("add-float {} {} {}", dest, b, c) + } + Self::SubFloat { b, dest, c } => { + format!("sub-float {} {} {}", dest, b, c) + } + Self::MulFloat { b, dest, c } => { + format!("mul-float {} {} {}", dest, b, c) + } + Self::DivFloat { b, dest, c } => { + format!("div-float {} {} {}", dest, b, c) + } + Self::RemFloat { b, dest, c } => { + format!("rem-float {} {} {}", dest, b, c) + } + Self::AddDouble { b, dest, c } => { + format!("add-double {} {} {}", dest, b, c) + } + Self::SubDouble { b, dest, c } => { + format!("sub-double {} {} {}", dest, b, c) + } + Self::MulDouble { b, dest, c } => { + format!("mul-double {} {} {}", dest, b, c) + } + Self::DivDouble { b, dest, c } => { + format!("div-double {} {} {}", dest, b, c) + } + Self::RemDouble { b, dest, c } => { + format!("rem-double {} {} {}", dest, b, c) + } + Self::AddInt2Addr { b, dest } => { + format!("add-int/2addr {} {}", dest, b) + } + Self::SubInt2Addr { b, dest } => { + format!("sub-int/2addr {} {}", dest, b) + } + Self::MulInt2Addr { b, dest } => { + format!("mul-int/2addr {} {}", dest, b) + } + Self::DivInt2Addr { b, dest } => { + format!("div-int/2addr {} {}", dest, b) + } + Self::RemInt2Addr { b, dest } => { + format!("rem-int/2addr {} {}", dest, b) + } + Self::AndInt2Addr { b, dest } => { + format!("and-int/2addr {} {}", dest, b) + } + Self::OrInt2Addr { b, dest } => { + format!("or-int/2addr {} {}", dest, b) + } + Self::XorInt2Addr { b, dest } => { + format!("xor-int/2addr {} {}", dest, b) + } + Self::ShlInt2Addr { b, dest } => { + format!("shl-int/2addr {} {}", dest, b) + } + Self::ShrInt2Addr { b, dest } => { + format!("shr-int/2addr {} {}", dest, b) + } + Self::UshrInt2Addr { b, dest } => { + format!("ushr-int/2addr {} {}", dest, b) + } + Self::AddLong2Addr { b, dest } => { + format!("add-long/2addr {} {}", dest, b) + } + Self::SubLong2Addr { b, dest } => { + format!("sub-long/2addr {} {}", dest, b) + } + Self::MulLong2Addr { b, dest } => { + format!("mul-long/2addr {} {}", dest, b) + } + Self::DivLong2Addr { b, dest } => { + format!("div-long/2addr {} {}", dest, b) + } + Self::RemLong2Addr { b, dest } => { + format!("rem-long/2addr {} {}", dest, b) + } + Self::AndLong2Addr { b, dest } => { + format!("and-long/2addr {} {}", dest, b) + } + Self::OrLong2Addr { b, dest } => { + format!("or-long/2addr {} {}", dest, b) + } + Self::XorLong2Addr { b, dest } => { + format!("xor-long/2addr {} {}", dest, b) + } + Self::ShlLong2Addr { b, dest } => { + format!("shl-long/2addr {} {}", dest, b) + } + Self::ShrLong2Addr { b, dest } => { + format!("shr-long/2addr {} {}", dest, b) + } + Self::UshrLong2Addr { b, dest } => { + format!("ushr-long/2addr {} {}", dest, b) + } + Self::AddFloat2Addr { b, dest } => { + format!("add-float/2addr {} {}", dest, b) + } + Self::SubFloat2Addr { b, dest } => { + format!("sub-float/2addr {} {}", dest, b) + } + Self::MulFloat2Addr { b, dest } => { + format!("mul-float/2addr {} {}", dest, b) + } + Self::DivFloat2Addr { b, dest } => { + format!("div-float/2addr {} {}", dest, b) + } + Self::RemFloat2Addr { b, dest } => { + format!("rem-float/2addr {} {}", dest, b) + } + Self::AddDouble2Addr { b, dest } => { + format!("add-double/2addr {} {}", dest, b) + } + Self::SubDouble2Addr { b, dest } => { + format!("sub-double/2addr {} {}", dest, b) + } + Self::MulDouble2Addr { b, dest } => { + format!("mul-double/2addr {} {}", dest, b) + } + Self::DivDouble2Addr { b, dest } => { + format!("div-double/2addr {} {}", dest, b) + } + Self::RemDouble2Addr { b, dest } => { + format!("rem-double/2addr {} {}", dest, b) + } + Self::AddIntLit { lit, b, dest } => { + format!("add-int/lit {} {} {}", dest, b, lit) + } + Self::RsubIntLit { lit, b, dest } => { + format!("rsub-int/lit {} {} {}", dest, b, lit) + } + Self::MulIntLit { lit, b, dest } => { + format!("mul-int/lit {} {} {}", dest, b, lit) + } + Self::DivIntLit { lit, b, dest } => { + format!("div-int/lit {} {} {}", dest, b, lit) + } + Self::RemIntLit { lit, b, dest } => { + format!("rem-int/lit {} {} {}", dest, b, lit) + } + Self::AndIntLit { lit, b, dest } => { + format!("and-int/lit {} {} {}", dest, b, lit) + } + Self::OrIntLit { lit, b, dest } => { + format!("or-int/lit {} {} {}", dest, b, lit) + } + Self::XorIntLit { lit, b, dest } => { + format!("xor-int/lit {} {} {}", dest, b, lit) + } + Self::ShlIntLit { lit, b, dest } => { + format!("shl-int/lit {} {} {}", dest, b, lit) + } + Self::ShrIntLit { lit, b, dest } => { + format!("shr-int/lit {} {} {}", dest, b, lit) + } + Self::UshrIntLit { lit, b, dest } => { + format!("ushr-int/lit {} {} {}", dest, b, lit) + } + Self::InvokePolymorphic { + args, + method, + proto, + } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!( + "invoke-polymorphic {{{}}} {} {}", + args, + method.__str__(), + proto.__str__() + ) + } + Self::InvokeCustom { args, call_site } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("invoke-custom {{{}}} {}", args, call_site.__str__(),) + } + Self::ConstMethodHandle { to, handle } => { + format!("const-method-handle {} {}", to, handle.__str__()) + } + Self::ConstMethodType { to, proto } => { + format!("const-method-type {} {}", to, proto.__str__()) + } + Self::Try { + handlers, + end_label, + default_handler, + } => { + let handlers = handlers + .iter() + .map(|(ty, label)| format!(" {}: {label}", ty.__str__())) + .collect::>() + .join("\n "); + let default_handler = if let Some(label) = default_handler { + format!(" default: {label}") + } else { + "".into() + }; + + format!("try until {}{}{}", end_label, handlers, default_handler) + } + Self::Label { name } => { + format!("{}:", name) + } } } pub fn __repr__(&self) -> String { match self { Self::Nop {} => "Instruction(Nop)".into(), - Self::Move(ins) => ins.__repr__(), - Self::MoveWide(ins) => ins.__repr__(), - Self::MoveObject(ins) => ins.__repr__(), - Self::MoveResult(ins) => ins.__repr__(), - Self::MoveResultWide(ins) => ins.__repr__(), - Self::MoveException(ins) => ins.__repr__(), - Self::MoveResultObject(ins) => ins.__repr__(), - Self::ReturnVoid(ins) => ins.__repr__(), - Self::Return(ins) => ins.__repr__(), - Self::ReturnWide(ins) => ins.__repr__(), - Self::ReturnObject(ins) => ins.__repr__(), - Self::Const(ins) => ins.__repr__(), - Self::ConstWide(ins) => ins.__repr__(), - Self::ConstString(ins) => ins.__repr__(), - Self::ConstClass(ins) => ins.__repr__(), - Self::MonitorEnter(ins) => ins.__repr__(), - Self::MonitorExit(ins) => ins.__repr__(), - Self::CheckCast(ins) => ins.__repr__(), - Self::InstanceOf(ins) => ins.__repr__(), - Self::ArrayLength(ins) => ins.__repr__(), - Self::NewInstance(ins) => ins.__repr__(), - Self::NewArray(ins) => ins.__repr__(), - Self::FilledNewArray(ins) => ins.__repr__(), - Self::FillArrayData(ins) => ins.__repr__(), - Self::Throw(ins) => ins.__repr__(), - Self::Goto(ins) => ins.__repr__(), - Self::Switch(ins) => ins.__repr__(), - Self::CmpLFloat(ins) => ins.__repr__(), - Self::CmpGFloat(ins) => ins.__repr__(), - Self::CmpLDouble(ins) => ins.__repr__(), - Self::CmpGDouble(ins) => ins.__repr__(), - Self::CmpLong(ins) => ins.__repr__(), - Self::IfEq(ins) => ins.__repr__(), - Self::IfNe(ins) => ins.__repr__(), - Self::IfLt(ins) => ins.__repr__(), - Self::IfGe(ins) => ins.__repr__(), - Self::IfGt(ins) => ins.__repr__(), - Self::IfLe(ins) => ins.__repr__(), - Self::IfEqZ(ins) => ins.__repr__(), - Self::IfNeZ(ins) => ins.__repr__(), - Self::IfLtZ(ins) => ins.__repr__(), - Self::IfGeZ(ins) => ins.__repr__(), - Self::IfGtZ(ins) => ins.__repr__(), - Self::IfLeZ(ins) => ins.__repr__(), - Self::AGet(ins) => ins.__repr__(), - Self::AGetWide(ins) => ins.__repr__(), - Self::AGetObject(ins) => ins.__repr__(), - Self::AGetBoolean(ins) => ins.__repr__(), - Self::AGetByte(ins) => ins.__repr__(), - Self::AGetChar(ins) => ins.__repr__(), - Self::AGetShort(ins) => ins.__repr__(), - Self::APut(ins) => ins.__repr__(), - Self::APutWide(ins) => ins.__repr__(), - Self::APutObject(ins) => ins.__repr__(), - Self::APutBoolean(ins) => ins.__repr__(), - Self::APutByte(ins) => ins.__repr__(), - Self::APutChar(ins) => ins.__repr__(), - Self::APutShort(ins) => ins.__repr__(), - Self::IGet(ins) => ins.__repr__(), - Self::IGetWide(ins) => ins.__repr__(), - Self::IGetObject(ins) => ins.__repr__(), - Self::IGetBoolean(ins) => ins.__repr__(), - Self::IGetByte(ins) => ins.__repr__(), - Self::IGetChar(ins) => ins.__repr__(), - Self::IGetShort(ins) => ins.__repr__(), - Self::IPut(ins) => ins.__repr__(), - Self::IPutWide(ins) => ins.__repr__(), - Self::IPutObject(ins) => ins.__repr__(), - Self::IPutBoolean(ins) => ins.__repr__(), - Self::IPutByte(ins) => ins.__repr__(), - Self::IPutChar(ins) => ins.__repr__(), - Self::IPutShort(ins) => ins.__repr__(), - Self::SGet(ins) => ins.__repr__(), - Self::SGetWide(ins) => ins.__repr__(), - Self::SGetObject(ins) => ins.__repr__(), - Self::SGetBoolean(ins) => ins.__repr__(), - Self::SGetByte(ins) => ins.__repr__(), - Self::SGetChar(ins) => ins.__repr__(), - Self::SGetShort(ins) => ins.__repr__(), - Self::SPut(ins) => ins.__repr__(), - Self::SPutWide(ins) => ins.__repr__(), - Self::SPutObject(ins) => ins.__repr__(), - Self::SPutBoolean(ins) => ins.__repr__(), - Self::SPutByte(ins) => ins.__repr__(), - Self::SPutChar(ins) => ins.__repr__(), - Self::SPutShort(ins) => ins.__repr__(), - Self::InvokeVirtual(ins) => ins.__repr__(), - Self::InvokeSuper(ins) => ins.__repr__(), - Self::InvokeDirect(ins) => ins.__repr__(), - Self::InvokeStatic(ins) => ins.__repr__(), - Self::InvokeInterface(ins) => ins.__repr__(), - Self::NegInt(ins) => ins.__repr__(), - Self::NotInt(ins) => ins.__repr__(), - Self::NegLong(ins) => ins.__repr__(), - Self::NotLong(ins) => ins.__repr__(), - Self::NegFloat(ins) => ins.__repr__(), - Self::NegDouble(ins) => ins.__repr__(), - Self::IntToLong(ins) => ins.__repr__(), - Self::IntToFloat(ins) => ins.__repr__(), - Self::IntToDouble(ins) => ins.__repr__(), - Self::LongToInt(ins) => ins.__repr__(), - Self::LongToFloat(ins) => ins.__repr__(), - Self::LongToDouble(ins) => ins.__repr__(), - Self::FloatToInt(ins) => ins.__repr__(), - Self::FloatToLong(ins) => ins.__repr__(), - Self::FloatToDouble(ins) => ins.__repr__(), - Self::DoubleToInt(ins) => ins.__repr__(), - Self::DoubleToLong(ins) => ins.__repr__(), - Self::DoubleToFloat(ins) => ins.__repr__(), - Self::IntToByte(ins) => ins.__repr__(), - Self::IntToChar(ins) => ins.__repr__(), - Self::IntToShort(ins) => ins.__repr__(), - Self::AddInt(ins) => ins.__repr__(), - Self::SubInt(ins) => ins.__repr__(), - Self::MulInt(ins) => ins.__repr__(), - Self::DivInt(ins) => ins.__repr__(), - Self::RemInt(ins) => ins.__repr__(), - Self::AndInt(ins) => ins.__repr__(), - Self::OrInt(ins) => ins.__repr__(), - Self::XorInt(ins) => ins.__repr__(), - Self::ShlInt(ins) => ins.__repr__(), - Self::ShrInt(ins) => ins.__repr__(), - Self::UshrInt(ins) => ins.__repr__(), - Self::AddLong(ins) => ins.__repr__(), - Self::SubLong(ins) => ins.__repr__(), - Self::MulLong(ins) => ins.__repr__(), - Self::DivLong(ins) => ins.__repr__(), - Self::RemLong(ins) => ins.__repr__(), - Self::AndLong(ins) => ins.__repr__(), - Self::OrLong(ins) => ins.__repr__(), - Self::XorLong(ins) => ins.__repr__(), - Self::ShlLong(ins) => ins.__repr__(), - Self::ShrLong(ins) => ins.__repr__(), - Self::UshrLong(ins) => ins.__repr__(), - Self::AddFloat(ins) => ins.__repr__(), - Self::SubFloat(ins) => ins.__repr__(), - Self::MulFloat(ins) => ins.__repr__(), - Self::DivFloat(ins) => ins.__repr__(), - Self::RemFloat(ins) => ins.__repr__(), - Self::AddDouble(ins) => ins.__repr__(), - Self::SubDouble(ins) => ins.__repr__(), - Self::MulDouble(ins) => ins.__repr__(), - Self::DivDouble(ins) => ins.__repr__(), - Self::RemDouble(ins) => ins.__repr__(), - Self::AddInt2Addr(ins) => ins.__repr__(), - Self::SubInt2Addr(ins) => ins.__repr__(), - Self::MulInt2Addr(ins) => ins.__repr__(), - Self::DivInt2Addr(ins) => ins.__repr__(), - Self::RemInt2Addr(ins) => ins.__repr__(), - Self::AndInt2Addr(ins) => ins.__repr__(), - Self::OrInt2Addr(ins) => ins.__repr__(), - Self::XorInt2Addr(ins) => ins.__repr__(), - Self::ShlInt2Addr(ins) => ins.__repr__(), - Self::ShrInt2Addr(ins) => ins.__repr__(), - Self::UshrInt2Addr(ins) => ins.__repr__(), - Self::AddLong2Addr(ins) => ins.__repr__(), - Self::SubLong2Addr(ins) => ins.__repr__(), - Self::MulLong2Addr(ins) => ins.__repr__(), - Self::DivLong2Addr(ins) => ins.__repr__(), - Self::RemLong2Addr(ins) => ins.__repr__(), - Self::AndLong2Addr(ins) => ins.__repr__(), - Self::OrLong2Addr(ins) => ins.__repr__(), - Self::XorLong2Addr(ins) => ins.__repr__(), - Self::ShlLong2Addr(ins) => ins.__repr__(), - Self::ShrLong2Addr(ins) => ins.__repr__(), - Self::UshrLong2Addr(ins) => ins.__repr__(), - Self::AddFloat2Addr(ins) => ins.__repr__(), - Self::SubFloat2Addr(ins) => ins.__repr__(), - Self::MulFloat2Addr(ins) => ins.__repr__(), - Self::DivFloat2Addr(ins) => ins.__repr__(), - Self::RemFloat2Addr(ins) => ins.__repr__(), - Self::AddDouble2Addr(ins) => ins.__repr__(), - Self::SubDouble2Addr(ins) => ins.__repr__(), - Self::MulDouble2Addr(ins) => ins.__repr__(), - Self::DivDouble2Addr(ins) => ins.__repr__(), - Self::RemDouble2Addr(ins) => ins.__repr__(), - Self::AddIntLit(ins) => ins.__repr__(), - Self::RsubIntLit(ins) => ins.__repr__(), - Self::MulIntLit(ins) => ins.__repr__(), - Self::DivIntLit(ins) => ins.__repr__(), - Self::RemIntLit(ins) => ins.__repr__(), - Self::AndIntLit(ins) => ins.__repr__(), - Self::OrIntLit(ins) => ins.__repr__(), - Self::XorIntLit(ins) => ins.__repr__(), - Self::ShlIntLit(ins) => ins.__repr__(), - Self::ShrIntLit(ins) => ins.__repr__(), - Self::UshrIntLit(ins) => ins.__repr__(), - Self::InvokePolymorphic(ins) => ins.__repr__(), - Self::InvokeCustom(ins) => ins.__repr__(), - Self::ConstMethodHandle(ins) => ins.__repr__(), - Self::ConstMethodType(ins) => ins.__repr__(), - Self::Try(ins) => ins.__repr__(), - Self::Label(ins) => ins.__repr__(), + Self::Move { from, to } => { + format!("Instruction(Move({}, {}))", to, from) + } + Self::MoveWide { from, to } => { + format!("Instruction(MoveWide({}, {}))", to, from) + } + Self::MoveObject { from, to } => { + format!("Instruction(MoveObject({}, {}))", to, from) + } + Self::MoveResult { to } => { + format!("Instruction(MoveResult({}))", to) + } + Self::MoveResultWide { to } => { + format!("Instruction(MoveResultWide({}))", to) + } + Self::MoveResultObject { to } => { + format!("Instruction(MoveResultObject({}))", to) + } + Self::MoveException { to } => { + format!("Instruction(MoveException({}))", to) + } + Self::ReturnVoid {} => "Instruction(ReturnVoid)".into(), + Self::Return { reg } => { + format!("Instruction(Return({}))", reg) + } + Self::ReturnWide { reg } => { + format!("Instruction(ReturnWide({}))", reg) + } + Self::ReturnObject { reg } => { + format!("Instruction(ReturnObject({}))", reg) + } + Self::Const { reg, lit } => { + format!("Instruction(Const({}, {}))", reg, lit) + } + Self::ConstWide { reg, lit } => { + format!("Instruction(ConstWide({}, {}))", reg, lit) + } + Self::ConstString { reg, lit } => { + format!("Instruction(ConstString({}, {}))", reg, lit.__repr__()) + } + Self::ConstClass { reg, lit } => { + format!("Instruction(ConstClass({}, {}))", reg, lit.__repr__()) + } + Self::MonitorEnter { reg } => { + format!("Instruction(MonitorEnter({}))", reg) + } + Self::MonitorExit { reg } => { + format!("Instruction(MonitorExit({}))", reg) + } + Self::CheckCast { reg, lit } => { + format!("Instruction(CheckCast({}, {}))", reg, lit.__repr__()) + } + Self::InstanceOf { obj, lit, dest } => { + format!( + "Instruction(InstanceOf({}, {}, {}))", + dest, + obj, + lit.__repr__() + ) + } + Self::ArrayLength { arr, dest } => { + format!("Instruction(ArrayLength({}, {}))", dest, arr,) + } + Self::NewInstance { reg, lit } => { + format!("Instruction(NewInstance({}, {}))", reg, lit.__repr__()) + } + Self::NewArray { reg, lit, size_reg } => { + format!( + "Instruction(NewArray({}, {}, {}))", + reg, + size_reg, + lit.__repr__() + ) + } + Self::FilledNewArray { type_, reg_values } => { + let args = if reg_values.len() >= 5 { + format!( + "{}, ..., {}", + reg_values[0], + reg_values[reg_values.len() - 1] + ) + } else { + reg_values + .iter() + .map(|v| format!("{v}")) + .collect::>() + .join(", ") + }; + format!( + "Instruction(FilledNewArray([{}], {}))", + args, + type_.__repr__() + ) + } + Self::FillArrayData { + elt_width, + arr, + data, + } => { + let data: String = if data.len() / *elt_width as usize == 0 { + "".into() + } else if data.len() / *elt_width as usize <= 2 { + let mut arr = "".into(); + for (i, v) in data.iter().enumerate() { + if i == 0 { + arr += "0x" + } else if i % *elt_width as usize == 0 { + arr += ", 0x" + } + arr += format!("{v:02x}").as_str(); + } + arr + } else { + let mut arr = "0x".into(); + for v in &data[..*elt_width as usize] { + arr += format!("{v:02x}").as_str(); + } + arr += ", ..., 0x"; + for v in &data[data.len() - *elt_width as usize..] { + arr += format!("{v:02x}").as_str(); + } + + arr + }; + format!("Instruction(FillArrayData({}, [{}]))", arr, data) + } + Self::Throw { reg } => { + format!("Instruction(Throw({}))", reg) + } + Self::Goto { label } => { + format!("Instruction(Goto({}))", label) + } + Self::Switch { reg, .. } => { + format!("Instruction(Switch({}, ...))", reg) + } + Self::CmpLFloat { b, c, dest } => { + format!("Instruction(CmpLFloat({}, {}, {}))", dest, b, c) + } + Self::CmpGFloat { b, c, dest } => { + format!("Instruction(CmpGFloat({}, {}, {}))", dest, b, c) + } + Self::CmpLDouble { b, c, dest } => { + format!("Instruction(CmpLDouble({}, {}, {}))", dest, b, c) + } + Self::CmpGDouble { b, c, dest } => { + format!("Instruction(CmpGDouble({}, {}, {}))", dest, b, c) + } + Self::CmpLong { b, c, dest } => { + format!("Instruction(CmpLong({}, {}, {}))", dest, b, c) + } + Self::IfEq { a, b, label } => { + format!("Instruction(IfEq({}, {}, {}))", a, b, label) + } + Self::IfNe { a, b, label } => { + format!("Instruction(IfNe({}, {}, {}))", a, b, label) + } + Self::IfLt { a, b, label } => { + format!("Instruction(IfLt({}, {}, {}))", a, b, label) + } + Self::IfGe { a, b, label } => { + format!("Instruction(IfGe({}, {}, {}))", a, b, label) + } + Self::IfGt { a, b, label } => { + format!("Instruction(IfGt({}, {}, {}))", a, b, label) + } + Self::IfLe { a, b, label } => { + format!("Instruction(IfLe({}, {}, {}))", a, b, label) + } + Self::IfEqZ { a, label } => { + format!("Instruction(IfEqZ({}, {}))", a, label) + } + Self::IfNeZ { a, label } => { + format!("Instruction(IfNe({}, {}))", a, label) + } + Self::IfLtZ { a, label } => { + format!("Instruction(IfLt({}, {}))", a, label) + } + Self::IfGeZ { a, label } => { + format!("Instruction(IfGe({}, {}))", a, label) + } + Self::IfGtZ { a, label } => { + format!("Instruction(IfGt({}, {}))", a, label) + } + Self::IfLeZ { a, label } => { + format!("Instruction(IfLe({}, {}))", a, label) + } + Self::AGet { idx, arr, dest } => { + format!("Instruction(AGet({}, {}, {}))", dest, arr, idx) + } + Self::AGetWide { idx, arr, dest } => { + format!("Instruction(AGetWide({}, {}, {}))", dest, arr, idx) + } + Self::AGetObject { idx, arr, dest } => { + format!("Instruction(AGetObject({}, {}, {}))", dest, arr, idx) + } + Self::AGetBoolean { idx, arr, dest } => { + format!("Instruction(AGetBoolean({}, {}, {}))", dest, arr, idx) + } + Self::AGetByte { idx, arr, dest } => { + format!("Instruction(AGetByte({}, {}, {}))", dest, arr, idx) + } + Self::AGetChar { idx, arr, dest } => { + format!("Instruction(AGetChar({}, {}, {}))", dest, arr, idx) + } + Self::AGetShort { idx, arr, dest } => { + format!("Instruction(AGetShort({}, {}, {}))", dest, arr, idx) + } + Self::APut { idx, arr, from } => { + format!("Instruction(APut({}, {}, {}))", from, arr, idx) + } + Self::APutWide { idx, arr, from } => { + format!("Instruction(APutWide({}, {}, {}))", from, arr, idx) + } + Self::APutObject { idx, arr, from } => { + format!("Instruction(APutObject({}, {}, {}))", from, arr, idx) + } + Self::APutBoolean { idx, arr, from } => { + format!("Instruction(APutBoolean({}, {}, {}))", from, arr, idx) + } + Self::APutByte { idx, arr, from } => { + format!("Instruction(APutByte({}, {}, {}))", from, arr, idx) + } + Self::APutChar { idx, arr, from } => { + format!("Instruction(APutChar({}, {}, {}))", from, arr, idx) + } + Self::APutShort { idx, arr, from } => { + format!("Instruction(APutShort({}, {}, {}))", from, arr, idx) + } + Self::IGet { obj, field, to } => { + format!("Instruction(IGet({}, {}, {}))", to, obj, field.__repr__()) + } + Self::IGetWide { obj, field, to } => { + format!( + "Instruction(IGetWide({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IGetObject { obj, field, to } => { + format!( + "Instruction(IGetObject({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IGetBoolean { obj, field, to } => { + format!( + "Instruction(IGetBoolean({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IGetByte { obj, field, to } => { + format!( + "Instruction(IGetByte({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IGetChar { obj, field, to } => { + format!( + "Instruction(IGetChar({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IGetShort { obj, field, to } => { + format!( + "Instruction(IGetShort({}, {}, {}))", + to, + obj, + field.__repr__() + ) + } + Self::IPut { obj, field, from } => { + format!("Instruction(IPut({}, {}, {}))", from, obj, field.__repr__()) + } + Self::IPutWide { obj, field, from } => { + format!( + "Instruction(IPutWide({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::IPutObject { obj, field, from } => { + format!( + "Instruction(IPutObject({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::IPutBoolean { obj, field, from } => { + format!( + "Instruction(IPutBoolean({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::IPutByte { obj, field, from } => { + format!( + "Instruction(IPutByte({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::IPutChar { obj, field, from } => { + format!( + "Instruction(IPutChar({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::IPutShort { obj, field, from } => { + format!( + "Instruction(IPutShort({}, {}, {}))", + from, + obj, + field.__repr__() + ) + } + Self::SGet { field, to } => { + format!("Instruction(SGet({}, {}))", to, field.__repr__()) + } + Self::SGetWide { field, to } => { + format!("Instruction(SGetWide({}, {}))", to, field.__repr__()) + } + Self::SGetObject { field, to } => { + format!("Instruction(SGetObject({}, {}))", to, field.__repr__()) + } + Self::SGetBoolean { field, to } => { + format!("Instruction(SGetBoolean({}, {}))", to, field.__repr__()) + } + Self::SGetByte { field, to } => { + format!("Instruction(SGetByte({}, {}))", to, field.__repr__()) + } + Self::SGetChar { field, to } => { + format!("Instruction(SGetChar({}, {}))", to, field.__repr__()) + } + Self::SGetShort { field, to } => { + format!("Instruction(SGetShort({}, {}))", to, field.__repr__()) + } + Self::SPut { field, from } => { + format!("Instruction(SPut({}, {}))", from, field.__repr__()) + } + Self::SPutWide { field, from } => { + format!("Instruction(SPutWide({}, {}))", from, field.__repr__()) + } + Self::SPutObject { field, from } => { + format!("Instruction(SPutObject({}, {}))", from, field.__repr__()) + } + Self::SPutBoolean { field, from } => { + format!("Instruction(SPutBoolean({}, {}))", from, field.__repr__()) + } + Self::SPutByte { field, from } => { + format!("Instruction(SPutByte({}, {}))", from, field.__repr__()) + } + Self::SPutChar { field, from } => { + format!("Instruction(SPutChar({}, {}))", from, field.__repr__()) + } + Self::SPutShort { field, from } => { + format!("Instruction(SPutShort({}, {}))", from, field.__repr__()) + } + Self::InvokeVirtual { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("Instruction(InvokeVirtual({}, {}))", args, method.__str__()) + } + Self::InvokeSuper { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("Instruction(InvokeSuper({}, {}))", args, method.__str__()) + } + Self::InvokeDirect { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("Instruction(InvokeDirect({}, {}))", args, method.__str__()) + } + Self::InvokeStatic { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!("Instruction(InvokeStatic({}, {}))", args, method.__str__()) + } + Self::InvokeInterface { args, method } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!( + "Instruction(InvokeInterface({}, {}))", + args, + method.__str__() + ) + } + Self::NegInt { val, dest } => { + format!("Instruction(NegInt({}, {}))", dest, val) + } + Self::NotInt { val, dest } => { + format!("Instruction(NotInt({}, {}))", dest, val) + } + Self::NegLong { val, dest } => { + format!("Instruction(NegLong({}, {}))", dest, val) + } + Self::NotLong { val, dest } => { + format!("Instruction(NotLong({}, {}))", dest, val) + } + Self::NegFloat { val, dest } => { + format!("Instruction(NegFloat({}, {}))", dest, val) + } + Self::NegDouble { val, dest } => { + format!("Instruction(NegDouble({}, {}))", dest, val) + } + Self::IntToLong { val, dest } => { + format!("Instruction(IntToLong({}, {}))", dest, val) + } + Self::IntToFloat { val, dest } => { + format!("Instruction(IntToFloat({}, {}))", dest, val) + } + Self::IntToDouble { val, dest } => { + format!("Instruction(IntToDouble({}, {}))", dest, val) + } + Self::LongToInt { val, dest } => { + format!("Instruction(LongToInt({}, {}))", dest, val) + } + Self::LongToFloat { val, dest } => { + format!("Instruction(LongToFloat({}, {}))", dest, val) + } + Self::LongToDouble { val, dest } => { + format!("Instruction(LongToDouble({}, {}))", dest, val) + } + Self::FloatToInt { val, dest } => { + format!("Instruction(FloatToInt({}, {}))", dest, val) + } + Self::FloatToLong { val, dest } => { + format!("Instruction(FloatToLong({}, {}))", dest, val) + } + Self::FloatToDouble { val, dest } => { + format!("Instruction(FloatToDouble({}, {}))", dest, val) + } + Self::DoubleToInt { val, dest } => { + format!("Instruction(DoubleToInt({}, {}))", dest, val) + } + Self::DoubleToLong { val, dest } => { + format!("Instruction(DoubleToLong({}, {}))", dest, val) + } + Self::DoubleToFloat { val, dest } => { + format!("Instruction(DoubleToFloat({}, {}))", dest, val) + } + Self::IntToByte { val, dest } => { + format!("Instruction(IntToByte({}, {}))", dest, val) + } + Self::IntToChar { val, dest } => { + format!("Instruction(IntToChar({}, {}))", dest, val) + } + Self::IntToShort { val, dest } => { + format!("Instruction(IntToShort({}, {}))", dest, val) + } + Self::AddInt { b, c, dest } => { + format!("Instruction(AddInt({}, {}, {}))", dest, b, c) + } + Self::SubInt { b, c, dest } => { + format!("Instruction(SubInt({}, {}, {}))", dest, b, c) + } + Self::MulInt { b, c, dest } => { + format!("Instruction(MulInt({}, {}, {}))", dest, b, c) + } + Self::DivInt { b, c, dest } => { + format!("Instruction(DivInt({}, {}, {}))", dest, b, c) + } + Self::RemInt { b, c, dest } => { + format!("Instruction(RemInt({}, {}, {}))", dest, b, c) + } + Self::AndInt { b, c, dest } => { + format!("Instruction(AndInt({}, {}, {}))", dest, b, c) + } + Self::OrInt { b, c, dest } => { + format!("Instruction(OrInt({}, {}, {}))", dest, b, c) + } + Self::XorInt { b, c, dest } => { + format!("Instruction(XorInt({}, {}, {}))", dest, b, c) + } + Self::ShlInt { b, c, dest } => { + format!("Instruction(ShlInt({}, {}, {}))", dest, b, c) + } + Self::ShrInt { b, c, dest } => { + format!("Instruction(ShrInt({}, {}, {}))", dest, b, c) + } + Self::UshrInt { b, c, dest } => { + format!("Instruction(UshrInt({}, {}, {}))", dest, b, c) + } + Self::AddLong { b, c, dest } => { + format!("Instruction(AddLong({}, {}, {}))", dest, b, c) + } + Self::SubLong { b, c, dest } => { + format!("Instruction(SubLong({}, {}, {}))", dest, b, c) + } + Self::MulLong { b, c, dest } => { + format!("Instruction(MulLong({}, {}, {}))", dest, b, c) + } + Self::DivLong { b, c, dest } => { + format!("Instruction(DivLong({}, {}, {}))", dest, b, c) + } + Self::RemLong { b, c, dest } => { + format!("Instruction(RemLong({}, {}, {}))", dest, b, c) + } + Self::AndLong { b, c, dest } => { + format!("Instruction(AndLong({}, {}, {}))", dest, b, c) + } + Self::OrLong { b, c, dest } => { + format!("Instruction(OrLong({}, {}, {}))", dest, b, c) + } + Self::XorLong { b, c, dest } => { + format!("Instruction(XorLong({}, {}, {}))", dest, b, c) + } + Self::ShlLong { b, c, dest } => { + format!("Instruction(ShlLong({}, {}, {}))", dest, b, c) + } + Self::ShrLong { b, c, dest } => { + format!("Instruction(ShrLong({}, {}, {}))", dest, b, c) + } + Self::UshrLong { b, c, dest } => { + format!("Instruction(UshrLong({}, {}, {}))", dest, b, c) + } + Self::AddFloat { b, c, dest } => { + format!("Instruction(AddFloat({}, {}, {}))", dest, b, c) + } + Self::SubFloat { b, c, dest } => { + format!("Instruction(SubFloat({}, {}, {}))", dest, b, c) + } + Self::MulFloat { b, c, dest } => { + format!("Instruction(MulFloat({}, {}, {}))", dest, b, c) + } + Self::DivFloat { b, c, dest } => { + format!("Instruction(DivFloat({}, {}, {}))", dest, b, c) + } + Self::RemFloat { b, c, dest } => { + format!("Instruction(RemFloat({}, {}, {}))", dest, b, c) + } + Self::AddDouble { b, c, dest } => { + format!("Instruction(AddDouble({}, {}, {}))", dest, b, c) + } + Self::SubDouble { b, c, dest } => { + format!("Instruction(SubDouble({}, {}, {}))", dest, b, c) + } + Self::MulDouble { b, c, dest } => { + format!("Instruction(MulDouble({}, {}, {}))", dest, b, c) + } + Self::DivDouble { b, c, dest } => { + format!("Instruction(DivDouble({}, {}, {}))", dest, b, c) + } + Self::RemDouble { b, c, dest } => { + format!("Instruction(RemDouble({}, {}, {}))", dest, b, c) + } + Self::AddInt2Addr { b, dest } => { + format!("Instruction(AddInt2Addr({}, {}))", dest, b) + } + Self::SubInt2Addr { b, dest } => { + format!("Instruction(SubInt2Addr({}, {}))", dest, b) + } + Self::MulInt2Addr { b, dest } => { + format!("Instruction(MulInt2Addr({}, {}))", dest, b) + } + Self::DivInt2Addr { b, dest } => { + format!("Instruction(DivInt2Addr({}, {}))", dest, b) + } + Self::RemInt2Addr { b, dest } => { + format!("Instruction(RemInt2Addr({}, {}))", dest, b) + } + Self::AndInt2Addr { b, dest } => { + format!("Instruction(AndInt2Addr({}, {}))", dest, b) + } + Self::OrInt2Addr { b, dest } => { + format!("Instruction(OrInt2Addr({}, {}))", dest, b) + } + Self::XorInt2Addr { b, dest } => { + format!("Instruction(XorInt2Addr({}, {}))", dest, b) + } + Self::ShlInt2Addr { b, dest } => { + format!("Instruction(ShlInt2Addr({}, {}))", dest, b) + } + Self::ShrInt2Addr { b, dest } => { + format!("Instruction(ShrInt2Addr({}, {}))", dest, b) + } + Self::UshrInt2Addr { b, dest } => { + format!("Instruction(UshrInt2Addr({}, {}))", dest, b) + } + Self::AddLong2Addr { b, dest } => { + format!("Instruction(AddLong2Addr({}, {}))", dest, b) + } + Self::SubLong2Addr { b, dest } => { + format!("Instruction(SubLong2Addr({}, {}))", dest, b) + } + Self::MulLong2Addr { b, dest } => { + format!("Instruction(MulLong2Addr({}, {}))", dest, b) + } + Self::DivLong2Addr { b, dest } => { + format!("Instruction(DivLong2Addr({}, {}))", dest, b) + } + Self::RemLong2Addr { b, dest } => { + format!("Instruction(RemLong2Addr({}, {}))", dest, b) + } + Self::AndLong2Addr { b, dest } => { + format!("Instruction(AndLong2Addr({}, {}))", dest, b) + } + Self::OrLong2Addr { b, dest } => { + format!("Instruction(OrLong2Addr({}, {}))", dest, b) + } + Self::XorLong2Addr { b, dest } => { + format!("Instruction(XorLong2Addr({}, {}))", dest, b) + } + Self::ShlLong2Addr { b, dest } => { + format!("Instruction(ShlLong2Addr({}, {}))", dest, b) + } + Self::ShrLong2Addr { b, dest } => { + format!("Instruction(ShrLong2Addr({}, {}))", dest, b) + } + Self::UshrLong2Addr { b, dest } => { + format!("Instruction(UshrLong2Addr({}, {}))", dest, b) + } + Self::AddFloat2Addr { b, dest } => { + format!("Instruction(AddFloat2Addr({}, {}))", dest, b) + } + Self::SubFloat2Addr { b, dest } => { + format!("Instruction(SubFloat2Addr({}, {}))", dest, b) + } + Self::MulFloat2Addr { b, dest } => { + format!("Instruction(MulFloat2Addr({}, {}))", dest, b) + } + Self::DivFloat2Addr { b, dest } => { + format!("Instruction(DivFloat2Addr({}, {}))", dest, b) + } + Self::RemFloat2Addr { b, dest } => { + format!("Instruction(RemFloat2Addr({}, {}))", dest, b) + } + Self::AddDouble2Addr { b, dest } => { + format!("Instruction(AddDouble2Addr({}, {}))", dest, b) + } + Self::SubDouble2Addr { b, dest } => { + format!("Instruction(SubDouble2Addr({}, {}))", dest, b) + } + Self::MulDouble2Addr { b, dest } => { + format!("Instruction(MulDouble2Addr({}, {}))", dest, b) + } + Self::DivDouble2Addr { b, dest } => { + format!("Instruction(DivDouble2Addr({}, {}))", dest, b) + } + Self::RemDouble2Addr { b, dest } => { + format!("Instruction(RemDouble2Addr({}, {}))", dest, b) + } + Self::AddIntLit { b, lit, dest } => { + format!("Instruction(AddIntLit({}, {}, {}))", dest, b, lit) + } + Self::RsubIntLit { b, lit, dest } => { + format!("Instruction(RsubIntLit({}, {}, {}))", dest, b, lit) + } + Self::MulIntLit { b, lit, dest } => { + format!("Instruction(MulIntLit({}, {}, {}))", dest, b, lit) + } + Self::DivIntLit { b, lit, dest } => { + format!("Instruction(DivIntLit({}, {}, {}))", dest, b, lit) + } + Self::RemIntLit { b, lit, dest } => { + format!("Instruction(RemIntLit({}, {}, {}))", dest, b, lit) + } + Self::AndIntLit { b, lit, dest } => { + format!("Instruction(AndIntLit({}, {}, {}))", dest, b, lit) + } + Self::OrIntLit { b, lit, dest } => { + format!("Instruction(OrIntLit({}, {}, {}))", dest, b, lit) + } + Self::XorIntLit { b, lit, dest } => { + format!("Instruction(XorIntLit({}, {}, {}))", dest, b, lit) + } + Self::ShlIntLit { b, lit, dest } => { + format!("Instruction(ShlIntLit({}, {}, {}))", dest, b, lit) + } + Self::ShrIntLit { b, lit, dest } => { + format!("Instruction(ShrIntLit({}, {}, {}))", dest, b, lit) + } + Self::UshrIntLit { b, lit, dest } => { + format!("Instruction(UshrIntLit({}, {}, {}))", dest, b, lit) + } + Self::InvokePolymorphic { + args, + proto, + method, + } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!( + "Instruction(InvokePolymorphic({}, {}, {}))", + args, + method.__str__(), + proto.__str__() + ) + } + Self::InvokeCustom { args, call_site } => { + let args = if args.len() >= 5 { + format!("{} .. {}", args[0], args[args.len() - 1]) + } else { + args.iter() + .map(|v| format!("{v}")) + .collect::>() + .join(" ") + }; + format!( + "Instruction(InvokeCustom({}, {}))", + args, + call_site.__str__(), + ) + } + Self::ConstMethodHandle { handle, to } => { + format!( + "Instruction(ConstMethodHandle({}, {}))", + to, + handle.__repr__() + ) + } + Self::ConstMethodType { proto, to } => { + format!("Instruction(ConstMethodType({}, {}))", to, proto.__repr__()) + } + Self::Try { + end_label, + default_handler, + handlers, + } => { + let handlers = handlers + .iter() + .map(|(ty, label)| format!("{}, {label}", ty.__repr__())) + .collect::>() + .join(", "); + format!( + "Instruction(Try({}, [{}], {:?}))", + end_label, handlers, default_handler, + ) + } + Self::Label { name } => { + format!("Instruction(Label({}))", name) + } } } @@ -1852,200 +3416,9 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn min_ins_size(&self) -> usize { match self { - Self::Nop {} => self.get_raw_ins().unwrap().size(), - Self::Move(ins) => ins.min_ins_size(), - Self::MoveWide(ins) => ins.min_ins_size(), - Self::MoveObject(ins) => ins.min_ins_size(), - Self::MoveResult(ins) => ins.min_ins_size(), - Self::MoveResultWide(ins) => ins.min_ins_size(), - Self::MoveException(ins) => ins.min_ins_size(), - Self::MoveResultObject(ins) => ins.min_ins_size(), - Self::ReturnVoid(ins) => ins.min_ins_size(), - Self::Return(ins) => ins.min_ins_size(), - Self::ReturnWide(ins) => ins.min_ins_size(), - Self::ReturnObject(ins) => ins.min_ins_size(), - Self::Const(ins) => ins.min_ins_size(), - Self::ConstWide(ins) => ins.min_ins_size(), - Self::ConstString(ins) => ins.min_ins_size(), - Self::ConstClass(ins) => ins.min_ins_size(), - Self::MonitorEnter(ins) => ins.min_ins_size(), - Self::MonitorExit(ins) => ins.min_ins_size(), - Self::CheckCast(ins) => ins.min_ins_size(), - Self::InstanceOf(ins) => ins.min_ins_size(), - Self::ArrayLength(ins) => ins.min_ins_size(), - Self::NewInstance(ins) => ins.min_ins_size(), - Self::NewArray(ins) => ins.min_ins_size(), - Self::FilledNewArray(ins) => ins.min_ins_size(), - Self::FillArrayData(ins) => ins.min_ins_size(), - Self::Throw(ins) => ins.min_ins_size(), - Self::Goto(ins) => ins.min_ins_size(), - Self::Switch(ins) => ins.min_ins_size(), - Self::CmpLFloat(ins) => ins.min_ins_size(), - Self::CmpGFloat(ins) => ins.min_ins_size(), - Self::CmpLDouble(ins) => ins.min_ins_size(), - Self::CmpGDouble(ins) => ins.min_ins_size(), - Self::CmpLong(ins) => ins.min_ins_size(), - Self::IfEq(ins) => ins.min_ins_size(), - Self::IfNe(ins) => ins.min_ins_size(), - Self::IfLt(ins) => ins.min_ins_size(), - Self::IfGe(ins) => ins.min_ins_size(), - Self::IfGt(ins) => ins.min_ins_size(), - Self::IfLe(ins) => ins.min_ins_size(), - Self::IfEqZ(ins) => ins.min_ins_size(), - Self::IfNeZ(ins) => ins.min_ins_size(), - Self::IfLtZ(ins) => ins.min_ins_size(), - Self::IfGeZ(ins) => ins.min_ins_size(), - Self::IfGtZ(ins) => ins.min_ins_size(), - Self::IfLeZ(ins) => ins.min_ins_size(), - Self::AGet(ins) => ins.min_ins_size(), - Self::AGetWide(ins) => ins.min_ins_size(), - Self::AGetObject(ins) => ins.min_ins_size(), - Self::AGetBoolean(ins) => ins.min_ins_size(), - Self::AGetByte(ins) => ins.min_ins_size(), - Self::AGetChar(ins) => ins.min_ins_size(), - Self::AGetShort(ins) => ins.min_ins_size(), - Self::APut(ins) => ins.min_ins_size(), - Self::APutWide(ins) => ins.min_ins_size(), - Self::APutObject(ins) => ins.min_ins_size(), - Self::APutBoolean(ins) => ins.min_ins_size(), - Self::APutByte(ins) => ins.min_ins_size(), - Self::APutChar(ins) => ins.min_ins_size(), - Self::APutShort(ins) => ins.min_ins_size(), - Self::IGet(ins) => ins.min_ins_size(), - Self::IGetWide(ins) => ins.min_ins_size(), - Self::IGetObject(ins) => ins.min_ins_size(), - Self::IGetBoolean(ins) => ins.min_ins_size(), - Self::IGetByte(ins) => ins.min_ins_size(), - Self::IGetChar(ins) => ins.min_ins_size(), - Self::IGetShort(ins) => ins.min_ins_size(), - Self::IPut(ins) => ins.min_ins_size(), - Self::IPutWide(ins) => ins.min_ins_size(), - Self::IPutObject(ins) => ins.min_ins_size(), - Self::IPutBoolean(ins) => ins.min_ins_size(), - Self::IPutByte(ins) => ins.min_ins_size(), - Self::IPutChar(ins) => ins.min_ins_size(), - Self::IPutShort(ins) => ins.min_ins_size(), - Self::SGet(ins) => ins.min_ins_size(), - Self::SGetWide(ins) => ins.min_ins_size(), - Self::SGetObject(ins) => ins.min_ins_size(), - Self::SGetBoolean(ins) => ins.min_ins_size(), - Self::SGetByte(ins) => ins.min_ins_size(), - Self::SGetChar(ins) => ins.min_ins_size(), - Self::SGetShort(ins) => ins.min_ins_size(), - Self::SPut(ins) => ins.min_ins_size(), - Self::SPutWide(ins) => ins.min_ins_size(), - Self::SPutObject(ins) => ins.min_ins_size(), - Self::SPutBoolean(ins) => ins.min_ins_size(), - Self::SPutByte(ins) => ins.min_ins_size(), - Self::SPutChar(ins) => ins.min_ins_size(), - Self::SPutShort(ins) => ins.min_ins_size(), - Self::InvokeVirtual(ins) => ins.min_ins_size(), - Self::InvokeSuper(ins) => ins.min_ins_size(), - Self::InvokeDirect(ins) => ins.min_ins_size(), - Self::InvokeStatic(ins) => ins.min_ins_size(), - Self::InvokeInterface(ins) => ins.min_ins_size(), - Self::NegInt(ins) => ins.min_ins_size(), - Self::NotInt(ins) => ins.min_ins_size(), - Self::NegLong(ins) => ins.min_ins_size(), - Self::NotLong(ins) => ins.min_ins_size(), - Self::NegFloat(ins) => ins.min_ins_size(), - Self::NegDouble(ins) => ins.min_ins_size(), - Self::IntToLong(ins) => ins.min_ins_size(), - Self::IntToFloat(ins) => ins.min_ins_size(), - Self::IntToDouble(ins) => ins.min_ins_size(), - Self::LongToInt(ins) => ins.min_ins_size(), - Self::LongToFloat(ins) => ins.min_ins_size(), - Self::LongToDouble(ins) => ins.min_ins_size(), - Self::FloatToInt(ins) => ins.min_ins_size(), - Self::FloatToLong(ins) => ins.min_ins_size(), - Self::FloatToDouble(ins) => ins.min_ins_size(), - Self::DoubleToInt(ins) => ins.min_ins_size(), - Self::DoubleToLong(ins) => ins.min_ins_size(), - Self::DoubleToFloat(ins) => ins.min_ins_size(), - Self::IntToByte(ins) => ins.min_ins_size(), - Self::IntToChar(ins) => ins.min_ins_size(), - Self::IntToShort(ins) => ins.min_ins_size(), - Self::AddInt(ins) => ins.min_ins_size(), - Self::SubInt(ins) => ins.min_ins_size(), - Self::MulInt(ins) => ins.min_ins_size(), - Self::DivInt(ins) => ins.min_ins_size(), - Self::RemInt(ins) => ins.min_ins_size(), - Self::AndInt(ins) => ins.min_ins_size(), - Self::OrInt(ins) => ins.min_ins_size(), - Self::XorInt(ins) => ins.min_ins_size(), - Self::ShlInt(ins) => ins.min_ins_size(), - Self::ShrInt(ins) => ins.min_ins_size(), - Self::UshrInt(ins) => ins.min_ins_size(), - Self::AddLong(ins) => ins.min_ins_size(), - Self::SubLong(ins) => ins.min_ins_size(), - Self::MulLong(ins) => ins.min_ins_size(), - Self::DivLong(ins) => ins.min_ins_size(), - Self::RemLong(ins) => ins.min_ins_size(), - Self::AndLong(ins) => ins.min_ins_size(), - Self::OrLong(ins) => ins.min_ins_size(), - Self::XorLong(ins) => ins.min_ins_size(), - Self::ShlLong(ins) => ins.min_ins_size(), - Self::ShrLong(ins) => ins.min_ins_size(), - Self::UshrLong(ins) => ins.min_ins_size(), - Self::AddFloat(ins) => ins.min_ins_size(), - Self::SubFloat(ins) => ins.min_ins_size(), - Self::MulFloat(ins) => ins.min_ins_size(), - Self::DivFloat(ins) => ins.min_ins_size(), - Self::RemFloat(ins) => ins.min_ins_size(), - Self::AddDouble(ins) => ins.min_ins_size(), - Self::SubDouble(ins) => ins.min_ins_size(), - Self::MulDouble(ins) => ins.min_ins_size(), - Self::DivDouble(ins) => ins.min_ins_size(), - Self::RemDouble(ins) => ins.min_ins_size(), - Self::AddInt2Addr(ins) => ins.min_ins_size(), - Self::SubInt2Addr(ins) => ins.min_ins_size(), - Self::MulInt2Addr(ins) => ins.min_ins_size(), - Self::DivInt2Addr(ins) => ins.min_ins_size(), - Self::RemInt2Addr(ins) => ins.min_ins_size(), - Self::AndInt2Addr(ins) => ins.min_ins_size(), - Self::OrInt2Addr(ins) => ins.min_ins_size(), - Self::XorInt2Addr(ins) => ins.min_ins_size(), - Self::ShlInt2Addr(ins) => ins.min_ins_size(), - Self::ShrInt2Addr(ins) => ins.min_ins_size(), - Self::UshrInt2Addr(ins) => ins.min_ins_size(), - Self::AddLong2Addr(ins) => ins.min_ins_size(), - Self::SubLong2Addr(ins) => ins.min_ins_size(), - Self::MulLong2Addr(ins) => ins.min_ins_size(), - Self::DivLong2Addr(ins) => ins.min_ins_size(), - Self::RemLong2Addr(ins) => ins.min_ins_size(), - Self::AndLong2Addr(ins) => ins.min_ins_size(), - Self::OrLong2Addr(ins) => ins.min_ins_size(), - Self::XorLong2Addr(ins) => ins.min_ins_size(), - Self::ShlLong2Addr(ins) => ins.min_ins_size(), - Self::ShrLong2Addr(ins) => ins.min_ins_size(), - Self::UshrLong2Addr(ins) => ins.min_ins_size(), - Self::AddFloat2Addr(ins) => ins.min_ins_size(), - Self::SubFloat2Addr(ins) => ins.min_ins_size(), - Self::MulFloat2Addr(ins) => ins.min_ins_size(), - Self::DivFloat2Addr(ins) => ins.min_ins_size(), - Self::RemFloat2Addr(ins) => ins.min_ins_size(), - Self::AddDouble2Addr(ins) => ins.min_ins_size(), - Self::SubDouble2Addr(ins) => ins.min_ins_size(), - Self::MulDouble2Addr(ins) => ins.min_ins_size(), - Self::DivDouble2Addr(ins) => ins.min_ins_size(), - Self::RemDouble2Addr(ins) => ins.min_ins_size(), - Self::AddIntLit(ins) => ins.min_ins_size(), - Self::RsubIntLit(ins) => ins.min_ins_size(), - Self::MulIntLit(ins) => ins.min_ins_size(), - Self::DivIntLit(ins) => ins.min_ins_size(), - Self::RemIntLit(ins) => ins.min_ins_size(), - Self::AndIntLit(ins) => ins.min_ins_size(), - Self::OrIntLit(ins) => ins.min_ins_size(), - Self::XorIntLit(ins) => ins.min_ins_size(), - Self::ShlIntLit(ins) => ins.min_ins_size(), - Self::ShrIntLit(ins) => ins.min_ins_size(), - Self::UshrIntLit(ins) => ins.min_ins_size(), - Self::InvokePolymorphic(ins) => ins.min_ins_size(), - Self::InvokeCustom(ins) => ins.min_ins_size(), - Self::ConstMethodHandle(ins) => ins.min_ins_size(), - Self::ConstMethodType(ins) => ins.min_ins_size(), - Self::Try(ins) => ins.min_ins_size(), - Self::Label(ins) => ins.min_ins_size(), + Self::ConstString { .. } => 4, + Self::Goto { .. } => 2, + _ => self.ins_size().unwrap(), } } @@ -2058,200 +3431,9 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn max_ins_size(&self) -> usize { match self { - Self::Nop {} => self.get_raw_ins().unwrap().size(), - Self::Move(ins) => ins.max_ins_size(), - Self::MoveWide(ins) => ins.max_ins_size(), - Self::MoveObject(ins) => ins.max_ins_size(), - Self::MoveResult(ins) => ins.max_ins_size(), - Self::MoveResultWide(ins) => ins.max_ins_size(), - Self::MoveException(ins) => ins.max_ins_size(), - Self::MoveResultObject(ins) => ins.max_ins_size(), - Self::ReturnVoid(ins) => ins.max_ins_size(), - Self::Return(ins) => ins.max_ins_size(), - Self::ReturnWide(ins) => ins.max_ins_size(), - Self::ReturnObject(ins) => ins.max_ins_size(), - Self::Const(ins) => ins.max_ins_size(), - Self::ConstWide(ins) => ins.max_ins_size(), - Self::ConstString(ins) => ins.max_ins_size(), - Self::ConstClass(ins) => ins.max_ins_size(), - Self::MonitorEnter(ins) => ins.max_ins_size(), - Self::MonitorExit(ins) => ins.max_ins_size(), - Self::CheckCast(ins) => ins.max_ins_size(), - Self::InstanceOf(ins) => ins.max_ins_size(), - Self::ArrayLength(ins) => ins.max_ins_size(), - Self::NewInstance(ins) => ins.max_ins_size(), - Self::NewArray(ins) => ins.max_ins_size(), - Self::FilledNewArray(ins) => ins.max_ins_size(), - Self::FillArrayData(ins) => ins.max_ins_size(), - Self::Throw(ins) => ins.max_ins_size(), - Self::Goto(ins) => ins.max_ins_size(), - Self::Switch(ins) => ins.max_ins_size(), - Self::CmpLFloat(ins) => ins.max_ins_size(), - Self::CmpGFloat(ins) => ins.max_ins_size(), - Self::CmpLDouble(ins) => ins.max_ins_size(), - Self::CmpGDouble(ins) => ins.max_ins_size(), - Self::CmpLong(ins) => ins.max_ins_size(), - Self::IfEq(ins) => ins.max_ins_size(), - Self::IfNe(ins) => ins.max_ins_size(), - Self::IfLt(ins) => ins.max_ins_size(), - Self::IfGe(ins) => ins.max_ins_size(), - Self::IfGt(ins) => ins.max_ins_size(), - Self::IfLe(ins) => ins.max_ins_size(), - Self::IfEqZ(ins) => ins.max_ins_size(), - Self::IfNeZ(ins) => ins.max_ins_size(), - Self::IfLtZ(ins) => ins.max_ins_size(), - Self::IfGeZ(ins) => ins.max_ins_size(), - Self::IfGtZ(ins) => ins.max_ins_size(), - Self::IfLeZ(ins) => ins.max_ins_size(), - Self::AGet(ins) => ins.max_ins_size(), - Self::AGetWide(ins) => ins.max_ins_size(), - Self::AGetObject(ins) => ins.max_ins_size(), - Self::AGetBoolean(ins) => ins.max_ins_size(), - Self::AGetByte(ins) => ins.max_ins_size(), - Self::AGetChar(ins) => ins.max_ins_size(), - Self::AGetShort(ins) => ins.max_ins_size(), - Self::APut(ins) => ins.max_ins_size(), - Self::APutWide(ins) => ins.max_ins_size(), - Self::APutObject(ins) => ins.max_ins_size(), - Self::APutBoolean(ins) => ins.max_ins_size(), - Self::APutByte(ins) => ins.max_ins_size(), - Self::APutChar(ins) => ins.max_ins_size(), - Self::APutShort(ins) => ins.max_ins_size(), - Self::IGet(ins) => ins.max_ins_size(), - Self::IGetWide(ins) => ins.max_ins_size(), - Self::IGetObject(ins) => ins.max_ins_size(), - Self::IGetBoolean(ins) => ins.max_ins_size(), - Self::IGetByte(ins) => ins.max_ins_size(), - Self::IGetChar(ins) => ins.max_ins_size(), - Self::IGetShort(ins) => ins.max_ins_size(), - Self::IPut(ins) => ins.max_ins_size(), - Self::IPutWide(ins) => ins.max_ins_size(), - Self::IPutObject(ins) => ins.max_ins_size(), - Self::IPutBoolean(ins) => ins.max_ins_size(), - Self::IPutByte(ins) => ins.max_ins_size(), - Self::IPutChar(ins) => ins.max_ins_size(), - Self::IPutShort(ins) => ins.max_ins_size(), - Self::SGet(ins) => ins.max_ins_size(), - Self::SGetWide(ins) => ins.max_ins_size(), - Self::SGetObject(ins) => ins.max_ins_size(), - Self::SGetBoolean(ins) => ins.max_ins_size(), - Self::SGetByte(ins) => ins.max_ins_size(), - Self::SGetChar(ins) => ins.max_ins_size(), - Self::SGetShort(ins) => ins.max_ins_size(), - Self::SPut(ins) => ins.max_ins_size(), - Self::SPutWide(ins) => ins.max_ins_size(), - Self::SPutObject(ins) => ins.max_ins_size(), - Self::SPutBoolean(ins) => ins.max_ins_size(), - Self::SPutByte(ins) => ins.max_ins_size(), - Self::SPutChar(ins) => ins.max_ins_size(), - Self::SPutShort(ins) => ins.max_ins_size(), - Self::InvokeVirtual(ins) => ins.max_ins_size(), - Self::InvokeSuper(ins) => ins.max_ins_size(), - Self::InvokeDirect(ins) => ins.max_ins_size(), - Self::InvokeStatic(ins) => ins.max_ins_size(), - Self::InvokeInterface(ins) => ins.max_ins_size(), - Self::NegInt(ins) => ins.max_ins_size(), - Self::NotInt(ins) => ins.max_ins_size(), - Self::NegLong(ins) => ins.max_ins_size(), - Self::NotLong(ins) => ins.max_ins_size(), - Self::NegFloat(ins) => ins.max_ins_size(), - Self::NegDouble(ins) => ins.max_ins_size(), - Self::IntToLong(ins) => ins.max_ins_size(), - Self::IntToFloat(ins) => ins.max_ins_size(), - Self::IntToDouble(ins) => ins.max_ins_size(), - Self::LongToInt(ins) => ins.max_ins_size(), - Self::LongToFloat(ins) => ins.max_ins_size(), - Self::LongToDouble(ins) => ins.max_ins_size(), - Self::FloatToInt(ins) => ins.max_ins_size(), - Self::FloatToLong(ins) => ins.max_ins_size(), - Self::FloatToDouble(ins) => ins.max_ins_size(), - Self::DoubleToInt(ins) => ins.max_ins_size(), - Self::DoubleToLong(ins) => ins.max_ins_size(), - Self::DoubleToFloat(ins) => ins.max_ins_size(), - Self::IntToByte(ins) => ins.max_ins_size(), - Self::IntToChar(ins) => ins.max_ins_size(), - Self::IntToShort(ins) => ins.max_ins_size(), - Self::AddInt(ins) => ins.max_ins_size(), - Self::SubInt(ins) => ins.max_ins_size(), - Self::MulInt(ins) => ins.max_ins_size(), - Self::DivInt(ins) => ins.max_ins_size(), - Self::RemInt(ins) => ins.max_ins_size(), - Self::AndInt(ins) => ins.max_ins_size(), - Self::OrInt(ins) => ins.max_ins_size(), - Self::XorInt(ins) => ins.max_ins_size(), - Self::ShlInt(ins) => ins.max_ins_size(), - Self::ShrInt(ins) => ins.max_ins_size(), - Self::UshrInt(ins) => ins.max_ins_size(), - Self::AddLong(ins) => ins.max_ins_size(), - Self::SubLong(ins) => ins.max_ins_size(), - Self::MulLong(ins) => ins.max_ins_size(), - Self::DivLong(ins) => ins.max_ins_size(), - Self::RemLong(ins) => ins.max_ins_size(), - Self::AndLong(ins) => ins.max_ins_size(), - Self::OrLong(ins) => ins.max_ins_size(), - Self::XorLong(ins) => ins.max_ins_size(), - Self::ShlLong(ins) => ins.max_ins_size(), - Self::ShrLong(ins) => ins.max_ins_size(), - Self::UshrLong(ins) => ins.max_ins_size(), - Self::AddFloat(ins) => ins.max_ins_size(), - Self::SubFloat(ins) => ins.max_ins_size(), - Self::MulFloat(ins) => ins.max_ins_size(), - Self::DivFloat(ins) => ins.max_ins_size(), - Self::RemFloat(ins) => ins.max_ins_size(), - Self::AddDouble(ins) => ins.max_ins_size(), - Self::SubDouble(ins) => ins.max_ins_size(), - Self::MulDouble(ins) => ins.max_ins_size(), - Self::DivDouble(ins) => ins.max_ins_size(), - Self::RemDouble(ins) => ins.max_ins_size(), - Self::AddInt2Addr(ins) => ins.max_ins_size(), - Self::SubInt2Addr(ins) => ins.max_ins_size(), - Self::MulInt2Addr(ins) => ins.max_ins_size(), - Self::DivInt2Addr(ins) => ins.max_ins_size(), - Self::RemInt2Addr(ins) => ins.max_ins_size(), - Self::AndInt2Addr(ins) => ins.max_ins_size(), - Self::OrInt2Addr(ins) => ins.max_ins_size(), - Self::XorInt2Addr(ins) => ins.max_ins_size(), - Self::ShlInt2Addr(ins) => ins.max_ins_size(), - Self::ShrInt2Addr(ins) => ins.max_ins_size(), - Self::UshrInt2Addr(ins) => ins.max_ins_size(), - Self::AddLong2Addr(ins) => ins.max_ins_size(), - Self::SubLong2Addr(ins) => ins.max_ins_size(), - Self::MulLong2Addr(ins) => ins.max_ins_size(), - Self::DivLong2Addr(ins) => ins.max_ins_size(), - Self::RemLong2Addr(ins) => ins.max_ins_size(), - Self::AndLong2Addr(ins) => ins.max_ins_size(), - Self::OrLong2Addr(ins) => ins.max_ins_size(), - Self::XorLong2Addr(ins) => ins.max_ins_size(), - Self::ShlLong2Addr(ins) => ins.max_ins_size(), - Self::ShrLong2Addr(ins) => ins.max_ins_size(), - Self::UshrLong2Addr(ins) => ins.max_ins_size(), - Self::AddFloat2Addr(ins) => ins.max_ins_size(), - Self::SubFloat2Addr(ins) => ins.max_ins_size(), - Self::MulFloat2Addr(ins) => ins.max_ins_size(), - Self::DivFloat2Addr(ins) => ins.max_ins_size(), - Self::RemFloat2Addr(ins) => ins.max_ins_size(), - Self::AddDouble2Addr(ins) => ins.max_ins_size(), - Self::SubDouble2Addr(ins) => ins.max_ins_size(), - Self::MulDouble2Addr(ins) => ins.max_ins_size(), - Self::DivDouble2Addr(ins) => ins.max_ins_size(), - Self::RemDouble2Addr(ins) => ins.max_ins_size(), - Self::AddIntLit(ins) => ins.max_ins_size(), - Self::RsubIntLit(ins) => ins.max_ins_size(), - Self::MulIntLit(ins) => ins.max_ins_size(), - Self::DivIntLit(ins) => ins.max_ins_size(), - Self::RemIntLit(ins) => ins.max_ins_size(), - Self::AndIntLit(ins) => ins.max_ins_size(), - Self::OrIntLit(ins) => ins.max_ins_size(), - Self::XorIntLit(ins) => ins.max_ins_size(), - Self::ShlIntLit(ins) => ins.max_ins_size(), - Self::ShrIntLit(ins) => ins.max_ins_size(), - Self::UshrIntLit(ins) => ins.max_ins_size(), - Self::InvokePolymorphic(ins) => ins.max_ins_size(), - Self::InvokeCustom(ins) => ins.max_ins_size(), - Self::ConstMethodHandle(ins) => ins.max_ins_size(), - Self::ConstMethodType(ins) => ins.max_ins_size(), - Self::Try(ins) => ins.max_ins_size(), - Self::Label(ins) => ins.max_ins_size(), + Self::ConstString { .. } => 6, + Self::Goto { .. } => 6, + _ => self.ins_size().unwrap(), } } @@ -2264,207 +3446,439 @@ impl Instruction { /// count addresses by unit of `u16`. pub fn ins_size(&self) -> Result { match self { - Self::Nop {} => Ok(self.get_raw_ins().unwrap().size()), - Self::Move(ins) => Ok(ins.ins_size()), - Self::MoveWide(ins) => Ok(ins.ins_size()), - Self::MoveObject(ins) => Ok(ins.ins_size()), - Self::MoveResult(ins) => Ok(ins.ins_size()), - Self::MoveResultWide(ins) => Ok(ins.ins_size()), - Self::MoveException(ins) => Ok(ins.ins_size()), - Self::MoveResultObject(ins) => Ok(ins.ins_size()), - Self::ReturnVoid(ins) => Ok(ins.ins_size()), - Self::Return(ins) => Ok(ins.ins_size()), - Self::ReturnWide(ins) => Ok(ins.ins_size()), - Self::ReturnObject(ins) => Ok(ins.ins_size()), - Self::Const(ins) => Ok(ins.ins_size()), - Self::ConstWide(ins) => Ok(ins.ins_size()), - Self::ConstString(_) => Err(anyhow!( + Self::ConstString { .. } => Err(anyhow!( "Cannot get the size of a const-string size without knowing the string idx" )), - Self::ConstClass(ins) => Ok(ins.ins_size()), - Self::MonitorEnter(ins) => Ok(ins.ins_size()), - Self::MonitorExit(ins) => Ok(ins.ins_size()), - Self::CheckCast(ins) => Ok(ins.ins_size()), - Self::InstanceOf(ins) => Ok(ins.ins_size()), - Self::ArrayLength(ins) => Ok(ins.ins_size()), - Self::NewInstance(ins) => Ok(ins.ins_size()), - Self::NewArray(ins) => Ok(ins.ins_size()), - Self::FilledNewArray(ins) => Ok(ins.ins_size()), - Self::FillArrayData(ins) => Ok(ins.ins_size()), - Self::Throw(ins) => Ok(ins.ins_size()), - Self::Goto(_) => Err(anyhow!( + Self::Goto { .. } => Err(anyhow!( "Cannot get the size of a goto without knowing the branch offset" )), - Self::Switch(ins) => Ok(ins.ins_size()), - Self::CmpLFloat(ins) => Ok(ins.ins_size()), - Self::CmpGFloat(ins) => Ok(ins.ins_size()), - Self::CmpLDouble(ins) => Ok(ins.ins_size()), - Self::CmpGDouble(ins) => Ok(ins.ins_size()), - Self::CmpLong(ins) => Ok(ins.ins_size()), - Self::IfEq(ins) => Ok(ins.ins_size()), - Self::IfNe(ins) => Ok(ins.ins_size()), - Self::IfLt(ins) => Ok(ins.ins_size()), - Self::IfGe(ins) => Ok(ins.ins_size()), - Self::IfGt(ins) => Ok(ins.ins_size()), - Self::IfLe(ins) => Ok(ins.ins_size()), - Self::IfEqZ(ins) => Ok(ins.ins_size()), - Self::IfNeZ(ins) => Ok(ins.ins_size()), - Self::IfLtZ(ins) => Ok(ins.ins_size()), - Self::IfGeZ(ins) => Ok(ins.ins_size()), - Self::IfGtZ(ins) => Ok(ins.ins_size()), - Self::IfLeZ(ins) => Ok(ins.ins_size()), - Self::AGet(ins) => Ok(ins.ins_size()), - Self::AGetWide(ins) => Ok(ins.ins_size()), - Self::AGetObject(ins) => Ok(ins.ins_size()), - Self::AGetBoolean(ins) => Ok(ins.ins_size()), - Self::AGetByte(ins) => Ok(ins.ins_size()), - Self::AGetChar(ins) => Ok(ins.ins_size()), - Self::AGetShort(ins) => Ok(ins.ins_size()), - Self::APut(ins) => Ok(ins.ins_size()), - Self::APutWide(ins) => Ok(ins.ins_size()), - Self::APutObject(ins) => Ok(ins.ins_size()), - Self::APutBoolean(ins) => Ok(ins.ins_size()), - Self::APutByte(ins) => Ok(ins.ins_size()), - Self::APutChar(ins) => Ok(ins.ins_size()), - Self::APutShort(ins) => Ok(ins.ins_size()), - Self::IGet(ins) => Ok(ins.ins_size()), - Self::IGetWide(ins) => Ok(ins.ins_size()), - Self::IGetObject(ins) => Ok(ins.ins_size()), - Self::IGetBoolean(ins) => Ok(ins.ins_size()), - Self::IGetByte(ins) => Ok(ins.ins_size()), - Self::IGetChar(ins) => Ok(ins.ins_size()), - Self::IGetShort(ins) => Ok(ins.ins_size()), - Self::IPut(ins) => Ok(ins.ins_size()), - Self::IPutWide(ins) => Ok(ins.ins_size()), - Self::IPutObject(ins) => Ok(ins.ins_size()), - Self::IPutBoolean(ins) => Ok(ins.ins_size()), - Self::IPutByte(ins) => Ok(ins.ins_size()), - Self::IPutChar(ins) => Ok(ins.ins_size()), - Self::IPutShort(ins) => Ok(ins.ins_size()), - Self::SGet(ins) => Ok(ins.ins_size()), - Self::SGetWide(ins) => Ok(ins.ins_size()), - Self::SGetObject(ins) => Ok(ins.ins_size()), - Self::SGetBoolean(ins) => Ok(ins.ins_size()), - Self::SGetByte(ins) => Ok(ins.ins_size()), - Self::SGetChar(ins) => Ok(ins.ins_size()), - Self::SGetShort(ins) => Ok(ins.ins_size()), - Self::SPut(ins) => Ok(ins.ins_size()), - Self::SPutWide(ins) => Ok(ins.ins_size()), - Self::SPutObject(ins) => Ok(ins.ins_size()), - Self::SPutBoolean(ins) => Ok(ins.ins_size()), - Self::SPutByte(ins) => Ok(ins.ins_size()), - Self::SPutChar(ins) => Ok(ins.ins_size()), - Self::SPutShort(ins) => Ok(ins.ins_size()), - Self::InvokeVirtual(ins) => Ok(ins.ins_size()), - Self::InvokeSuper(ins) => Ok(ins.ins_size()), - Self::InvokeDirect(ins) => Ok(ins.ins_size()), - Self::InvokeStatic(ins) => Ok(ins.ins_size()), - Self::InvokeInterface(ins) => Ok(ins.ins_size()), - Self::NegInt(ins) => Ok(ins.ins_size()), - Self::NotInt(ins) => Ok(ins.ins_size()), - Self::NegLong(ins) => Ok(ins.ins_size()), - Self::NotLong(ins) => Ok(ins.ins_size()), - Self::NegFloat(ins) => Ok(ins.ins_size()), - Self::NegDouble(ins) => Ok(ins.ins_size()), - Self::IntToLong(ins) => Ok(ins.ins_size()), - Self::IntToFloat(ins) => Ok(ins.ins_size()), - Self::IntToDouble(ins) => Ok(ins.ins_size()), - Self::LongToInt(ins) => Ok(ins.ins_size()), - Self::LongToFloat(ins) => Ok(ins.ins_size()), - Self::LongToDouble(ins) => Ok(ins.ins_size()), - Self::FloatToInt(ins) => Ok(ins.ins_size()), - Self::FloatToLong(ins) => Ok(ins.ins_size()), - Self::FloatToDouble(ins) => Ok(ins.ins_size()), - Self::DoubleToInt(ins) => Ok(ins.ins_size()), - Self::DoubleToLong(ins) => Ok(ins.ins_size()), - Self::DoubleToFloat(ins) => Ok(ins.ins_size()), - Self::IntToByte(ins) => Ok(ins.ins_size()), - Self::IntToChar(ins) => Ok(ins.ins_size()), - Self::IntToShort(ins) => Ok(ins.ins_size()), - Self::AddInt(ins) => Ok(ins.ins_size()), - Self::SubInt(ins) => Ok(ins.ins_size()), - Self::MulInt(ins) => Ok(ins.ins_size()), - Self::DivInt(ins) => Ok(ins.ins_size()), - Self::RemInt(ins) => Ok(ins.ins_size()), - Self::AndInt(ins) => Ok(ins.ins_size()), - Self::OrInt(ins) => Ok(ins.ins_size()), - Self::XorInt(ins) => Ok(ins.ins_size()), - Self::ShlInt(ins) => Ok(ins.ins_size()), - Self::ShrInt(ins) => Ok(ins.ins_size()), - Self::UshrInt(ins) => Ok(ins.ins_size()), - Self::AddLong(ins) => Ok(ins.ins_size()), - Self::SubLong(ins) => Ok(ins.ins_size()), - Self::MulLong(ins) => Ok(ins.ins_size()), - Self::DivLong(ins) => Ok(ins.ins_size()), - Self::RemLong(ins) => Ok(ins.ins_size()), - Self::AndLong(ins) => Ok(ins.ins_size()), - Self::OrLong(ins) => Ok(ins.ins_size()), - Self::XorLong(ins) => Ok(ins.ins_size()), - Self::ShlLong(ins) => Ok(ins.ins_size()), - Self::ShrLong(ins) => Ok(ins.ins_size()), - Self::UshrLong(ins) => Ok(ins.ins_size()), - Self::AddFloat(ins) => Ok(ins.ins_size()), - Self::SubFloat(ins) => Ok(ins.ins_size()), - Self::MulFloat(ins) => Ok(ins.ins_size()), - Self::DivFloat(ins) => Ok(ins.ins_size()), - Self::RemFloat(ins) => Ok(ins.ins_size()), - Self::AddDouble(ins) => Ok(ins.ins_size()), - Self::SubDouble(ins) => Ok(ins.ins_size()), - Self::MulDouble(ins) => Ok(ins.ins_size()), - Self::DivDouble(ins) => Ok(ins.ins_size()), - Self::RemDouble(ins) => Ok(ins.ins_size()), - Self::AddInt2Addr(ins) => Ok(ins.ins_size()), - Self::SubInt2Addr(ins) => Ok(ins.ins_size()), - Self::MulInt2Addr(ins) => Ok(ins.ins_size()), - Self::DivInt2Addr(ins) => Ok(ins.ins_size()), - Self::RemInt2Addr(ins) => Ok(ins.ins_size()), - Self::AndInt2Addr(ins) => Ok(ins.ins_size()), - Self::OrInt2Addr(ins) => Ok(ins.ins_size()), - Self::XorInt2Addr(ins) => Ok(ins.ins_size()), - Self::ShlInt2Addr(ins) => Ok(ins.ins_size()), - Self::ShrInt2Addr(ins) => Ok(ins.ins_size()), - Self::UshrInt2Addr(ins) => Ok(ins.ins_size()), - Self::AddLong2Addr(ins) => Ok(ins.ins_size()), - Self::SubLong2Addr(ins) => Ok(ins.ins_size()), - Self::MulLong2Addr(ins) => Ok(ins.ins_size()), - Self::DivLong2Addr(ins) => Ok(ins.ins_size()), - Self::RemLong2Addr(ins) => Ok(ins.ins_size()), - Self::AndLong2Addr(ins) => Ok(ins.ins_size()), - Self::OrLong2Addr(ins) => Ok(ins.ins_size()), - Self::XorLong2Addr(ins) => Ok(ins.ins_size()), - Self::ShlLong2Addr(ins) => Ok(ins.ins_size()), - Self::ShrLong2Addr(ins) => Ok(ins.ins_size()), - Self::UshrLong2Addr(ins) => Ok(ins.ins_size()), - Self::AddFloat2Addr(ins) => Ok(ins.ins_size()), - Self::SubFloat2Addr(ins) => Ok(ins.ins_size()), - Self::MulFloat2Addr(ins) => Ok(ins.ins_size()), - Self::DivFloat2Addr(ins) => Ok(ins.ins_size()), - Self::RemFloat2Addr(ins) => Ok(ins.ins_size()), - Self::AddDouble2Addr(ins) => Ok(ins.ins_size()), - Self::SubDouble2Addr(ins) => Ok(ins.ins_size()), - Self::MulDouble2Addr(ins) => Ok(ins.ins_size()), - Self::DivDouble2Addr(ins) => Ok(ins.ins_size()), - Self::RemDouble2Addr(ins) => Ok(ins.ins_size()), - Self::AddIntLit(ins) => Ok(ins.ins_size()), - Self::RsubIntLit(ins) => Ok(ins.ins_size()), - Self::MulIntLit(ins) => Ok(ins.ins_size()), - Self::DivIntLit(ins) => Ok(ins.ins_size()), - Self::RemIntLit(ins) => Ok(ins.ins_size()), - Self::AndIntLit(ins) => Ok(ins.ins_size()), - Self::OrIntLit(ins) => Ok(ins.ins_size()), - Self::XorIntLit(ins) => Ok(ins.ins_size()), - Self::ShlIntLit(ins) => Ok(ins.ins_size()), - Self::ShrIntLit(ins) => Ok(ins.ins_size()), - Self::UshrIntLit(ins) => Ok(ins.ins_size()), - Self::InvokePolymorphic(ins) => Ok(ins.ins_size()), - Self::InvokeCustom(ins) => Ok(ins.ins_size()), - Self::ConstMethodHandle(ins) => Ok(ins.ins_size()), - Self::ConstMethodType(ins) => Ok(ins.ins_size()), - Self::Try(ins) => Ok(ins.ins_size()), - Self::Label(ins) => Ok(ins.ins_size()), + Self::ConstClass { .. } => Ok(4), + Self::CheckCast { .. } => Ok(4), + Self::InstanceOf { .. } => Ok(4), + Self::NewInstance { .. } => Ok(4), + Self::NewArray { .. } => Ok(4), + Self::FilledNewArray { .. } => Ok(6), + Self::FillArrayData { .. } => Ok(6), + Self::Switch { .. } => Ok(6), + Self::IfEq { .. } => Ok(4), + Self::IfNe { .. } => Ok(4), + Self::IfLt { .. } => Ok(4), + Self::IfGe { .. } => Ok(4), + Self::IfGt { .. } => Ok(4), + Self::IfLe { .. } => Ok(4), + Self::IfEqZ { .. } => Ok(4), + Self::IfNeZ { .. } => Ok(4), + Self::IfLtZ { .. } => Ok(4), + Self::IfGeZ { .. } => Ok(4), + Self::IfGtZ { .. } => Ok(4), + Self::IfLeZ { .. } => Ok(4), + Self::IGet { .. } => Ok(4), + Self::IGetWide { .. } => Ok(4), + Self::IGetObject { .. } => Ok(4), + Self::IGetBoolean { .. } => Ok(4), + Self::IGetByte { .. } => Ok(4), + Self::IGetChar { .. } => Ok(4), + Self::IGetShort { .. } => Ok(4), + Self::IPut { .. } => Ok(4), + Self::IPutWide { .. } => Ok(4), + Self::IPutObject { .. } => Ok(4), + Self::IPutBoolean { .. } => Ok(4), + Self::IPutByte { .. } => Ok(4), + Self::IPutChar { .. } => Ok(4), + Self::IPutShort { .. } => Ok(4), + Self::SGet { .. } => Ok(4), + Self::SGetWide { .. } => Ok(4), + Self::SGetObject { .. } => Ok(4), + Self::SGetBoolean { .. } => Ok(4), + Self::SGetByte { .. } => Ok(4), + Self::SGetChar { .. } => Ok(4), + Self::SGetShort { .. } => Ok(4), + Self::SPut { .. } => Ok(4), + Self::SPutWide { .. } => Ok(4), + Self::SPutObject { .. } => Ok(4), + Self::SPutBoolean { .. } => Ok(4), + Self::SPutByte { .. } => Ok(4), + Self::SPutChar { .. } => Ok(4), + Self::SPutShort { .. } => Ok(4), + Self::InvokeVirtual { .. } => Ok(6), + Self::InvokeSuper { .. } => Ok(6), + Self::InvokeDirect { .. } => Ok(6), + Self::InvokeStatic { .. } => Ok(6), + Self::InvokeInterface { .. } => Ok(6), + Self::InvokePolymorphic { .. } => Ok(8), + Self::InvokeCustom { .. } => Ok(6), + Self::ConstMethodHandle { .. } => Ok(4), + Self::ConstMethodType { .. } => Ok(4), + Self::Try { .. } => Ok(0), + Self::Label { .. } => Ok(0), + _ => self.get_raw_ins().map(|ins| ins.size()), } } + pub fn sanity_check(&self) -> Result<()> { + match self { + Self::InstanceOf { dest, obj, .. } => sanity_check_4_bit_reg!("instance-of", dest, obj), + Self::ArrayLength { dest, arr } => sanity_check_4_bit_reg!("array-length", dest, arr), + Self::NewArray { reg, size_reg, .. } => { + sanity_check_4_bit_reg!("new-array", reg, size_reg) + } + Self::FilledNewArray { reg_values, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = reg_values.len(); + for r in reg_values.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "filled-new-array instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::IfEq { a, b, .. } => sanity_check_4_bit_reg!("if-eq", a, b), + Self::IfNe { a, b, .. } => sanity_check_4_bit_reg!("if-neq", a, b), + Self::IfLt { a, b, .. } => sanity_check_4_bit_reg!("if-lt", a, b), + Self::IfGe { a, b, .. } => sanity_check_4_bit_reg!("if-ge", a, b), + Self::IfGt { a, b, .. } => sanity_check_4_bit_reg!("if-gt", a, b), + Self::IfLe { a, b, .. } => sanity_check_4_bit_reg!("if-le", a, b), + Self::IGet { to, obj, .. } => sanity_check_4_bit_reg!("iget", to, obj), + Self::IGetWide { to, obj, .. } => sanity_check_4_bit_reg!("iget-wide", to, obj), + Self::IGetObject { to, obj, .. } => sanity_check_4_bit_reg!("iget-object", to, obj), + Self::IGetBoolean { to, obj, .. } => sanity_check_4_bit_reg!("iget-boolean", to, obj), + Self::IGetByte { to, obj, .. } => sanity_check_4_bit_reg!("iget-byte", to, obj), + Self::IGetChar { to, obj, .. } => sanity_check_4_bit_reg!("iget-char", to, obj), + Self::IGetShort { to, obj, .. } => sanity_check_4_bit_reg!("iget-short", to, obj), + Self::IPut { from, obj, .. } => sanity_check_4_bit_reg!("iput", from, obj), + Self::IPutWide { from, obj, .. } => sanity_check_4_bit_reg!("iput-wide", from, obj), + Self::IPutObject { from, obj, .. } => sanity_check_4_bit_reg!("iput-object", from, obj), + Self::IPutBoolean { from, obj, .. } => { + sanity_check_4_bit_reg!("iput-boolean", from, obj) + } + Self::IPutByte { from, obj, .. } => sanity_check_4_bit_reg!("iput-byte", from, obj), + Self::IPutChar { from, obj, .. } => sanity_check_4_bit_reg!("iput-char", from, obj), + Self::IPutShort { from, obj, .. } => sanity_check_4_bit_reg!("iput-short", from, obj), + Self::InvokeVirtual { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-virtual instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::InvokeSuper { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-super instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::InvokeDirect { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-direct instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::InvokeStatic { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-static instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::InvokeInterface { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-interface instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::NegInt { dest, val } => sanity_check_4_bit_reg!("neg-int", dest, val), + Self::NotInt { dest, val } => sanity_check_4_bit_reg!("not-int", dest, val), + Self::NegLong { dest, val } => sanity_check_4_bit_reg!("neg-long", dest, val), + Self::NotLong { dest, val } => sanity_check_4_bit_reg!("not-long", dest, val), + Self::NegFloat { dest, val } => sanity_check_4_bit_reg!("neg-float", dest, val), + Self::NegDouble { dest, val } => sanity_check_4_bit_reg!("neg-double", dest, val), + Self::IntToLong { dest, val } => sanity_check_4_bit_reg!("int-to-long", dest, val), + Self::IntToFloat { dest, val } => sanity_check_4_bit_reg!("int-to-float", dest, val), + Self::IntToDouble { dest, val } => sanity_check_4_bit_reg!("int-to-double", dest, val), + Self::LongToInt { dest, val } => sanity_check_4_bit_reg!("long-to-int", dest, val), + Self::LongToFloat { dest, val } => sanity_check_4_bit_reg!("long-to-float", dest, val), + Self::LongToDouble { dest, val } => { + sanity_check_4_bit_reg!("long-to-double", dest, val) + } + Self::FloatToInt { dest, val } => sanity_check_4_bit_reg!("float-to-int", dest, val), + Self::FloatToLong { dest, val } => sanity_check_4_bit_reg!("float-to-long", dest, val), + Self::FloatToDouble { dest, val } => { + sanity_check_4_bit_reg!("float-to-double", dest, val) + } + Self::LongToInt { dest, val } => sanity_check_4_bit_reg!("long-to-int", dest, val), + Self::DoubleToInt { dest, val } => sanity_check_4_bit_reg!("double-to-int", dest, val), + Self::DoubleToLong { dest, val } => { + sanity_check_4_bit_reg!("double-to-long", dest, val) + } + Self::DoubleToFloat { dest, val } => { + sanity_check_4_bit_reg!("double-to-float", dest, val) + } + Self::IntToByte { dest, val } => sanity_check_4_bit_reg!("int-to-byte", dest, val), + Self::IntToChar { dest, val } => sanity_check_4_bit_reg!("int-to-char", dest, val), + Self::IntToShort { dest, val } => sanity_check_4_bit_reg!("int-to-short", dest, val), + Self::AddInt2Addr { dest, b } => sanity_check_4_bit_reg!("add-int/2addr", dest, b), + Self::SubInt2Addr { dest, b } => sanity_check_4_bit_reg!("sub-int/2addr", dest, b), + Self::MulInt2Addr { dest, b } => sanity_check_4_bit_reg!("mul-int/2addr", dest, b), + Self::DivInt2Addr { dest, b } => sanity_check_4_bit_reg!("div-int/2addr", dest, b), + Self::RemInt2Addr { dest, b } => sanity_check_4_bit_reg!("rem-int/2addr", dest, b), + Self::AndInt2Addr { dest, b } => sanity_check_4_bit_reg!("and-int/2addr", dest, b), + Self::OrInt2Addr { dest, b } => sanity_check_4_bit_reg!("or-int/2addr", dest, b), + Self::XorInt2Addr { dest, b } => sanity_check_4_bit_reg!("xor-int/2addr", dest, b), + Self::ShlInt2Addr { dest, b } => sanity_check_4_bit_reg!("shl-int/2addr", dest, b), + Self::ShrInt2Addr { dest, b } => sanity_check_4_bit_reg!("shr-int/2addr", dest, b), + Self::UshrInt2Addr { dest, b } => sanity_check_4_bit_reg!("ushr-int/2addr", dest, b), + Self::AddLong2Addr { dest, b } => sanity_check_4_bit_reg!("add-long/2addr", dest, b), + Self::SubLong2Addr { dest, b } => sanity_check_4_bit_reg!("sub-long/2addr", dest, b), + Self::MulLong2Addr { dest, b } => sanity_check_4_bit_reg!("mul-long/2addr", dest, b), + Self::DivLong2Addr { dest, b } => sanity_check_4_bit_reg!("div-long/2addr", dest, b), + Self::RemLong2Addr { dest, b } => sanity_check_4_bit_reg!("rem-long/2addr", dest, b), + Self::AndLong2Addr { dest, b } => sanity_check_4_bit_reg!("and-long/2addr", dest, b), + Self::OrLong2Addr { dest, b } => sanity_check_4_bit_reg!("or-long/2addr", dest, b), + Self::XorLong2Addr { dest, b } => sanity_check_4_bit_reg!("xor-long/2addr", dest, b), + Self::ShlLong2Addr { dest, b } => sanity_check_4_bit_reg!("shl-long/2addr", dest, b), + Self::ShrLong2Addr { dest, b } => sanity_check_4_bit_reg!("shr-long/2addr", dest, b), + Self::UshrLong2Addr { dest, b } => sanity_check_4_bit_reg!("ushr-long/2addr", dest, b), + Self::AddFloat2Addr { dest, b } => sanity_check_4_bit_reg!("add-float/2addr", dest, b), + Self::SubFloat2Addr { dest, b } => sanity_check_4_bit_reg!("sub-float/2addr", dest, b), + Self::MulFloat2Addr { dest, b } => sanity_check_4_bit_reg!("mul-float/2addr", dest, b), + Self::DivFloat2Addr { dest, b } => sanity_check_4_bit_reg!("div-float/2addr", dest, b), + Self::RemFloat2Addr { dest, b } => sanity_check_4_bit_reg!("rem-float/2addr", dest, b), + Self::AddDouble2Addr { dest, b } => { + sanity_check_4_bit_reg!("add-double/2addr", dest, b) + } + Self::SubDouble2Addr { dest, b } => { + sanity_check_4_bit_reg!("sub-double/2addr", dest, b) + } + Self::MulDouble2Addr { dest, b } => { + sanity_check_4_bit_reg!("mul-double/2addr", dest, b) + } + Self::DivDouble2Addr { dest, b } => { + sanity_check_4_bit_reg!("div-double/2addr", dest, b) + } + Self::RemDouble2Addr { dest, b } => { + sanity_check_4_bit_reg!("rem-double/2addr", dest, b) + } + Self::AddIntLit { dest, b, lit } => sanity_check_22b_or_22s!("add-int", dest, b, lit), + Self::RsubIntLit { dest, b, lit } => sanity_check_22b_or_22s!("rsub-int", dest, b, lit), + Self::MulIntLit { dest, b, lit } => sanity_check_22b_or_22s!("mul-int", dest, b, lit), + Self::DivIntLit { dest, b, lit } => sanity_check_22b_or_22s!("div-int", dest, b, lit), + Self::RemIntLit { dest, b, lit } => sanity_check_22b_or_22s!("rem-int", dest, b, lit), + Self::AndIntLit { dest, b, lit } => sanity_check_22b_or_22s!("and-int", dest, b, lit), + Self::OrIntLit { dest, b, lit } => sanity_check_22b_or_22s!("or-int", dest, b, lit), + Self::XorIntLit { dest, b, lit } => sanity_check_22b_or_22s!("xor-int", dest, b, lit), + Self::InvokePolymorphic { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-polymorphic instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + Self::InvokeCustom { args, .. } => { + let mut last = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if (four_bites && len <= 5) || (consec && len <= 255) { + Ok(()) + } else { + Err(anyhow!( + "invoke-custom instruction must either use 5 or \ + less register indexed on 4 bites or less than 255 \ + consecutive registers" + )) + } + } + _ => Ok(()), + } + } + /// Return all strings referenced in the instruction. + pub fn get_all_strings(&self) -> HashSet { + let mut visitor = StringCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } + + /// Return all types referenced in the instruction. + pub fn get_all_types(&self) -> HashSet { + let mut visitor = TypeCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } + + /// Return all prototypes referenced in the instruction. + pub fn get_all_protos(&self) -> HashSet { + let mut visitor = MethodTypeCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } + + /// Return all field ids referenced in the instruction. + pub fn get_all_field_ids(&self) -> HashSet { + let mut visitor = FieldIdCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } + + /// Return all method ids referenced in the instruction. + pub fn get_all_method_ids(&self) -> HashSet { + let mut visitor = MethodIdCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } + + /// Return all method handles referenced in the instruction. + pub fn get_all_method_handles(&self) -> HashSet { + let mut visitor = MethodHandleCollector::default(); + visitor.visit_instruction(self).unwrap(); + visitor.result() + } +} + +impl Instruction { /// Return the raw instruction ([`InsFormat`]) when it does not need additionnal data. /// /// # Warning @@ -2539,985 +3953,2063 @@ impl Instruction { /// - `Label` pub fn get_raw_ins(&self) -> Result { match self { - Self::Nop {} => Ok(InsFormat::Format10X { op: 0x00 }), - Self::Move(ins) => Ok(ins.get_raw_ins()), - Self::MoveWide(ins) => Ok(ins.get_raw_ins()), - Self::MoveObject(ins) => Ok(ins.get_raw_ins()), - Self::MoveResult(ins) => Ok(ins.get_raw_ins()), - Self::MoveResultWide(ins) => Ok(ins.get_raw_ins()), - Self::MoveException(ins) => Ok(ins.get_raw_ins()), - Self::MoveResultObject(ins) => Ok(ins.get_raw_ins()), - Self::ReturnVoid(ins) => Ok(ins.get_raw_ins()), - Self::Return(ins) => Ok(ins.get_raw_ins()), - Self::ReturnWide(ins) => Ok(ins.get_raw_ins()), - Self::ReturnObject(ins) => Ok(ins.get_raw_ins()), - Self::Const(ins) => Ok(ins.get_raw_ins()), - Self::ConstWide(ins) => Ok(ins.get_raw_ins()), - Self::ConstString(_) => Err(anyhow!( + Self::ConstString { .. } => Err(anyhow!( "Cannot get the raw instruction of a const-string without knowing the string idx" )), - Self::ConstClass(_) => Err(anyhow!( + Self::ConstClass { .. } => Err(anyhow!( "Cannot get the raw instruction of a const-class without knowing the class idx" )), - Self::MonitorEnter(ins) => Ok(ins.get_raw_ins()), - Self::MonitorExit(ins) => Ok(ins.get_raw_ins()), - Self::CheckCast(_) => Err(anyhow!( + Self::CheckCast { .. } => Err(anyhow!( "Cannot get the raw instruction of a check-cast without knowing the type idx" )), - Self::InstanceOf(_) => Err(anyhow!( + Self::InstanceOf { .. } => Err(anyhow!( "Cannot get the raw instruction of a instance-of without knowing the type idx" )), - Self::ArrayLength(ins) => Ok(ins.get_raw_ins()), - Self::NewInstance(_) => Err(anyhow!( + Self::NewInstance { .. } => Err(anyhow!( "Cannot get the raw instruction of a new-instance without knowing the class idx" )), - Self::NewArray(_) => Err(anyhow!( + Self::NewArray { .. } => Err(anyhow!( "Cannot get the raw instruction of a new-array without knowing the type idx" )), - Self::FilledNewArray(_) => Err(anyhow!( + Self::FilledNewArray { .. } => Err(anyhow!( "Cannot get the raw instruction of a filled-new-array without knowing the type idx" )), - Self::FillArrayData(_) => Err(anyhow!( + Self::FillArrayData { .. } => Err(anyhow!( "Cannot get the raw instruction of a fill-array-data without knowing the offset \ to the -fill-array-data-payload" )), - Self::Throw(ins) => Ok(ins.get_raw_ins()), - Self::Goto(_) => Err(anyhow!( + Self::Goto { .. } => Err(anyhow!( "Cannot get the size of a goto without knowing the branch offset" )), - Self::Switch(_) => Err(anyhow!( + Self::Switch { .. } => Err(anyhow!( "Cannot get the raw instruction of a switch without knowing the offset \ to the packed/sparse-switch-payload" )), - Self::CmpLFloat(ins) => Ok(ins.get_raw_ins()), - Self::CmpGFloat(ins) => Ok(ins.get_raw_ins()), - Self::CmpLDouble(ins) => Ok(ins.get_raw_ins()), - Self::CmpGDouble(ins) => Ok(ins.get_raw_ins()), - Self::CmpLong(ins) => Ok(ins.get_raw_ins()), - Self::IfEq(_) => Err(anyhow!( + Self::IfEq { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-eq without knowing \ the offset to the branch" )), - Self::IfNe(_) => Err(anyhow!( + Self::IfNe { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-ne without knowing \ the offset to the branch" )), - Self::IfLt(_) => Err(anyhow!( + Self::IfLt { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-lt without knowing \ the offset to the branch" )), - Self::IfGe(_) => Err(anyhow!( + Self::IfGe { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-ge without knowing \ the offset to the branch" )), - Self::IfGt(_) => Err(anyhow!( + Self::IfGt { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-gt without knowing \ the offset to the branch" )), - Self::IfLe(_) => Err(anyhow!( + Self::IfLe { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-le without knowing \ the offset to the branch" )), - Self::IfEqZ(_) => Err(anyhow!( + Self::IfEqZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-eqz without knowing \ the offset to the branch" )), - Self::IfNeZ(_) => Err(anyhow!( + Self::IfNeZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-nez without knowing \ the offset to the branch" )), - Self::IfLtZ(_) => Err(anyhow!( + Self::IfLtZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-ltz without knowing \ the offset to the branch" )), - Self::IfGeZ(_) => Err(anyhow!( + Self::IfGeZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-gez without knowing \ the offset to the branch" )), - Self::IfGtZ(_) => Err(anyhow!( + Self::IfGtZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-gtz without knowing \ the offset to the branch" )), - Self::IfLeZ(_) => Err(anyhow!( + Self::IfLeZ { .. } => Err(anyhow!( "Cannot get the raw instruction of a if-lez without knowing \ the offset to the branch" )), - Self::AGet(ins) => Ok(ins.get_raw_ins()), - Self::AGetWide(ins) => Ok(ins.get_raw_ins()), - Self::AGetObject(ins) => Ok(ins.get_raw_ins()), - Self::AGetBoolean(ins) => Ok(ins.get_raw_ins()), - Self::AGetByte(ins) => Ok(ins.get_raw_ins()), - Self::AGetChar(ins) => Ok(ins.get_raw_ins()), - Self::AGetShort(ins) => Ok(ins.get_raw_ins()), - Self::APut(ins) => Ok(ins.get_raw_ins()), - Self::APutWide(ins) => Ok(ins.get_raw_ins()), - Self::APutObject(ins) => Ok(ins.get_raw_ins()), - Self::APutBoolean(ins) => Ok(ins.get_raw_ins()), - Self::APutByte(ins) => Ok(ins.get_raw_ins()), - Self::APutChar(ins) => Ok(ins.get_raw_ins()), - Self::APutShort(ins) => Ok(ins.get_raw_ins()), - Self::IGet(_) => Err(anyhow!( + Self::IGet { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget without knowing the field idx" )), - Self::IGetWide(_) => Err(anyhow!( + Self::IGetWide { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-wide without knowing the field idx" )), - Self::IGetObject(_) => Err(anyhow!( + Self::IGetObject { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-object without knowing the field idx" )), - Self::IGetBoolean(_) => Err(anyhow!( + Self::IGetBoolean { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-boolean without knowing the field idx" )), - Self::IGetByte(_) => Err(anyhow!( + Self::IGetByte { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-byte without knowing the field idx" )), - Self::IGetChar(_) => Err(anyhow!( + Self::IGetChar { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-char without knowing the field idx" )), - Self::IGetShort(_) => Err(anyhow!( + Self::IGetShort { .. } => Err(anyhow!( "Cannot get the raw instruction of a iget-short without knowing the field idx" )), - Self::IPut(_) => Err(anyhow!( + Self::IPut { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput without knowing the field idx" )), - Self::IPutWide(_) => Err(anyhow!( + Self::IPutWide { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-wide without knowing the field idx" )), - Self::IPutObject(_) => Err(anyhow!( + Self::IPutObject { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-object without knowing the field idx" )), - Self::IPutBoolean(_) => Err(anyhow!( + Self::IPutBoolean { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-boolean without knowing the field idx" )), - Self::IPutByte(_) => Err(anyhow!( + Self::IPutByte { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-byte without knowing the field idx" )), - Self::IPutChar(_) => Err(anyhow!( + Self::IPutChar { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-char without knowing the field idx" )), - Self::IPutShort(_) => Err(anyhow!( + Self::IPutShort { .. } => Err(anyhow!( "Cannot get the raw instruction of a iput-short without knowing the field idx" )), - Self::SGet(_) => Err(anyhow!( + Self::SGet { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget without knowing the field idx" )), - Self::SGetWide(_) => Err(anyhow!( + Self::SGetWide { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-wide without knowing the field idx" )), - Self::SGetObject(_) => Err(anyhow!( + Self::SGetObject { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-object without knowing the field idx" )), - Self::SGetBoolean(_) => Err(anyhow!( + Self::SGetBoolean { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-boolean without knowing the field idx" )), - Self::SGetByte(_) => Err(anyhow!( + Self::SGetByte { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-byte without knowing the field idx" )), - Self::SGetChar(_) => Err(anyhow!( + Self::SGetChar { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-char without knowing the field idx" )), - Self::SGetShort(_) => Err(anyhow!( + Self::SGetShort { .. } => Err(anyhow!( "Cannot get the raw instruction of a sget-short without knowing the field idx" )), - Self::SPut(_) => Err(anyhow!( + Self::SPut { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput without knowing the field idx" )), - Self::SPutWide(_) => Err(anyhow!( + Self::SPutWide { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-wide without knowing the field idx" )), - Self::SPutObject(_) => Err(anyhow!( + Self::SPutObject { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-object without knowing the field idx" )), - Self::SPutBoolean(_) => Err(anyhow!( + Self::SPutBoolean { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-boolean without knowing the field idx" )), - Self::SPutByte(_) => Err(anyhow!( + Self::SPutByte { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-byte without knowing the field idx" )), - Self::SPutChar(_) => Err(anyhow!( + Self::SPutChar { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-char without knowing the field idx" )), - Self::SPutShort(_) => Err(anyhow!( + Self::SPutShort { .. } => Err(anyhow!( "Cannot get the raw instruction of a sput-short without knowing the field idx" )), - Self::InvokeVirtual(_) => Err(anyhow!( + Self::InvokeVirtual { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-virtual without knowing \ the method idx" )), - Self::InvokeSuper(_) => Err(anyhow!( + Self::InvokeSuper { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-super without knowing \ the method idx" )), - Self::InvokeDirect(_) => Err(anyhow!( + Self::InvokeDirect { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-direct without knowing \ the method idx" )), - Self::InvokeStatic(_) => Err(anyhow!( + Self::InvokeStatic { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-static without knowing \ the method idx" )), - Self::InvokeInterface(_) => Err(anyhow!( + Self::InvokeInterface { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-interface without knowing \ the method idx" )), - Self::NegInt(ins) => Ok(ins.get_raw_ins()), - Self::NotInt(ins) => Ok(ins.get_raw_ins()), - Self::NegLong(ins) => Ok(ins.get_raw_ins()), - Self::NotLong(ins) => Ok(ins.get_raw_ins()), - Self::NegFloat(ins) => Ok(ins.get_raw_ins()), - Self::NegDouble(ins) => Ok(ins.get_raw_ins()), - Self::IntToLong(ins) => Ok(ins.get_raw_ins()), - Self::IntToFloat(ins) => Ok(ins.get_raw_ins()), - Self::IntToDouble(ins) => Ok(ins.get_raw_ins()), - Self::LongToInt(ins) => Ok(ins.get_raw_ins()), - Self::LongToFloat(ins) => Ok(ins.get_raw_ins()), - Self::LongToDouble(ins) => Ok(ins.get_raw_ins()), - Self::FloatToInt(ins) => Ok(ins.get_raw_ins()), - Self::FloatToLong(ins) => Ok(ins.get_raw_ins()), - Self::FloatToDouble(ins) => Ok(ins.get_raw_ins()), - Self::DoubleToInt(ins) => Ok(ins.get_raw_ins()), - Self::DoubleToLong(ins) => Ok(ins.get_raw_ins()), - Self::DoubleToFloat(ins) => Ok(ins.get_raw_ins()), - Self::IntToByte(ins) => Ok(ins.get_raw_ins()), - Self::IntToChar(ins) => Ok(ins.get_raw_ins()), - Self::IntToShort(ins) => Ok(ins.get_raw_ins()), - Self::AddInt(ins) => Ok(ins.get_raw_ins()), - Self::SubInt(ins) => Ok(ins.get_raw_ins()), - Self::MulInt(ins) => Ok(ins.get_raw_ins()), - Self::DivInt(ins) => Ok(ins.get_raw_ins()), - Self::RemInt(ins) => Ok(ins.get_raw_ins()), - Self::AndInt(ins) => Ok(ins.get_raw_ins()), - Self::OrInt(ins) => Ok(ins.get_raw_ins()), - Self::XorInt(ins) => Ok(ins.get_raw_ins()), - Self::ShlInt(ins) => Ok(ins.get_raw_ins()), - Self::ShrInt(ins) => Ok(ins.get_raw_ins()), - Self::UshrInt(ins) => Ok(ins.get_raw_ins()), - Self::AddLong(ins) => Ok(ins.get_raw_ins()), - Self::SubLong(ins) => Ok(ins.get_raw_ins()), - Self::MulLong(ins) => Ok(ins.get_raw_ins()), - Self::DivLong(ins) => Ok(ins.get_raw_ins()), - Self::RemLong(ins) => Ok(ins.get_raw_ins()), - Self::AndLong(ins) => Ok(ins.get_raw_ins()), - Self::OrLong(ins) => Ok(ins.get_raw_ins()), - Self::XorLong(ins) => Ok(ins.get_raw_ins()), - Self::ShlLong(ins) => Ok(ins.get_raw_ins()), - Self::ShrLong(ins) => Ok(ins.get_raw_ins()), - Self::UshrLong(ins) => Ok(ins.get_raw_ins()), - Self::AddFloat(ins) => Ok(ins.get_raw_ins()), - Self::SubFloat(ins) => Ok(ins.get_raw_ins()), - Self::MulFloat(ins) => Ok(ins.get_raw_ins()), - Self::DivFloat(ins) => Ok(ins.get_raw_ins()), - Self::RemFloat(ins) => Ok(ins.get_raw_ins()), - Self::AddDouble(ins) => Ok(ins.get_raw_ins()), - Self::SubDouble(ins) => Ok(ins.get_raw_ins()), - Self::MulDouble(ins) => Ok(ins.get_raw_ins()), - Self::DivDouble(ins) => Ok(ins.get_raw_ins()), - Self::RemDouble(ins) => Ok(ins.get_raw_ins()), - Self::AddInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::SubInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::MulInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::DivInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::RemInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AndInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::OrInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::XorInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::ShlInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::ShrInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::UshrInt2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AddLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::SubLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::MulLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::DivLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::RemLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AndLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::OrLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::XorLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::ShlLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::ShrLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::UshrLong2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AddFloat2Addr(ins) => Ok(ins.get_raw_ins()), - Self::SubFloat2Addr(ins) => Ok(ins.get_raw_ins()), - Self::MulFloat2Addr(ins) => Ok(ins.get_raw_ins()), - Self::DivFloat2Addr(ins) => Ok(ins.get_raw_ins()), - Self::RemFloat2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AddDouble2Addr(ins) => Ok(ins.get_raw_ins()), - Self::SubDouble2Addr(ins) => Ok(ins.get_raw_ins()), - Self::MulDouble2Addr(ins) => Ok(ins.get_raw_ins()), - Self::DivDouble2Addr(ins) => Ok(ins.get_raw_ins()), - Self::RemDouble2Addr(ins) => Ok(ins.get_raw_ins()), - Self::AddIntLit(ins) => Ok(ins.get_raw_ins()), - Self::RsubIntLit(ins) => Ok(ins.get_raw_ins()), - Self::MulIntLit(ins) => Ok(ins.get_raw_ins()), - Self::DivIntLit(ins) => Ok(ins.get_raw_ins()), - Self::RemIntLit(ins) => Ok(ins.get_raw_ins()), - Self::AndIntLit(ins) => Ok(ins.get_raw_ins()), - Self::OrIntLit(ins) => Ok(ins.get_raw_ins()), - Self::XorIntLit(ins) => Ok(ins.get_raw_ins()), - Self::ShlIntLit(ins) => Ok(ins.get_raw_ins()), - Self::ShrIntLit(ins) => Ok(ins.get_raw_ins()), - Self::UshrIntLit(ins) => Ok(ins.get_raw_ins()), - Self::InvokePolymorphic(_) => Err(anyhow!( + Self::InvokePolymorphic { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-polymorphic without knowing \ the method idx and proto idx" )), - Self::InvokeCustom(_) => Err(anyhow!( + Self::InvokeCustom { .. } => Err(anyhow!( "Cannot get the raw instruction of a invoke-custom without knowing the \ call site idx" )), - Self::ConstMethodHandle(_) => Err(anyhow!( + Self::ConstMethodHandle { .. } => Err(anyhow!( "Cannot get the raw instruction of a const-method-handle \ without knowing the method handle idx" )), - Self::ConstMethodType(_) => Err(anyhow!( + Self::ConstMethodType { .. } => Err(anyhow!( "Cannot get the raw instruction of a const-method-type \ without knowing the proto idx" )), - Self::Try(_) => Err(anyhow!( + Self::Try { .. } => Err(anyhow!( "Try instruction cannot be converted to raw instruction" )), - Self::Label(_) => Err(anyhow!("Label cannot be convertedto raw instruction")), + Self::Label { .. } => Err(anyhow!("Label cannot be converted to raw instruction")), + Self::Nop {} => Ok(InsFormat::Format10X { op: 0x00 }), + Self::Move { from, to } => match (to, from) { + (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { + op: 0x01, + va: *to as u8, + vb: *from as u8, + }), + (0..=0xff, _) => Ok(InsFormat::Format22X { + op: 0x02, + va: *to as u8, + vb: *from, + }), + (_, _) => Ok(InsFormat::Format32X { + op: 0x03, + va: *to, + vb: *from, + }), + }, + Self::MoveWide { from, to } => match (to, from) { + (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { + op: 0x04, + va: *to as u8, + vb: *from as u8, + }), + (0..=0xff, _) => Ok(InsFormat::Format22X { + op: 0x05, + va: *to as u8, + vb: *from, + }), + (_, _) => Ok(InsFormat::Format32X { + op: 0x06, + va: *to, + vb: *from, + }), + }, + Self::MoveObject { from, to } => match (to, from) { + (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { + op: 0x07, + va: *to as u8, + vb: *from as u8, + }), + (0..=0xff, _) => Ok(InsFormat::Format22X { + op: 0x08, + va: *to as u8, + vb: *from, + }), + (_, _) => Ok(InsFormat::Format32X { + op: 0x09, + va: *to, + vb: *from, + }), + }, + Self::MoveResult { to } => Ok(InsFormat::Format11X { op: 0x0a, va: *to }), + Self::MoveResultWide { to } => Ok(InsFormat::Format11X { op: 0x0b, va: *to }), + Self::MoveResultObject { to } => Ok(InsFormat::Format11X { op: 0x0c, va: *to }), + Self::MoveException { to } => Ok(InsFormat::Format11X { op: 0x0d, va: *to }), + Self::ReturnVoid {} => Ok(InsFormat::Format10X { op: 0x0e }), + Self::Return { reg } => Ok(InsFormat::Format11X { op: 0x0f, va: *reg }), + Self::ReturnWide { reg } => Ok(InsFormat::Format11X { op: 0x10, va: *reg }), + Self::ReturnObject { reg } => Ok(InsFormat::Format11X { op: 0x11, va: *reg }), + Self::Const { lit, reg } => match (reg, lit) { + (0..=0b0000_1111, -8..=7) => Ok(InsFormat::Format11N { + op: 0x12, + va: *reg, + b: *lit as i8, + }), + (_, I16_MIN_AS_I32..=I16_MAX_AS_I32) => Ok(InsFormat::Format21S { + op: 0x13, + va: *reg, + b: *lit as i16, + }), + (_, lit) if lit % 0x1_0000 == 0 => Ok(InsFormat::Format21H { + op: 0x15, + va: *reg, + b: (*lit / 0x1_0000) as i16, + }), + (_, _) => Ok(InsFormat::Format31I { + op: 0x14, + va: *reg, + b: *lit, + }), + }, + Self::ConstWide { lit, reg } => match lit { + I16_MIN_AS_I64..=I16_MAX_AS_I64 => Ok(InsFormat::Format21S { + op: 0x16, + va: *reg, + b: *lit as i16, + }), + I32_MIN_AS_I64..=I32_MAX_AS_I64 => Ok(InsFormat::Format31I { + op: 0x17, + va: *reg, + b: *lit as i32, + }), + lit if lit % 0x1_0000_0000_0000 == 0 => Ok(InsFormat::Format21H { + op: 0x19, + va: *reg, + b: (*lit / 0x1_0000_0000_0000) as i16, + }), + _ => Ok(InsFormat::Format51L { + op: 0x18, + va: *reg, + b: *lit, + }), + }, + /* needs string_idx + Self::ConstString { reg, string_idx } => match string_idx { + 0..=U16_MAX_AS_USIZE => Ok(InsFormat::Format21C { + op: 0x1a, + va: *reg, + b: string_idx as u16, + }, + _ => Ok(InsFormat::Format31C { + op: 0x1b, + va: *reg, + b: string_idx as u32, + }), + }, + */ + /* needs cclass_idx + Self::ConstClass { reg, class_idx} => Ok(InsFormat::Format21C { + op: 0x1c, + va: *reg, + b: *class_idx as u16, + }), + */ + Self::MonitorEnter { reg } => Ok(InsFormat::Format11X { op: 0x1d, va: *reg }), + Self::MonitorExit { reg } => Ok(InsFormat::Format11X { op: 0x1e, va: *reg }), + /* needs type_idx + Self::CheckCast {reg, type_idx} => Ok(InsFormat::Format21C { + op: 0x1f, + va: *reg, + b: *type_idx as u16, + }), + */ + /* needs type_idx + Self::InstanceOf { dest, obj, type_idx } => Ok(InsFormat::Format22C { + op: 0x20, + va: *dest, + vb: *obj, + c: type_idx as u16, + }, + */ + Self::ArrayLength { dest, arr } => Ok(InsFormat::Format12X { + op: 0x21, + va: *dest, + vb: *arr, + }), + /* needs type_idx + Self::NewInstance {reg, type_idx} => Ok(InsFormat::Format21C { + op: 0x22, + va: *reg, + b: *type_idx as u16, + }), + */ + /* needs type_idx + Self::NewArray { reg, size_reg, type_idx} => Ok(InsFormat::Format22C { + op: 0x23, + va: *reg, + vb: *size_reg, + c: *type_idx as u16, + }), + */ + /* need type_idx + Self::FilledNewArray { reg_values } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = reg_values.len(); + for r in reg_values.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in reg_values.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = reg_values.len() as u8; + Ok(InsFormat::Format35C { + op: 0x24, + a, + vc, + ve, + vd, + vf, + vg, + b: type_idx as u16, + }) + } else if consec && len <= 255 { + let a = reg_values.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x25, + a, + vc, + b: type_idx as u16, + }) + } else { + // Not supposed to happend with a sanitized array + panic!("Invalid NewArrayInstruction {self:?}") + } + } + */ + /* needs data_offset + Self::FillArrayData { arr, data_offset } => Ok(InsFormat::Format31T { + op: 0x26, + va: *arr, + b: data_offset, + }), + */ + Self::Throw { reg } => Ok(InsFormat::Format11X { op: 0x27, va: *reg }), + /* needs data_offset + Self::Goto { data_offset } => { + if goto_size == 2 && (I8_MIN_AS_I32..=I8_MAX_AS_I32).contains(&data_offset) { + Ok(InsFormat::Format10T { + op: 0x28, + a: data_offset as i8, + }) + } else if goto_size == 4 && (I16_MIN_AS_I32..=I16_MAX_AS_I32).contains(&data_offset) + { + Ok(InsFormat::Format20T { + op: 0x29, + a: data_offset as i16, + }) + } else if goto_size == 6 { + Ok(InsFormat::Format30T { + op: 0x2a, + a: data_offset, + }) + } else { + panic!("Invalid goto_size and/or data_offset value") + } + } + */ + /* needs data_offset + Self::Switch {reg, data_offset} => Ok(InsFormat::Format31T { + op: if is_packed() { 0x2b } else { 0x2c }, + va: *reg, + b: data_offset, + }), + */ + Self::CmpLFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x2d, + va: *dest, + vb: *b, + vc: *c, + }), + Self::CmpGFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x2e, + va: *dest, + vb: *b, + vc: *c, + }), + Self::CmpLDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x2f, + va: *dest, + vb: *b, + vc: *c, + }), + Self::CmpGDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x30, + va: *dest, + vb: *b, + vc: *c, + }), + Self::CmpLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x31, + va: *dest, + vb: *b, + vc: *c, + }), + /* needs branch_offset + Self::IfEq { a, b } => Ok(InsFormat::Format22T { + op: 0x32, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfNe { a, b } => Ok(InsFormat::Format22T { + op: 0x33, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfLt { a, b } => Ok(InsFormat::Format22T { + op: 0x34, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfGe { a, b } => Ok(InsFormat::Format22T { + op: 0x35, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfGt { a, b } => Ok(InsFormat::Format22T { + op: 0x36, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfLe { a, b } => Ok(InsFormat::Format22T { + op: 0x37, + va: *a, + vb: *b, + c: *branch_offset, + }), + Self::IfEqZ { a } => Ok(InsFormat::Format21T { + op: 0x38, + va: *a, + b: *branch_offset, + }), + Self::IfNeZ { a } => Ok(InsFormat::Format21T { + op: 0x39, + va: *a, + b: *branch_offset, + }), + Self::IfLtZ { a } => Ok(InsFormat::Format21T { + op: 0x3a, + va: *a, + b: *branch_offset, + }), + Self::IfGeZ { a } => Ok(InsFormat::Format21T { + op: 0x3b, + va: *a, + b: *branch_offset, + }), + Self::IfGtZ { a } => Ok(InsFormat::Format21T { + op: 0x3c, + va: *a, + b: *branch_offset, + }), + Self::IfLeZ { a } => Ok(InsFormat::Format21T { + op: 0x3d, + va: *a, + b: *branch_offset, + }), + */ + Self::AGet { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x44, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetWide { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x45, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetObject { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x46, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetBoolean { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x47, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetByte { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x48, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetChar { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x49, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::AGetShort { dest, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4a, + va: *dest, + vb: *arr, + vc: *idx, + }), + Self::APut { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4b, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutWide { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4c, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutObject { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4d, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutBoolean { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4e, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutByte { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x4f, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutChar { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x50, + va: *from, + vb: *arr, + vc: *idx, + }), + Self::APutShort { from, arr, idx } => Ok(InsFormat::Format23X { + op: 0x51, + va: *from, + vb: *arr, + vc: *idx, + }), + /* needs field_idx + Self::IGet { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x52, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetWide { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x53, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetObject { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x54, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetBoolean { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x55, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetByte { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x56, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetChar { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x57, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IGetShort { to, obj, field } => Ok(InsFormat::Format22C { + op: 0x58, + va: *to, + vb: *obj, + c: field_idx as u16, + }), + Self::IPut { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x59, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutWide { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5a, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutObject { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5b, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutBoolean { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5c, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutByte { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5d, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutChar { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5e, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::IPutShort { from, obj, field } => Ok(InsFormat::Format22C { + op: 0x5f, + va: *from, + vb: *obj, + c: field_idx as u16, + }), + Self::SGet { to, field } => Ok(InsFormat::Format21C { + op: 0x60, + va: *to, + b: field_idx as u16, + }), + Self::SGetWide { to, field } => Ok(InsFormat::Format21C { + op: 0x61, + va: *to, + b: field_idx as u16, + }), + Self::SGetObject { to, field } => Ok(InsFormat::Format21C { + op: 0x62, + va: *to, + b: field_idx as u16, + }), + Self::SGetBoolean { to, field } => Ok(InsFormat::Format21C { + op: 0x63, + va: *to, + b: field_idx as u16, + }), + Self::SGetByte { to, field } => Ok(InsFormat::Format21C { + op: 0x64, + va: *to, + b: field_idx as u16, + }), + Self::SGetChar { to, field } => Ok(InsFormat::Format21C { + op: 0x65, + va: *to, + b: field_idx as u16, + }), + Self::SGetShort { to, field } => Ok(InsFormat::Format21C { + op: 0x66, + va: *to, + b: field_idx as u16, + }), + Self::SPut { from, field } => Ok(InsFormat::Format21C { + op: 0x67, + va: *from, + b: field_idx as u16, + }), + Self::SPutWide { from, field } => Ok(InsFormat::Format21C { + op: 0x68, + va: *from, + b: field_idx as u16, + }), + Self::SPutObject { from, field } => Ok(InsFormat::Format21C { + op: 0x69, + va: *from, + b: field_idx as u16, + }), + Self::SPutBoolean { from, field } => Ok(InsFormat::Format21C { + op: 0x6a, + va: *from, + b: field_idx as u16, + }), + Self::SPutByte { from, field } => Ok(InsFormat::Format21C { + op: 0x6b, + va: *from, + b: field_idx as u16, + }), + Self::SPutChar { from, field } => Ok(InsFormat::Format21C { + op: 0x6c, + va: *from, + b: field_idx as u16, + }), + Self::SPutShort { from, field } => Ok(InsFormat::Format21C { + op: 0x6d, + va: *from, + b: field_idx as u16, + }), + */ + /* needs meth_idx + Self::InvokeVirtual { args, method } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0x6e, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x74, + a, + vc, + b: meth_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + Self::InvokeSuper { args, method } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0x6f, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x75, + a, + vc, + b: meth_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + Self::InvokeDirect { args, method } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0x70, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x76, + a, + vc, + b: meth_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + Self::InvokeStatic { args, method } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0x71, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x77, + a, + vc, + b: meth_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + Self::InvokeInterface { args, method } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0x72, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0x78, + a, + vc, + b: meth_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + */ + Self::NegInt { dest, val } => Ok(InsFormat::Format12X { + op: 0x7b, + va: *dest, + vb: *val, + }), + Self::NotInt { dest, val } => Ok(InsFormat::Format12X { + op: 0x7c, + va: *dest, + vb: *val, + }), + Self::NegLong { dest, val } => Ok(InsFormat::Format12X { + op: 0x7d, + va: *dest, + vb: *val, + }), + Self::NotLong { dest, val } => Ok(InsFormat::Format12X { + op: 0x7e, + va: *dest, + vb: *val, + }), + Self::NegFloat { dest, val } => Ok(InsFormat::Format12X { + op: 0x7f, + va: *dest, + vb: *val, + }), + Self::NegDouble { dest, val } => Ok(InsFormat::Format12X { + op: 0x80, + va: *dest, + vb: *val, + }), + Self::IntToLong { dest, val } => Ok(InsFormat::Format12X { + op: 0x81, + va: *dest, + vb: *val, + }), + Self::IntToFloat { dest, val } => Ok(InsFormat::Format12X { + op: 0x82, + va: *dest, + vb: *val, + }), + Self::IntToDouble { dest, val } => Ok(InsFormat::Format12X { + op: 0x83, + va: *dest, + vb: *val, + }), + Self::LongToInt { dest, val } => Ok(InsFormat::Format12X { + op: 0x84, + va: *dest, + vb: *val, + }), + Self::LongToFloat { dest, val } => Ok(InsFormat::Format12X { + op: 0x85, + va: *dest, + vb: *val, + }), + Self::LongToDouble { dest, val } => Ok(InsFormat::Format12X { + op: 0x86, + va: *dest, + vb: *val, + }), + Self::FloatToInt { dest, val } => Ok(InsFormat::Format12X { + op: 0x87, + va: *dest, + vb: *val, + }), + Self::FloatToLong { dest, val } => Ok(InsFormat::Format12X { + op: 0x88, + va: *dest, + vb: *val, + }), + Self::FloatToDouble { dest, val } => Ok(InsFormat::Format12X { + op: 0x89, + va: *dest, + vb: *val, + }), + Self::DoubleToInt { dest, val } => Ok(InsFormat::Format12X { + op: 0x8a, + va: *dest, + vb: *val, + }), + Self::DoubleToLong { dest, val } => Ok(InsFormat::Format12X { + op: 0x8b, + va: *dest, + vb: *val, + }), + Self::DoubleToFloat { dest, val } => Ok(InsFormat::Format12X { + op: 0x8c, + va: *dest, + vb: *val, + }), + Self::IntToByte { dest, val } => Ok(InsFormat::Format12X { + op: 0x8d, + va: *dest, + vb: *val, + }), + Self::IntToChar { dest, val } => Ok(InsFormat::Format12X { + op: 0x8e, + va: *dest, + vb: *val, + }), + Self::IntToShort { dest, val } => Ok(InsFormat::Format12X { + op: 0x8f, + va: *dest, + vb: *val, + }), + Self::AddInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x90, + va: *dest, + vb: *b, + vc: *c, + }), + Self::SubInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x91, + va: *dest, + vb: *b, + vc: *c, + }), + Self::MulInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x92, + va: *dest, + vb: *b, + vc: *c, + }), + Self::DivInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x93, + va: *dest, + vb: *b, + vc: *c, + }), + Self::RemInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x94, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AndInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x95, + va: *dest, + vb: *b, + vc: *c, + }), + Self::OrInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x96, + va: *dest, + vb: *b, + vc: *c, + }), + Self::XorInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x97, + va: *dest, + vb: *b, + vc: *c, + }), + Self::ShlInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x98, + va: *dest, + vb: *b, + vc: *c, + }), + Self::ShrInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x99, + va: *dest, + vb: *b, + vc: *c, + }), + Self::UshrInt { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9a, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AddLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9b, + va: *dest, + vb: *b, + vc: *c, + }), + Self::SubLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9c, + va: *dest, + vb: *b, + vc: *c, + }), + Self::MulLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9d, + va: *dest, + vb: *b, + vc: *c, + }), + Self::DivLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9e, + va: *dest, + vb: *b, + vc: *c, + }), + Self::RemLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0x9f, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AndLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa0, + va: *dest, + vb: *b, + vc: *c, + }), + Self::OrLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa1, + va: *dest, + vb: *b, + vc: *c, + }), + Self::XorLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa2, + va: *dest, + vb: *b, + vc: *c, + }), + Self::ShlLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa3, + va: *dest, + vb: *b, + vc: *c, + }), + Self::ShrLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa4, + va: *dest, + vb: *b, + vc: *c, + }), + Self::UshrLong { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa5, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AddFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa6, + va: *dest, + vb: *b, + vc: *c, + }), + Self::SubFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa7, + va: *dest, + vb: *b, + vc: *c, + }), + Self::MulFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa8, + va: *dest, + vb: *b, + vc: *c, + }), + Self::DivFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xa9, + va: *dest, + vb: *b, + vc: *c, + }), + Self::RemFloat { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xaa, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AddDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xab, + va: *dest, + vb: *b, + vc: *c, + }), + Self::SubDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xac, + va: *dest, + vb: *b, + vc: *c, + }), + Self::MulDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xad, + va: *dest, + vb: *b, + vc: *c, + }), + Self::DivDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xae, + va: *dest, + vb: *b, + vc: *c, + }), + Self::RemDouble { dest, b, c } => Ok(InsFormat::Format23X { + op: 0xaf, + va: *dest, + vb: *b, + vc: *c, + }), + Self::AddInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb0, + va: *dest, + vb: *b, + }), + Self::SubInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb1, + va: *dest, + vb: *b, + }), + Self::MulInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb2, + va: *dest, + vb: *b, + }), + Self::DivInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb3, + va: *dest, + vb: *b, + }), + Self::RemInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb4, + va: *dest, + vb: *b, + }), + Self::AndInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb5, + va: *dest, + vb: *b, + }), + Self::OrInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb6, + va: *dest, + vb: *b, + }), + Self::XorInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb7, + va: *dest, + vb: *b, + }), + Self::ShlInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb8, + va: *dest, + vb: *b, + }), + Self::ShrInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xb9, + va: *dest, + vb: *b, + }), + Self::UshrInt2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xba, + va: *dest, + vb: *b, + }), + Self::AddLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xbb, + va: *dest, + vb: *b, + }), + Self::SubLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xbc, + va: *dest, + vb: *b, + }), + Self::MulLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xbd, + va: *dest, + vb: *b, + }), + Self::DivLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xbe, + va: *dest, + vb: *b, + }), + Self::RemLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xbf, + va: *dest, + vb: *b, + }), + Self::AndLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc0, + va: *dest, + vb: *b, + }), + Self::OrLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc1, + va: *dest, + vb: *b, + }), + Self::XorLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc2, + va: *dest, + vb: *b, + }), + Self::ShlLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc3, + va: *dest, + vb: *b, + }), + Self::ShrLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc4, + va: *dest, + vb: *b, + }), + Self::UshrLong2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc5, + va: *dest, + vb: *b, + }), + Self::AddFloat2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc6, + va: *dest, + vb: *b, + }), + Self::SubFloat2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc7, + va: *dest, + vb: *b, + }), + Self::MulFloat2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc8, + va: *dest, + vb: *b, + }), + Self::DivFloat2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xc9, + va: *dest, + vb: *b, + }), + Self::RemFloat2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xca, + va: *dest, + vb: *b, + }), + Self::AddDouble2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xcb, + va: *dest, + vb: *b, + }), + Self::SubDouble2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xcc, + va: *dest, + vb: *b, + }), + Self::MulDouble2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xcd, + va: *dest, + vb: *b, + }), + Self::DivDouble2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xce, + va: *dest, + vb: *b, + }), + Self::RemDouble2Addr { b, dest } => Ok(InsFormat::Format12X { + op: 0xcf, + va: *dest, + vb: *b, + }), + Self::AddIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "add-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (add-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (add-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xd8, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd0, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::RsubIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "sub-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (sub-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (sub-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xd9, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd1, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::MulIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "mul-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (mul-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (mul-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xda, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd2, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::DivIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "div-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (div-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (div-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xdb, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd3, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::RemIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "rem-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (rem-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (rem-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xdc, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd4, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::AndIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "and-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (and-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (and-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xdd, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd5, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::OrIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "or-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (or-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (or-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xde, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd6, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::XorIntLit { lit, b, dest } => { + let mut reg_on_4_bit = true; + let mut lit_on_8_bits = true; + if dest & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if b & 0b1111_0000 != 0 { + reg_on_4_bit = false; + } + if *lit < I8_MIN_AS_I16 || *lit > I8_MAX_AS_I16 { + lit_on_8_bits = false; + } + if !reg_on_4_bit && !lit_on_8_bits { + // Should not happen on a sanitized op + panic!( + "xor-int/lit uses either registers indexed on 4 bits, and a literal \ + encoded on 16 bits (xor-int/lit16), or registers indexed on 8 bits and \ + a literal encoded on 8 bits (xor-int/lit8). Found reg {} and {}, and lit \ + {}", + dest, b, lit + ) + } else if lit_on_8_bits { + Ok(InsFormat::Format22B { + op: 0xdf, + va: *dest, + vb: *b, + c: *lit as i8, + }) + } else { + Ok(InsFormat::Format22S { + op: 0xd7, + va: *dest, + vb: *b, + c: *lit, + }) + } + } + Self::ShlIntLit { dest, b, lit } => Ok(InsFormat::Format22B { + op: 0xe0, + va: *dest, + vb: *b, + c: *lit, + }), + Self::ShrIntLit { dest, b, lit } => Ok(InsFormat::Format22B { + op: 0xe1, + va: *dest, + vb: *b, + c: *lit, + }), + Self::UshrIntLit { dest, b, lit } => Ok(InsFormat::Format22B { + op: 0xe2, + va: *dest, + vb: *b, + c: *lit, + }), + /* needs method_idx and proto_idx + Self::InvokePolymorphic { args, method, proto } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format45CC { + op: 0xfa, + a, + vc, + ve, + vd, + vf, + vg, + b: meth_idx, + h: proto_idx, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format4RCC { + op: 0xfb, + a, + vc, + b: meth_idx, + h: proto_idx, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + */ + /* needs call_site_idx + Self::InvokeCustom { args, call_site } => { + let mut last = None; + let mut first = None; + let mut consec = true; + let mut four_bites = true; + let len = args.len(); + for r in args.iter().cloned() { + if first.is_none() { + first = Some(r); + } + if let Some(last) = last { + if r != last + 1 { + consec = false; + } + } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); + } + if four_bites && len <= 5 { + let mut regs = vec![]; + for reg in args.iter().cloned() { + regs.push(reg); + } + while regs.len() != 5 { + regs.push(0); + } + let [vc, vd, ve, vf, vg]: [u8; 5] = regs + .into_iter() + .map(|r| r as u8) + .collect::>() + .try_into() + .ok() + .unwrap(); + let a = args.len() as u8; + Ok(InsFormat::Format35C { + op: 0xfc, + a, + vc, + ve, + vd, + vf, + vg, + b: call_site_idx as u16, + }) + } else if consec && len <= 255 { + let a = args.len() as u8; + let vc = if let Some(vc) = first { vc } else { 0 }; + Ok(InsFormat::Format3RC { + op: 0xfd, + a, + vc, + b: call_site_idx as u16, + }) + } else { + // Not supposed to happend with a sanitized invoke + panic!("Invalid Invoke instruction {self:?}") + } + } + */ + /* needs method_handle_idx + Self::ConstMethodHandle {to, handle} => Ok(InsFormat::Format21C { + op: 0xfe, + va: *to, + b: method_handle_idx as u16, + }), + */ + /* needs proto_idx + Self::ConstMethodType {to, proto} => Ok(InsFormat::Format21C { + op: 0xff, + va: *to, + b: proto_idx as u16, + }), + */ } } - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - let mut visitor = StringCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut visitor = TypeCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - let mut visitor = MethodTypeCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut visitor = FieldIdCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut visitor = MethodIdCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - let mut visitor = MethodHandleCollector::default(); - visitor.visit_instruction(self).unwrap(); - visitor.result() - } -} - -impl<'source> FromPyObject<'source> for Instruction { - fn extract(ob: &'source PyAny) -> PyResult { - if let Ok(ins) = Nop::extract(ob) { - Ok(Self::Nop {}) - } else if let Ok(ins) = Move::extract(ob) { - Ok(Self::Move(ins)) - } else if let Ok(ins) = MoveWide::extract(ob) { - Ok(Self::MoveWide(ins)) - } else if let Ok(ins) = MoveObject::extract(ob) { - Ok(Self::MoveObject(ins)) - } else if let Ok(ins) = MoveResult::extract(ob) { - Ok(Self::MoveResult(ins)) - } else if let Ok(ins) = MoveResultWide::extract(ob) { - Ok(Self::MoveResultWide(ins)) - } else if let Ok(ins) = MoveException::extract(ob) { - Ok(Self::MoveException(ins)) - } else if let Ok(ins) = MoveResultObject::extract(ob) { - Ok(Self::MoveResultObject(ins)) - } else if let Ok(ins) = ReturnVoid::extract(ob) { - Ok(Self::ReturnVoid(ins)) - } else if let Ok(ins) = Return::extract(ob) { - Ok(Self::Return(ins)) - } else if let Ok(ins) = ReturnWide::extract(ob) { - Ok(Self::ReturnWide(ins)) - } else if let Ok(ins) = ReturnObject::extract(ob) { - Ok(Self::ReturnObject(ins)) - } else if let Ok(ins) = Const::extract(ob) { - Ok(Self::Const(ins)) - } else if let Ok(ins) = ConstWide::extract(ob) { - Ok(Self::ConstWide(ins)) - } else if let Ok(ins) = ConstString::extract(ob) { - Ok(Self::ConstString(ins)) - } else if let Ok(ins) = ConstClass::extract(ob) { - Ok(Self::ConstClass(ins)) - } else if let Ok(ins) = MonitorEnter::extract(ob) { - Ok(Self::MonitorEnter(ins)) - } else if let Ok(ins) = MonitorExit::extract(ob) { - Ok(Self::MonitorExit(ins)) - } else if let Ok(ins) = CheckCast::extract(ob) { - Ok(Self::CheckCast(ins)) - } else if let Ok(ins) = InstanceOf::extract(ob) { - Ok(Self::InstanceOf(ins)) - } else if let Ok(ins) = ArrayLength::extract(ob) { - Ok(Self::ArrayLength(ins)) - } else if let Ok(ins) = NewInstance::extract(ob) { - Ok(Self::NewInstance(ins)) - } else if let Ok(ins) = NewArray::extract(ob) { - Ok(Self::NewArray(ins)) - } else if let Ok(ins) = FilledNewArray::extract(ob) { - Ok(Self::FilledNewArray(ins)) - } else if let Ok(ins) = FillArrayData::extract(ob) { - Ok(Self::FillArrayData(ins)) - } else if let Ok(ins) = Throw::extract(ob) { - Ok(Self::Throw(ins)) - } else if let Ok(ins) = Goto::extract(ob) { - Ok(Self::Goto(ins)) - } else if let Ok(ins) = Switch::extract(ob) { - Ok(Self::Switch(ins)) - } else if let Ok(ins) = CmpLFloat::extract(ob) { - Ok(Self::CmpLFloat(ins)) - } else if let Ok(ins) = CmpGFloat::extract(ob) { - Ok(Self::CmpGFloat(ins)) - } else if let Ok(ins) = CmpLDouble::extract(ob) { - Ok(Self::CmpLDouble(ins)) - } else if let Ok(ins) = CmpGDouble::extract(ob) { - Ok(Self::CmpGDouble(ins)) - } else if let Ok(ins) = CmpLong::extract(ob) { - Ok(Self::CmpLong(ins)) - } else if let Ok(ins) = IfEq::extract(ob) { - Ok(Self::IfEq(ins)) - } else if let Ok(ins) = IfNe::extract(ob) { - Ok(Self::IfNe(ins)) - } else if let Ok(ins) = IfLt::extract(ob) { - Ok(Self::IfLt(ins)) - } else if let Ok(ins) = IfGe::extract(ob) { - Ok(Self::IfGe(ins)) - } else if let Ok(ins) = IfGt::extract(ob) { - Ok(Self::IfGt(ins)) - } else if let Ok(ins) = IfLe::extract(ob) { - Ok(Self::IfLe(ins)) - } else if let Ok(ins) = IfEqZ::extract(ob) { - Ok(Self::IfEqZ(ins)) - } else if let Ok(ins) = IfNeZ::extract(ob) { - Ok(Self::IfNeZ(ins)) - } else if let Ok(ins) = IfLtZ::extract(ob) { - Ok(Self::IfLtZ(ins)) - } else if let Ok(ins) = IfGeZ::extract(ob) { - Ok(Self::IfGeZ(ins)) - } else if let Ok(ins) = IfGtZ::extract(ob) { - Ok(Self::IfGtZ(ins)) - } else if let Ok(ins) = IfLeZ::extract(ob) { - Ok(Self::IfLeZ(ins)) - } else if let Ok(ins) = AGet::extract(ob) { - Ok(Self::AGet(ins)) - } else if let Ok(ins) = AGetWide::extract(ob) { - Ok(Self::AGetWide(ins)) - } else if let Ok(ins) = AGetObject::extract(ob) { - Ok(Self::AGetObject(ins)) - } else if let Ok(ins) = AGetBoolean::extract(ob) { - Ok(Self::AGetBoolean(ins)) - } else if let Ok(ins) = AGetByte::extract(ob) { - Ok(Self::AGetByte(ins)) - } else if let Ok(ins) = AGetChar::extract(ob) { - Ok(Self::AGetChar(ins)) - } else if let Ok(ins) = AGetShort::extract(ob) { - Ok(Self::AGetShort(ins)) - } else if let Ok(ins) = APut::extract(ob) { - Ok(Self::APut(ins)) - } else if let Ok(ins) = APutWide::extract(ob) { - Ok(Self::APutWide(ins)) - } else if let Ok(ins) = APutObject::extract(ob) { - Ok(Self::APutObject(ins)) - } else if let Ok(ins) = APutBoolean::extract(ob) { - Ok(Self::APutBoolean(ins)) - } else if let Ok(ins) = APutByte::extract(ob) { - Ok(Self::APutByte(ins)) - } else if let Ok(ins) = APutChar::extract(ob) { - Ok(Self::APutChar(ins)) - } else if let Ok(ins) = APutShort::extract(ob) { - Ok(Self::APutShort(ins)) - } else if let Ok(ins) = IGet::extract(ob) { - Ok(Self::IGet(ins)) - } else if let Ok(ins) = IGetWide::extract(ob) { - Ok(Self::IGetWide(ins)) - } else if let Ok(ins) = IGetObject::extract(ob) { - Ok(Self::IGetObject(ins)) - } else if let Ok(ins) = IGetBoolean::extract(ob) { - Ok(Self::IGetBoolean(ins)) - } else if let Ok(ins) = IGetByte::extract(ob) { - Ok(Self::IGetByte(ins)) - } else if let Ok(ins) = IGetChar::extract(ob) { - Ok(Self::IGetChar(ins)) - } else if let Ok(ins) = IGetShort::extract(ob) { - Ok(Self::IGetShort(ins)) - } else if let Ok(ins) = IPut::extract(ob) { - Ok(Self::IPut(ins)) - } else if let Ok(ins) = IPutWide::extract(ob) { - Ok(Self::IPutWide(ins)) - } else if let Ok(ins) = IPutObject::extract(ob) { - Ok(Self::IPutObject(ins)) - } else if let Ok(ins) = IPutBoolean::extract(ob) { - Ok(Self::IPutBoolean(ins)) - } else if let Ok(ins) = IPutByte::extract(ob) { - Ok(Self::IPutByte(ins)) - } else if let Ok(ins) = IPutChar::extract(ob) { - Ok(Self::IPutChar(ins)) - } else if let Ok(ins) = IPutShort::extract(ob) { - Ok(Self::IPutShort(ins)) - } else if let Ok(ins) = SGet::extract(ob) { - Ok(Self::SGet(ins)) - } else if let Ok(ins) = SGetWide::extract(ob) { - Ok(Self::SGetWide(ins)) - } else if let Ok(ins) = SGetObject::extract(ob) { - Ok(Self::SGetObject(ins)) - } else if let Ok(ins) = SGetBoolean::extract(ob) { - Ok(Self::SGetBoolean(ins)) - } else if let Ok(ins) = SGetByte::extract(ob) { - Ok(Self::SGetByte(ins)) - } else if let Ok(ins) = SGetChar::extract(ob) { - Ok(Self::SGetChar(ins)) - } else if let Ok(ins) = SGetShort::extract(ob) { - Ok(Self::SGetShort(ins)) - } else if let Ok(ins) = SPut::extract(ob) { - Ok(Self::SPut(ins)) - } else if let Ok(ins) = SPutWide::extract(ob) { - Ok(Self::SPutWide(ins)) - } else if let Ok(ins) = SPutObject::extract(ob) { - Ok(Self::SPutObject(ins)) - } else if let Ok(ins) = SPutBoolean::extract(ob) { - Ok(Self::SPutBoolean(ins)) - } else if let Ok(ins) = SPutByte::extract(ob) { - Ok(Self::SPutByte(ins)) - } else if let Ok(ins) = SPutChar::extract(ob) { - Ok(Self::SPutChar(ins)) - } else if let Ok(ins) = SPutShort::extract(ob) { - Ok(Self::SPutShort(ins)) - } else if let Ok(ins) = InvokeVirtual::extract(ob) { - Ok(Self::InvokeVirtual(ins)) - } else if let Ok(ins) = InvokeSuper::extract(ob) { - Ok(Self::InvokeSuper(ins)) - } else if let Ok(ins) = InvokeDirect::extract(ob) { - Ok(Self::InvokeDirect(ins)) - } else if let Ok(ins) = InvokeStatic::extract(ob) { - Ok(Self::InvokeStatic(ins)) - } else if let Ok(ins) = InvokeInterface::extract(ob) { - Ok(Self::InvokeInterface(ins)) - } else if let Ok(ins) = NegInt::extract(ob) { - Ok(Self::NegInt(ins)) - } else if let Ok(ins) = NotInt::extract(ob) { - Ok(Self::NotInt(ins)) - } else if let Ok(ins) = NegLong::extract(ob) { - Ok(Self::NegLong(ins)) - } else if let Ok(ins) = NotLong::extract(ob) { - Ok(Self::NotLong(ins)) - } else if let Ok(ins) = NegFloat::extract(ob) { - Ok(Self::NegFloat(ins)) - } else if let Ok(ins) = NegDouble::extract(ob) { - Ok(Self::NegDouble(ins)) - } else if let Ok(ins) = IntToLong::extract(ob) { - Ok(Self::IntToLong(ins)) - } else if let Ok(ins) = IntToFloat::extract(ob) { - Ok(Self::IntToFloat(ins)) - } else if let Ok(ins) = IntToDouble::extract(ob) { - Ok(Self::IntToDouble(ins)) - } else if let Ok(ins) = LongToInt::extract(ob) { - Ok(Self::LongToInt(ins)) - } else if let Ok(ins) = LongToFloat::extract(ob) { - Ok(Self::LongToFloat(ins)) - } else if let Ok(ins) = LongToDouble::extract(ob) { - Ok(Self::LongToDouble(ins)) - } else if let Ok(ins) = FloatToInt::extract(ob) { - Ok(Self::FloatToInt(ins)) - } else if let Ok(ins) = FloatToLong::extract(ob) { - Ok(Self::FloatToLong(ins)) - } else if let Ok(ins) = FloatToDouble::extract(ob) { - Ok(Self::FloatToDouble(ins)) - } else if let Ok(ins) = DoubleToInt::extract(ob) { - Ok(Self::DoubleToInt(ins)) - } else if let Ok(ins) = DoubleToLong::extract(ob) { - Ok(Self::DoubleToLong(ins)) - } else if let Ok(ins) = DoubleToFloat::extract(ob) { - Ok(Self::DoubleToFloat(ins)) - } else if let Ok(ins) = IntToByte::extract(ob) { - Ok(Self::IntToByte(ins)) - } else if let Ok(ins) = IntToChar::extract(ob) { - Ok(Self::IntToChar(ins)) - } else if let Ok(ins) = IntToShort::extract(ob) { - Ok(Self::IntToShort(ins)) - } else if let Ok(ins) = AddInt::extract(ob) { - Ok(Self::AddInt(ins)) - } else if let Ok(ins) = SubInt::extract(ob) { - Ok(Self::SubInt(ins)) - } else if let Ok(ins) = MulInt::extract(ob) { - Ok(Self::MulInt(ins)) - } else if let Ok(ins) = DivInt::extract(ob) { - Ok(Self::DivInt(ins)) - } else if let Ok(ins) = RemInt::extract(ob) { - Ok(Self::RemInt(ins)) - } else if let Ok(ins) = AndInt::extract(ob) { - Ok(Self::AndInt(ins)) - } else if let Ok(ins) = OrInt::extract(ob) { - Ok(Self::OrInt(ins)) - } else if let Ok(ins) = XorInt::extract(ob) { - Ok(Self::XorInt(ins)) - } else if let Ok(ins) = ShlInt::extract(ob) { - Ok(Self::ShlInt(ins)) - } else if let Ok(ins) = ShrInt::extract(ob) { - Ok(Self::ShrInt(ins)) - } else if let Ok(ins) = UshrInt::extract(ob) { - Ok(Self::UshrInt(ins)) - } else if let Ok(ins) = AddLong::extract(ob) { - Ok(Self::AddLong(ins)) - } else if let Ok(ins) = SubLong::extract(ob) { - Ok(Self::SubLong(ins)) - } else if let Ok(ins) = MulLong::extract(ob) { - Ok(Self::MulLong(ins)) - } else if let Ok(ins) = DivLong::extract(ob) { - Ok(Self::DivLong(ins)) - } else if let Ok(ins) = RemLong::extract(ob) { - Ok(Self::RemLong(ins)) - } else if let Ok(ins) = AndLong::extract(ob) { - Ok(Self::AndLong(ins)) - } else if let Ok(ins) = OrLong::extract(ob) { - Ok(Self::OrLong(ins)) - } else if let Ok(ins) = XorLong::extract(ob) { - Ok(Self::XorLong(ins)) - } else if let Ok(ins) = ShlLong::extract(ob) { - Ok(Self::ShlLong(ins)) - } else if let Ok(ins) = ShrLong::extract(ob) { - Ok(Self::ShrLong(ins)) - } else if let Ok(ins) = UshrLong::extract(ob) { - Ok(Self::UshrLong(ins)) - } else if let Ok(ins) = AddFloat::extract(ob) { - Ok(Self::AddFloat(ins)) - } else if let Ok(ins) = SubFloat::extract(ob) { - Ok(Self::SubFloat(ins)) - } else if let Ok(ins) = MulFloat::extract(ob) { - Ok(Self::MulFloat(ins)) - } else if let Ok(ins) = DivFloat::extract(ob) { - Ok(Self::DivFloat(ins)) - } else if let Ok(ins) = RemFloat::extract(ob) { - Ok(Self::RemFloat(ins)) - } else if let Ok(ins) = AddDouble::extract(ob) { - Ok(Self::AddDouble(ins)) - } else if let Ok(ins) = SubDouble::extract(ob) { - Ok(Self::SubDouble(ins)) - } else if let Ok(ins) = MulDouble::extract(ob) { - Ok(Self::MulDouble(ins)) - } else if let Ok(ins) = DivDouble::extract(ob) { - Ok(Self::DivDouble(ins)) - } else if let Ok(ins) = RemDouble::extract(ob) { - Ok(Self::RemDouble(ins)) - } else if let Ok(ins) = AddInt2Addr::extract(ob) { - Ok(Self::AddInt2Addr(ins)) - } else if let Ok(ins) = SubInt2Addr::extract(ob) { - Ok(Self::SubInt2Addr(ins)) - } else if let Ok(ins) = MulInt2Addr::extract(ob) { - Ok(Self::MulInt2Addr(ins)) - } else if let Ok(ins) = DivInt2Addr::extract(ob) { - Ok(Self::DivInt2Addr(ins)) - } else if let Ok(ins) = RemInt2Addr::extract(ob) { - Ok(Self::RemInt2Addr(ins)) - } else if let Ok(ins) = AndInt2Addr::extract(ob) { - Ok(Self::AndInt2Addr(ins)) - } else if let Ok(ins) = OrInt2Addr::extract(ob) { - Ok(Self::OrInt2Addr(ins)) - } else if let Ok(ins) = XorInt2Addr::extract(ob) { - Ok(Self::XorInt2Addr(ins)) - } else if let Ok(ins) = ShlInt2Addr::extract(ob) { - Ok(Self::ShlInt2Addr(ins)) - } else if let Ok(ins) = ShrInt2Addr::extract(ob) { - Ok(Self::ShrInt2Addr(ins)) - } else if let Ok(ins) = UshrInt2Addr::extract(ob) { - Ok(Self::UshrInt2Addr(ins)) - } else if let Ok(ins) = AddLong2Addr::extract(ob) { - Ok(Self::AddLong2Addr(ins)) - } else if let Ok(ins) = SubLong2Addr::extract(ob) { - Ok(Self::SubLong2Addr(ins)) - } else if let Ok(ins) = MulLong2Addr::extract(ob) { - Ok(Self::MulLong2Addr(ins)) - } else if let Ok(ins) = DivLong2Addr::extract(ob) { - Ok(Self::DivLong2Addr(ins)) - } else if let Ok(ins) = RemLong2Addr::extract(ob) { - Ok(Self::RemLong2Addr(ins)) - } else if let Ok(ins) = AndLong2Addr::extract(ob) { - Ok(Self::AndLong2Addr(ins)) - } else if let Ok(ins) = OrLong2Addr::extract(ob) { - Ok(Self::OrLong2Addr(ins)) - } else if let Ok(ins) = XorLong2Addr::extract(ob) { - Ok(Self::XorLong2Addr(ins)) - } else if let Ok(ins) = ShlLong2Addr::extract(ob) { - Ok(Self::ShlLong2Addr(ins)) - } else if let Ok(ins) = ShrLong2Addr::extract(ob) { - Ok(Self::ShrLong2Addr(ins)) - } else if let Ok(ins) = UshrLong2Addr::extract(ob) { - Ok(Self::UshrLong2Addr(ins)) - } else if let Ok(ins) = AddFloat2Addr::extract(ob) { - Ok(Self::AddFloat2Addr(ins)) - } else if let Ok(ins) = SubFloat2Addr::extract(ob) { - Ok(Self::SubFloat2Addr(ins)) - } else if let Ok(ins) = MulFloat2Addr::extract(ob) { - Ok(Self::MulFloat2Addr(ins)) - } else if let Ok(ins) = DivFloat2Addr::extract(ob) { - Ok(Self::DivFloat2Addr(ins)) - } else if let Ok(ins) = RemFloat2Addr::extract(ob) { - Ok(Self::RemFloat2Addr(ins)) - } else if let Ok(ins) = AddDouble2Addr::extract(ob) { - Ok(Self::AddDouble2Addr(ins)) - } else if let Ok(ins) = SubDouble2Addr::extract(ob) { - Ok(Self::SubDouble2Addr(ins)) - } else if let Ok(ins) = MulDouble2Addr::extract(ob) { - Ok(Self::MulDouble2Addr(ins)) - } else if let Ok(ins) = DivDouble2Addr::extract(ob) { - Ok(Self::DivDouble2Addr(ins)) - } else if let Ok(ins) = RemDouble2Addr::extract(ob) { - Ok(Self::RemDouble2Addr(ins)) - } else if let Ok(ins) = AddIntLit::extract(ob) { - Ok(Self::AddIntLit(ins)) - } else if let Ok(ins) = RsubIntLit::extract(ob) { - Ok(Self::RsubIntLit(ins)) - } else if let Ok(ins) = MulIntLit::extract(ob) { - Ok(Self::MulIntLit(ins)) - } else if let Ok(ins) = DivIntLit::extract(ob) { - Ok(Self::DivIntLit(ins)) - } else if let Ok(ins) = RemIntLit::extract(ob) { - Ok(Self::RemIntLit(ins)) - } else if let Ok(ins) = AndIntLit::extract(ob) { - Ok(Self::AndIntLit(ins)) - } else if let Ok(ins) = OrIntLit::extract(ob) { - Ok(Self::OrIntLit(ins)) - } else if let Ok(ins) = XorIntLit::extract(ob) { - Ok(Self::XorIntLit(ins)) - } else if let Ok(ins) = ShlIntLit::extract(ob) { - Ok(Self::ShlIntLit(ins)) - } else if let Ok(ins) = ShrIntLit::extract(ob) { - Ok(Self::ShrIntLit(ins)) - } else if let Ok(ins) = UshrIntLit::extract(ob) { - Ok(Self::UshrIntLit(ins)) - } else if let Ok(ins) = InvokePolymorphic::extract(ob) { - Ok(Self::InvokePolymorphic(ins)) - } else if let Ok(ins) = InvokeCustom::extract(ob) { - Ok(Self::InvokeCustom(ins)) - } else if let Ok(ins) = ConstMethodHandle::extract(ob) { - Ok(Self::ConstMethodHandle(ins)) - } else if let Ok(ins) = ConstMethodType::extract(ob) { - Ok(Self::ConstMethodType(ins)) - } else if let Ok(ins) = Try::extract(ob) { - Ok(Self::Try(ins)) - } else if let Ok(ins) = Label::extract(ob) { - Ok(Self::Label(ins)) - } else { - Err(PyErr::new::(format!( - "{} is not a castable as an Instruction", - ob.repr()? - ))) - } - } -} - -impl IntoPy for Instruction { - fn into_py(self, py: Python<'_>) -> PyObject { + /// TODO: remove? tmp solution for now, only implemented for Switch + pub fn is_packed(&self) -> bool { match self { - Self::Nop {} => todo!(), - Self::Move(ins) => ins.into_py(py), - Self::MoveWide(ins) => ins.into_py(py), - Self::MoveObject(ins) => ins.into_py(py), - Self::MoveResult(ins) => ins.into_py(py), - Self::MoveResultWide(ins) => ins.into_py(py), - Self::MoveException(ins) => ins.into_py(py), - Self::MoveResultObject(ins) => ins.into_py(py), - Self::ReturnVoid(ins) => ins.into_py(py), - Self::Return(ins) => ins.into_py(py), - Self::ReturnWide(ins) => ins.into_py(py), - Self::ReturnObject(ins) => ins.into_py(py), - Self::Const(ins) => ins.into_py(py), - Self::ConstWide(ins) => ins.into_py(py), - Self::ConstString(ins) => ins.into_py(py), - Self::ConstClass(ins) => ins.into_py(py), - Self::MonitorEnter(ins) => ins.into_py(py), - Self::MonitorExit(ins) => ins.into_py(py), - Self::CheckCast(ins) => ins.into_py(py), - Self::InstanceOf(ins) => ins.into_py(py), - Self::ArrayLength(ins) => ins.into_py(py), - Self::NewInstance(ins) => ins.into_py(py), - Self::NewArray(ins) => ins.into_py(py), - Self::FilledNewArray(ins) => ins.into_py(py), - Self::FillArrayData(ins) => ins.into_py(py), - Self::Throw(ins) => ins.into_py(py), - Self::Goto(ins) => ins.into_py(py), - Self::Switch(ins) => ins.into_py(py), - Self::CmpLFloat(ins) => ins.into_py(py), - Self::CmpGFloat(ins) => ins.into_py(py), - Self::CmpLDouble(ins) => ins.into_py(py), - Self::CmpGDouble(ins) => ins.into_py(py), - Self::CmpLong(ins) => ins.into_py(py), - Self::IfEq(ins) => ins.into_py(py), - Self::IfNe(ins) => ins.into_py(py), - Self::IfLt(ins) => ins.into_py(py), - Self::IfGe(ins) => ins.into_py(py), - Self::IfGt(ins) => ins.into_py(py), - Self::IfLe(ins) => ins.into_py(py), - Self::IfEqZ(ins) => ins.into_py(py), - Self::IfNeZ(ins) => ins.into_py(py), - Self::IfLtZ(ins) => ins.into_py(py), - Self::IfGeZ(ins) => ins.into_py(py), - Self::IfGtZ(ins) => ins.into_py(py), - Self::IfLeZ(ins) => ins.into_py(py), - Self::AGet(ins) => ins.into_py(py), - Self::AGetWide(ins) => ins.into_py(py), - Self::AGetObject(ins) => ins.into_py(py), - Self::AGetBoolean(ins) => ins.into_py(py), - Self::AGetByte(ins) => ins.into_py(py), - Self::AGetChar(ins) => ins.into_py(py), - Self::AGetShort(ins) => ins.into_py(py), - Self::APut(ins) => ins.into_py(py), - Self::APutWide(ins) => ins.into_py(py), - Self::APutObject(ins) => ins.into_py(py), - Self::APutBoolean(ins) => ins.into_py(py), - Self::APutByte(ins) => ins.into_py(py), - Self::APutChar(ins) => ins.into_py(py), - Self::APutShort(ins) => ins.into_py(py), - Self::IGet(ins) => ins.into_py(py), - Self::IGetWide(ins) => ins.into_py(py), - Self::IGetObject(ins) => ins.into_py(py), - Self::IGetBoolean(ins) => ins.into_py(py), - Self::IGetByte(ins) => ins.into_py(py), - Self::IGetChar(ins) => ins.into_py(py), - Self::IGetShort(ins) => ins.into_py(py), - Self::IPut(ins) => ins.into_py(py), - Self::IPutWide(ins) => ins.into_py(py), - Self::IPutObject(ins) => ins.into_py(py), - Self::IPutBoolean(ins) => ins.into_py(py), - Self::IPutByte(ins) => ins.into_py(py), - Self::IPutChar(ins) => ins.into_py(py), - Self::IPutShort(ins) => ins.into_py(py), - Self::SGet(ins) => ins.into_py(py), - Self::SGetWide(ins) => ins.into_py(py), - Self::SGetObject(ins) => ins.into_py(py), - Self::SGetBoolean(ins) => ins.into_py(py), - Self::SGetByte(ins) => ins.into_py(py), - Self::SGetChar(ins) => ins.into_py(py), - Self::SGetShort(ins) => ins.into_py(py), - Self::SPut(ins) => ins.into_py(py), - Self::SPutWide(ins) => ins.into_py(py), - Self::SPutObject(ins) => ins.into_py(py), - Self::SPutBoolean(ins) => ins.into_py(py), - Self::SPutByte(ins) => ins.into_py(py), - Self::SPutChar(ins) => ins.into_py(py), - Self::SPutShort(ins) => ins.into_py(py), - Self::InvokeVirtual(ins) => ins.into_py(py), - Self::InvokeSuper(ins) => ins.into_py(py), - Self::InvokeDirect(ins) => ins.into_py(py), - Self::InvokeStatic(ins) => ins.into_py(py), - Self::InvokeInterface(ins) => ins.into_py(py), - Self::NegInt(ins) => ins.into_py(py), - Self::NotInt(ins) => ins.into_py(py), - Self::NegLong(ins) => ins.into_py(py), - Self::NotLong(ins) => ins.into_py(py), - Self::NegFloat(ins) => ins.into_py(py), - Self::NegDouble(ins) => ins.into_py(py), - Self::IntToLong(ins) => ins.into_py(py), - Self::IntToFloat(ins) => ins.into_py(py), - Self::IntToDouble(ins) => ins.into_py(py), - Self::LongToInt(ins) => ins.into_py(py), - Self::LongToFloat(ins) => ins.into_py(py), - Self::LongToDouble(ins) => ins.into_py(py), - Self::FloatToInt(ins) => ins.into_py(py), - Self::FloatToLong(ins) => ins.into_py(py), - Self::FloatToDouble(ins) => ins.into_py(py), - Self::DoubleToInt(ins) => ins.into_py(py), - Self::DoubleToLong(ins) => ins.into_py(py), - Self::DoubleToFloat(ins) => ins.into_py(py), - Self::IntToByte(ins) => ins.into_py(py), - Self::IntToChar(ins) => ins.into_py(py), - Self::IntToShort(ins) => ins.into_py(py), - Self::AddInt(ins) => ins.into_py(py), - Self::SubInt(ins) => ins.into_py(py), - Self::MulInt(ins) => ins.into_py(py), - Self::DivInt(ins) => ins.into_py(py), - Self::RemInt(ins) => ins.into_py(py), - Self::AndInt(ins) => ins.into_py(py), - Self::OrInt(ins) => ins.into_py(py), - Self::XorInt(ins) => ins.into_py(py), - Self::ShlInt(ins) => ins.into_py(py), - Self::ShrInt(ins) => ins.into_py(py), - Self::UshrInt(ins) => ins.into_py(py), - Self::AddLong(ins) => ins.into_py(py), - Self::SubLong(ins) => ins.into_py(py), - Self::MulLong(ins) => ins.into_py(py), - Self::DivLong(ins) => ins.into_py(py), - Self::RemLong(ins) => ins.into_py(py), - Self::AndLong(ins) => ins.into_py(py), - Self::OrLong(ins) => ins.into_py(py), - Self::XorLong(ins) => ins.into_py(py), - Self::ShlLong(ins) => ins.into_py(py), - Self::ShrLong(ins) => ins.into_py(py), - Self::UshrLong(ins) => ins.into_py(py), - Self::AddFloat(ins) => ins.into_py(py), - Self::SubFloat(ins) => ins.into_py(py), - Self::MulFloat(ins) => ins.into_py(py), - Self::DivFloat(ins) => ins.into_py(py), - Self::RemFloat(ins) => ins.into_py(py), - Self::AddDouble(ins) => ins.into_py(py), - Self::SubDouble(ins) => ins.into_py(py), - Self::MulDouble(ins) => ins.into_py(py), - Self::DivDouble(ins) => ins.into_py(py), - Self::RemDouble(ins) => ins.into_py(py), - Self::AddInt2Addr(ins) => ins.into_py(py), - Self::SubInt2Addr(ins) => ins.into_py(py), - Self::MulInt2Addr(ins) => ins.into_py(py), - Self::DivInt2Addr(ins) => ins.into_py(py), - Self::RemInt2Addr(ins) => ins.into_py(py), - Self::AndInt2Addr(ins) => ins.into_py(py), - Self::OrInt2Addr(ins) => ins.into_py(py), - Self::XorInt2Addr(ins) => ins.into_py(py), - Self::ShlInt2Addr(ins) => ins.into_py(py), - Self::ShrInt2Addr(ins) => ins.into_py(py), - Self::UshrInt2Addr(ins) => ins.into_py(py), - Self::AddLong2Addr(ins) => ins.into_py(py), - Self::SubLong2Addr(ins) => ins.into_py(py), - Self::MulLong2Addr(ins) => ins.into_py(py), - Self::DivLong2Addr(ins) => ins.into_py(py), - Self::RemLong2Addr(ins) => ins.into_py(py), - Self::AndLong2Addr(ins) => ins.into_py(py), - Self::OrLong2Addr(ins) => ins.into_py(py), - Self::XorLong2Addr(ins) => ins.into_py(py), - Self::ShlLong2Addr(ins) => ins.into_py(py), - Self::ShrLong2Addr(ins) => ins.into_py(py), - Self::UshrLong2Addr(ins) => ins.into_py(py), - Self::AddFloat2Addr(ins) => ins.into_py(py), - Self::SubFloat2Addr(ins) => ins.into_py(py), - Self::MulFloat2Addr(ins) => ins.into_py(py), - Self::DivFloat2Addr(ins) => ins.into_py(py), - Self::RemFloat2Addr(ins) => ins.into_py(py), - Self::AddDouble2Addr(ins) => ins.into_py(py), - Self::SubDouble2Addr(ins) => ins.into_py(py), - Self::MulDouble2Addr(ins) => ins.into_py(py), - Self::DivDouble2Addr(ins) => ins.into_py(py), - Self::RemDouble2Addr(ins) => ins.into_py(py), - Self::AddIntLit(ins) => ins.into_py(py), - Self::RsubIntLit(ins) => ins.into_py(py), - Self::MulIntLit(ins) => ins.into_py(py), - Self::DivIntLit(ins) => ins.into_py(py), - Self::RemIntLit(ins) => ins.into_py(py), - Self::AndIntLit(ins) => ins.into_py(py), - Self::OrIntLit(ins) => ins.into_py(py), - Self::XorIntLit(ins) => ins.into_py(py), - Self::ShlIntLit(ins) => ins.into_py(py), - Self::ShrIntLit(ins) => ins.into_py(py), - Self::UshrIntLit(ins) => ins.into_py(py), - Self::InvokePolymorphic(ins) => ins.into_py(py), - Self::InvokeCustom(ins) => ins.into_py(py), - Self::ConstMethodHandle(ins) => ins.into_py(py), - Self::ConstMethodType(ins) => ins.into_py(py), - Self::Try(ins) => ins.into_py(py), - Self::Label(ins) => ins.into_py(py), + Self::Switch { branches, .. } => { + let mut last = None; + let mut keys = branches.keys().collect::>(); + keys.sort(); + for key in keys.into_iter().cloned() { + if let Some(last) = &last { + if *last != key - 1 { + return false; + } + } + last = Some(key); + } + true + } + _ => todo!(), // TODO: leave as is? + } + } + /// TODO: remove? rename goto_size_.. ?tmp solution for now + pub fn size_from_branch_offset_interval( + addr_goto: usize, + min_addr_branch: usize, + max_addr_branch: usize, + ) -> Result { + let worst_offset = if max_addr_branch as i32 - addr_goto as i32 + > addr_goto as i32 - min_addr_branch as i32 + { + max_addr_branch as i32 - addr_goto as i32 + } else { + min_addr_branch as i32 - addr_goto as i32 + }; + match worst_offset { + I8_MIN_AS_I32..=I8_MAX_AS_I32 => Ok(2), + I16_MIN_AS_I32..=I16_MAX_AS_I32 => Ok(4), + _ => Ok(6), } } } @@ -3662,25523 +6154,3 @@ impl CallSite { handles } } - -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct Nop; - -impl Default for Nop { - fn default() -> Self { - Self::new() - } -} - -#[pymethods] -impl Nop { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new() -> Self { - Self - } - - pub fn __str__(&self) -> String { - "nop".into() - } - - pub fn __repr__(&self) -> String { - "Instruction(Nop)".into() - } - - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Nop { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format10X { op: 0x00 } - } -} - -/// Move contents of a non object register to another. -/// -/// Can represent several dalvik instructions : -/// -/// move vA, vB -/// move/from16 vAA, vBBBB -/// move/16 vAAAA, vBBBB -/// -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct Move { - #[pyo3(get)] - pub from: u16, - #[pyo3(get)] - pub to: u16, -} - -#[pymethods] -impl Move { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u16, from: u16) -> Self { - Self { from, to } - } - - pub fn __str__(&self) -> String { - format!("move {} {}", self.to, self.from) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Move({}, {}))", self.to, self.from) - } - - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Move { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - match (self.to, self.from) { - (0..=0b0000_1111, 0..=0b0000_1111) => InsFormat::Format12X { - op: 0x01, - va: self.to as u8, - vb: self.from as u8, - }, - (0..=0xff, _) => InsFormat::Format22X { - op: 0x02, - va: self.to as u8, - vb: self.from, - }, - (_, _) => InsFormat::Format32X { - op: 0x03, - va: self.to, - vb: self.from, - }, - } - } -} - -/// Move contents of a register pair to another. -/// -/// Can represent several dalvik instructions : -/// -/// move-wide vA, vB -/// move-wide/from16 vAA, vBBBB -/// move-wide/16 vAAAA, vBBBB -/// -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveWide { - #[pyo3(get)] - pub from: u16, - #[pyo3(get)] - pub to: u16, -} - -#[pymethods] -impl MoveWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u16, from: u16) -> Self { - Self { from, to } - } - - pub fn __str__(&self) -> String { - format!("move-wide {} {}", self.to, self.from) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveWide({}, {}))", self.to, self.from) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - match (self.to, self.from) { - (0..=0b0000_1111, 0..=0b0000_1111) => InsFormat::Format12X { - op: 0x04, - va: self.to as u8, - vb: self.from as u8, - }, - (0..=0xff, _) => InsFormat::Format22X { - op: 0x05, - va: self.to as u8, - vb: self.from, - }, - (_, _) => InsFormat::Format32X { - op: 0x06, - va: self.to, - vb: self.from, - }, - } - } -} - -/// Move contents of an object bearing register to another. -/// -/// Can represent several dalvik instructions : -/// -/// move-object vA, vB -/// move-object/from16 vAA, vBBBB -/// move-object/16 vAAAA, vBBBB -/// -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveObject { - #[pyo3(get)] - pub from: u16, - #[pyo3(get)] - pub to: u16, -} - -#[pymethods] -impl MoveObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u16, from: u16) -> Self { - Self { from, to } - } - - pub fn __str__(&self) -> String { - format!("move-object {} {}", self.to, self.from) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveObject({}, {}))", self.to, self.from) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveObject { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - match (self.to, self.from) { - (0..=0b0000_1111, 0..=0b0000_1111) => InsFormat::Format12X { - op: 0x07, - va: self.to as u8, - vb: self.from as u8, - }, - (0..=0xff, _) => InsFormat::Format22X { - op: 0x08, - va: self.to as u8, - vb: self.from, - }, - (_, _) => InsFormat::Format32X { - op: 0x09, - va: self.to, - vb: self.from, - }, - } - } -} - -/// Move the single word non object result of the preciding invoke-kind into a register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveResult { - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl MoveResult { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8) -> Self { - Self { to } - } - - pub fn __str__(&self) -> String { - format!("move-result {}", self.to) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveResult({}))", self.to) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveResult { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x0a, - va: self.to, - } - } -} - -/// Move the double word non object result of the preciding invoke-kind into a register pair. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveResultWide { - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl MoveResultWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8) -> Self { - Self { to } - } - - pub fn __str__(&self) -> String { - format!("move-result-wide {}", self.to) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveResultWide({}))", self.to) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveResultWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x0b, - va: self.to, - } - } -} - -/// Move the object result of the preciding invoke-kind or filled-new-array into a register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveResultObject { - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl MoveResultObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8) -> Self { - Self { to } - } - - pub fn __str__(&self) -> String { - format!("move-result-object {}", self.to) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveResultObject({}))", self.to) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveResultObject { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x0c, - va: self.to, - } - } -} - -/// Move the just caught exception into a register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MoveException { - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl MoveException { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8) -> Self { - Self { to } - } - - pub fn __str__(&self) -> String { - format!("move-exception {}", self.to) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MoveException({}))", self.to) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MoveException { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x0d, - va: self.to, - } - } -} - -/// Return a void method -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ReturnVoid; - -impl Default for ReturnVoid { - fn default() -> Self { - Self::new() - } -} - -#[pymethods] -impl ReturnVoid { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new() -> Self { - Self - } - - pub fn __str__(&self) -> String { - "return-void".into() - } - - pub fn __repr__(&self) -> String { - "Instruction(ReturnVoid)".into() - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ReturnVoid { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format10X { op: 0x0e } - } -} - -/// Return the 32 bits non object value from the method. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct Return { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl Return { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("return {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Return({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Return { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x0f, - va: self.reg, - } - } -} - -/// Return the 64 bits non object value from the method. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ReturnWide { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl ReturnWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("return-wide {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ReturnWide({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ReturnWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x10, - va: self.reg, - } - } -} - -/// Return the object value from the method. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ReturnObject { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl ReturnObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("return-object {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ReturnObject({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ReturnObject { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x11, - va: self.reg, - } - } -} - -/// Move a literal to a register. -/// -/// Can represent several dalvik instructions : -/// -/// const/4 vA #+B -/// const/16 vAA #+BBBB -/// const vAA #+BBBBBBBB -/// const/high 16 vAA #+BBBB0000 -/// -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct Const { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: i32, -} - -#[pymethods] -impl Const { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: i32) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("const {} {}", self.reg, self.lit) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Const({}, {}))", self.reg, self.lit) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Const { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - match (self.reg, self.lit) { - (0..=0b0000_1111, -8..=7) => InsFormat::Format11N { - op: 0x12, - va: self.reg, - b: self.lit as i8, - }, - (_, I16_MIN_AS_I32..=I16_MAX_AS_I32) => InsFormat::Format21S { - op: 0x13, - va: self.reg, - b: self.lit as i16, - }, - (_, lit) if lit % 0x1_0000 == 0 => InsFormat::Format21H { - op: 0x15, - va: self.reg, - b: (self.lit / 0x1_0000) as i16, - }, - (_, _) => InsFormat::Format31I { - op: 0x14, - va: self.reg, - b: self.lit, - }, - } - } -} - -/// Move a literal to a register pair (64bits). -/// -/// Can represent several dalvik instructions : -/// -/// const-wide/16 vAA #+BBBB -/// const-wide/32 vAA #+BBBBBBBB -/// const-wide vAA #+BBBBBBBBBBBBBBBB -/// const-wide/hight 16 vAA #+BBBB000000000000 -/// -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ConstWide { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: i64, -} - -#[pymethods] -impl ConstWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: i64) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("const-wide {} {}", self.reg, self.lit) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ConstWide({}, {}))", self.reg, self.lit) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ConstWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - match self.lit { - I16_MIN_AS_I64..=I16_MAX_AS_I64 => InsFormat::Format21S { - op: 0x16, - va: self.reg, - b: self.lit as i16, - }, - I32_MIN_AS_I64..=I32_MAX_AS_I64 => InsFormat::Format31I { - op: 0x17, - va: self.reg, - b: self.lit as i32, - }, - lit if lit % 0x1_0000_0000_0000 == 0 => InsFormat::Format21H { - op: 0x19, - va: self.reg, - b: (self.lit / 0x1_0000_0000_0000) as i16, - }, - _ => InsFormat::Format51L { - op: 0x18, - va: self.reg, - b: self.lit, - }, - } - } -} - -/// Move a reference to a string in a register. -/// -/// Can represent several dalvik instructions : -/// -/// const-string vAA string@BBBB -/// const-string/jumbo vAA string@BBBBBBBB -/// -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct ConstString { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: DexString, -} - -#[pymethods] -impl ConstString { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: DexString) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("const-string {} \"{}\"", self.reg, self.lit.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ConstString({}, {}))", - self.reg, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - 4 - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - let mut strings = HashSet::new(); - strings.insert(self.lit.clone()); - strings - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ConstString { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, string_idx: usize) -> InsFormat { - match string_idx { - 0..=U16_MAX_AS_USIZE => InsFormat::Format21C { - op: 0x1a, - va: self.reg, - b: string_idx as u16, - }, - _ => InsFormat::Format31C { - op: 0x1b, - va: self.reg, - b: string_idx as u32, - }, - } - } -} - -/// Move a reference to a class in a register. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct ConstClass { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: IdType, -} - -#[pymethods] -impl ConstClass { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: IdType) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("const-class {} \"{}\"", self.reg, self.lit.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ConstClass({}, {}))", - self.reg, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.lit.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.lit.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ConstClass { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, class_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x1c, - va: self.reg, - b: class_idx as u16, - } - } -} - -/// Acquire the monitor for the object in the register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MonitorEnter { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl MonitorEnter { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("monitor-enter {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MonitorEnter({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MonitorEnter { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x1d, - va: self.reg, - } - } -} - -/// Release the monitor for the object in the register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MonitorExit { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl MonitorExit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("monitor-exit {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MonitorExit({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MonitorExit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x1e, - va: self.reg, - } - } -} - -/// Check if the object in the register can be cast to the type. -/// (Raise a `ClassCastException` if not) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct CheckCast { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: IdType, -} - -#[pymethods] -impl CheckCast { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: IdType) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("check-cast {} {}", self.reg, self.lit.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CheckCast({}, {}))", - self.reg, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.lit.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.lit.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CheckCast { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, type_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x1f, - va: self.reg, - b: type_idx as u16, - } - } -} - -/// Check if an object if an instance of a type. -/// (put 1 in the dest register if yes, else 0) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InstanceOf { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub lit: IdType, -} - -#[pymethods] -impl InstanceOf { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, obj: u8, lit: IdType) -> Result { - let ins = Self { dest, obj, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of InstanceOf are indexed on 4 bits, found {}", - self.dest - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of InstanceOf are indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "instance-of {} {} {}", - self.dest, - self.obj, - self.lit.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(InstanceOf({}, {}, {}))", - self.dest, - self.obj, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.lit.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.lit.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InstanceOf { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, type_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x20, - va: self.dest, - vb: self.obj, - c: type_idx as u16, - } - } -} - -/// Get the number of item in an array. -/// (put the lenght in the dest register) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ArrayLength { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, -} - -#[pymethods] -impl ArrayLength { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8) -> Result { - let ins = Self { dest, arr }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of ArrayLength are indexed on 4 bits, found {}", - self.dest - )) - } else if self.arr & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of ArrayLength are indexed on 4 bits, found {}", - self.arr - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("array-length{} {}", self.dest, self.arr,) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ArrayLength({}, {}))", self.dest, self.arr,) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ArrayLength { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x21, - va: self.dest, - vb: self.arr, - } - } -} - -/// Construct a new instance of the indicated type and store a reference to it. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct NewInstance { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub lit: IdType, -} - -#[pymethods] -impl NewInstance { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, lit: IdType) -> Self { - Self { reg, lit } - } - - pub fn __str__(&self) -> String { - format!("new-instance {} {}", self.reg, self.lit.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(NewInstance({}, {}))", - self.reg, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.lit.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.lit.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NewInstance { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, type_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x22, - va: self.reg, - b: type_idx as u16, - } - } -} - -/// Construct a new array of the indicated type and size in size_reg and store a reference to it. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct NewArray { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - pub size_reg: u8, - #[pyo3(get)] - pub lit: IdType, -} - -#[pymethods] -impl NewArray { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, size_reg: u8, lit: IdType) -> Result { - let ins = Self { reg, size_reg, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!( - "new-array {} {} {}", - self.reg, - self.size_reg, - self.lit.__str__() - ) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.reg & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of NewArray are indexed on 4 bits, found {}", - self.reg - )) - } else if self.size_reg & 0b1111_0000 != 0 { - Err(anyhow!( - "The registers of NewArray are indexed on 4 bits, found {}", - self.size_reg - )) - } else { - Ok(()) - } - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(NewArray({}, {}, {}))", - self.reg, - self.size_reg, - self.lit.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.lit.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.lit.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NewArray { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, type_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x23, - va: self.reg, - vb: self.size_reg, - c: type_idx as u16, - } - } -} - -/// Construct a new array of the indicated type and size fill it with the values of the -/// given registers. -/// -/// The elements of the array must fit in 32bits. -/// -/// The registers must either be less to 5 and their number must fit on 4 bits each, or -/// be less than 256, their the number of the smallest must fit on 16 bits and they must -/// be sorted an directly adjascent. -/// -/// The newly created array can be retreived with a move-result-object instruction. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct FilledNewArray { - #[pyo3(get)] - pub type_: IdType, - #[pyo3(get)] - pub reg_values: Vec, -} - -#[pymethods] -impl FilledNewArray { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(type_: IdType, reg_values: Vec) -> Result { - let array = Self { type_, reg_values }; - array.sanity_check()?; - Ok(array) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.reg_values.len(); - for r in self.reg_values.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "filled-new-array instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.reg_values.len() >= 5 { - format!( - "{} .. {}", - self.reg_values[0], - self.reg_values[self.reg_values.len() - 1] - ) - } else { - self.reg_values - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("filled-new-array {{{}}} {}", args, self.type_.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.reg_values.len() >= 5 { - format!( - "{}, ..., {}", - self.reg_values[0], - self.reg_values[self.reg_values.len() - 1] - ) - } else { - self.reg_values - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(", ") - }; - format!( - "Instruction(FilledNewArray([{}], {}))", - args, - self.type_.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.type_.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - types.insert(self.type_.clone()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl FilledNewArray { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self, type_idx: usize) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.reg_values.len(); - for r in self.reg_values.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.reg_values.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.reg_values.len() as u8; - InsFormat::Format35C { - op: 0x24, - a, - vc, - ve, - vd, - vf, - vg, - b: type_idx as u16, - } - } else if consec && len <= 255 { - let a = self.reg_values.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x25, - a, - vc, - b: type_idx as u16, - } - } else { - // Not supposed to happend with a sanitized array - panic!("Invalid NewArrayInstruction {self:?}") - } - } -} - -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct FillArrayData { - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub elt_width: u16, - #[pyo3(get)] - pub data: Vec, -} - -#[pymethods] -impl FillArrayData { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(arr: u8, elt_width: u16, data: Vec) -> Self { - Self { - arr, - elt_width, - data, - } - } - - pub fn __str__(&self) -> String { - let data: String = if self.data.len() / self.elt_width as usize == 0 { - "".into() - } else if self.data.len() / self.elt_width as usize <= 2 { - let mut arr = "".into(); - for (i, v) in self.data.iter().enumerate() { - if i == 0 { - arr += "0x" - } else if i % self.elt_width as usize == 0 { - arr += " 0x" - } - arr += format!("{v:02x}").as_str(); - } - arr - } else { - let mut arr = "0x".into(); - for v in &self.data[..self.elt_width as usize] { - arr += format!("{v:02x}").as_str(); - } - arr += " ... 0x"; - for v in &self.data[self.data.len() - self.elt_width as usize..] { - arr += format!("{v:02x}").as_str(); - } - - arr - }; - format!("fill-array-data {} {}", self.arr, data) - } - - pub fn __repr__(&self) -> String { - let data: String = if self.data.len() / self.elt_width as usize == 0 { - "".into() - } else if self.data.len() / self.elt_width as usize <= 2 { - let mut arr = "".into(); - for (i, v) in self.data.iter().enumerate() { - if i == 0 { - arr += "0x" - } else if i % self.elt_width as usize == 0 { - arr += ", 0x" - } - arr += format!("{v:02x}").as_str(); - } - arr - } else { - let mut arr = "0x".into(); - for v in &self.data[..self.elt_width as usize] { - arr += format!("{v:02x}").as_str(); - } - arr += ", ..., 0x"; - for v in &self.data[self.data.len() - self.elt_width as usize..] { - arr += format!("{v:02x}").as_str(); - } - - arr - }; - format!("Instruction(FillArrayData({}, [{}]))", self.arr, data) - } - - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl FillArrayData { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `data_offset` is the offset to the address where the data are located. - pub fn get_raw_ins(&self, data_offset: i32) -> InsFormat { - InsFormat::Format31T { - op: 0x26, - va: self.arr, - b: data_offset, - } - } -} - -/// Throws the exception in the register. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct Throw { - #[pyo3(get)] - pub reg: u8, -} - -#[pymethods] -impl Throw { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8) -> Self { - Self { reg } - } - - pub fn __str__(&self) -> String { - format!("throw {}", self.reg) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Throw({}))", self.reg) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Throw { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format11X { - op: 0x27, - va: self.reg, - } - } -} - -/// Jump to the label. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct Goto { - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl Goto { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(label: String) -> Self { - Self { label } - } - - pub fn __str__(&self) -> String { - format!("goto {}", self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Goto({}))", self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - 2 - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Goto { - /// Return the raw instruction ([`InsFormat`]). - /// - /// - `branch_offset` is the offset to the address. - /// - `goto_size` is the estimated size of the goto used to compute the offset. - /// It may not be the optimal size, but the instructions of the associtated - /// size will be used, and the offset is expected to fit in the instruction. - /// - /// Possible goto size and associated offset size: - /// - `2`: offset must fit in an i8 - /// - `4`: offset must fit in an i16 - /// - `6`: offset must fit in an i32 - pub fn get_raw_ins(&self, data_offset: i32, goto_size: usize) -> InsFormat { - if goto_size == 2 && (I8_MIN_AS_I32..=I8_MAX_AS_I32).contains(&data_offset) { - InsFormat::Format10T { - op: 0x28, - a: data_offset as i8, - } - } else if goto_size == 4 && (I16_MIN_AS_I32..=I16_MAX_AS_I32).contains(&data_offset) { - InsFormat::Format20T { - op: 0x29, - a: data_offset as i16, - } - } else if goto_size == 6 { - InsFormat::Format30T { - op: 0x2a, - a: data_offset, - } - } else { - panic!("Invalid goto_size and/or data_offset value") - } - } - - /// Return the size of a goto instruction from the goto instruction address and - /// and interval for the branch address. The size will be selected to be the smallest - /// possible size that fit the offset for the worst case scenario. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - /// - /// The address for the intervals are in code address units `u16`. - pub fn size_from_branch_offset_interval( - addr_goto: usize, - min_addr_branch: usize, - max_addr_branch: usize, - ) -> Result { - let worst_offset = if max_addr_branch as i32 - addr_goto as i32 - > addr_goto as i32 - min_addr_branch as i32 - { - max_addr_branch as i32 - addr_goto as i32 - } else { - min_addr_branch as i32 - addr_goto as i32 - }; - match worst_offset { - I8_MIN_AS_I32..=I8_MAX_AS_I32 => Ok(2), - I16_MIN_AS_I32..=I16_MAX_AS_I32 => Ok(4), - _ => Ok(6), - } - } -} - -/// Jump to a label depending on the value of a register. If the value -/// is not matched, continue the extecution at the next instruction. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct Switch { - #[pyo3(get)] - pub reg: u8, - #[pyo3(get)] - #[serde(with = "hashmap_vectorize")] - pub branches: HashMap, -} - -#[pymethods] -impl Switch { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(reg: u8, branches: HashMap) -> Self { - Self { reg, branches } - } - - pub fn __str__(&self) -> String { - let mut branches_str: String = "".into(); - let mut branches: Vec<_> = self.branches.iter().collect(); - branches.sort_by_key(|(key, _)| **key); - for (key, label) in branches { - branches_str += &format!("\n {key}: goto {label}"); - } - format!("switch {} {}", self.reg, branches_str) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Switch({}, ...))", self.reg) - } - - /// Test if the swith is packed of pack - pub fn is_packed(&self) -> bool { - let mut last = None; - let mut keys = self.branches.keys().collect::>(); - keys.sort(); - for key in keys.into_iter().cloned() { - if let Some(last) = &last { - if *last != key - 1 { - return false; - } - } - last = Some(key); - } - true - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl Switch { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `table_offset` is the offset to the address where the branche table located. - pub fn get_raw_ins(&self, data_offset: i32) -> InsFormat { - InsFormat::Format31T { - op: if self.is_packed() { 0x2b } else { 0x2c }, - va: self.reg, - b: data_offset, - } - } -} -/// Store the result of the comparison between the registers. -/// -/// - b < c: a = -1 -/// - b == c: a = 0 -/// - b > c : a = 1 -/// - b == c == Nan: a = -1 -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct CmpLFloat { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub c: u8, -} - -#[pymethods] -impl CmpLFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("cmpl-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CmpLFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CmpLFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x2d, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Store the result of the comparison between the registers. -/// -/// - b < c: a = -1 -/// - b == c: a = 0 -/// - b > c : a = 1 -/// - b == c == Nan: a = 1 -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct CmpGFloat { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub c: u8, -} - -#[pymethods] -impl CmpGFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("cmpg-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CmpGFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CmpGFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x2e, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Store the result of the comparison between the registers. -/// -/// - b < c: a = -1 -/// - b == c: a = 0 -/// - b > c : a = 1 -/// - b == c == Nan: a = -1 -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct CmpLDouble { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub c: u8, -} - -#[pymethods] -impl CmpLDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("cmpl-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CmpLDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CmpLDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x2f, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Store the result of the comparison between the registers. -/// -/// - b < c: a = -1 -/// - b == c: a = 0 -/// - b > c : a = 1 -/// - b == c == Nan: a = 1 -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct CmpGDouble { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub c: u8, -} - -#[pymethods] -impl CmpGDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("cmpg-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CmpGDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CmpGDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x30, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Store the result of the comparison between the registers. -/// -/// - b < c: a = -1 -/// - b == c: a = 0 -/// - b > c : a = 1 -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct CmpLong { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub c: u8, -} - -#[pymethods] -impl CmpLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("cmp-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(CmpLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl CmpLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x31, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Jump to the label if a == b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfEq { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfEq { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-eq uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-eq uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-eq {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfEq({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} -impl IfEq { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x32, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a != b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfNe { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfNe { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-neq uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-neq uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-neq {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfNe({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfNe { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x33, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a < b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfLt { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfLt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-lt uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-lt uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-lt {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfLt({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfLt { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x34, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a >= b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfGe { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfGe { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-ge uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-ge uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-ge {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfGe({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfGe { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x35, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a > b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfGt { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfGt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-gt uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-gt uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-gt {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfGt({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfGt { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x36, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a <= b -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfLe { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub b: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfLe { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, b: u8, label: String) -> Result { - let ins = Self { a, b, label }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.a & 0b1111_0000 != 0 { - Err(anyhow!( - "if-le uses registers indexed on 4 bits, found {}", - self.a - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "if-le uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("if-le {} {} {}", self.a, self.b, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfLe({}, {}, {}))", self.a, self.b, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfLe { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format22T { - op: 0x37, - va: self.a, - vb: self.b, - c: branch_offset, - } - } -} - -/// Jump to the label if a == 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfEqZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfEqZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-eqz {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfEqZ({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfEqZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x38, - va: self.a, - b: branch_offset, - } - } -} - -/// Jump to the label if a != 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfNeZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfNeZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-neq {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfNe({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfNeZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x39, - va: self.a, - b: branch_offset, - } - } -} - -/// Jump to the label if a < 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfLtZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfLtZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-lt {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfLt({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfLtZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x3a, - va: self.a, - b: branch_offset, - } - } -} - -/// Jump to the label if a >= 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfGeZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfGeZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-ge {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfGe({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfGeZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x3b, - va: self.a, - b: branch_offset, - } - } -} - -/// Jump to the label if a > 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfGtZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfGtZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-gt {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfGt({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfGtZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x3c, - va: self.a, - b: branch_offset, - } - } -} - -/// Jump to the label if a <= 0 -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IfLeZ { - #[pyo3(get)] - pub a: u8, - #[pyo3(get)] - pub label: String, -} - -#[pymethods] -impl IfLeZ { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(a: u8, label: String) -> Result { - let ins = Self { a, label }; - Ok(ins) - } - - pub fn __str__(&self) -> String { - format!("if-le {} {}", self.a, self.label) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IfLe({}, {}))", self.a, self.label) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IfLeZ { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `branch_offset` is the offset to the address to jump to if - /// the test is true. - pub fn get_raw_ins(&self, branch_offset: i16) -> InsFormat { - InsFormat::Format21T { - op: 0x3d, - va: self.a, - b: branch_offset, - } - } -} - -/// Put the value at `arr[idx]` in register dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGet { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGet { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGet({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGet { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x44, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the value at `arr[idx]` in register pair dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetWide { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-wide {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetWide({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x45, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the reference at `arr[idx]` in register (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetObject { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-object {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetObject({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetObject { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x46, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the boolean at `arr[idx]` in register dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetBoolean { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-boolean {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetBoolean({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetBoolean { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x47, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the byte at `arr[idx]` in register dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetByte { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-byte {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetByte({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetByte { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x48, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the char at `arr[idx]` in register dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetChar { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-char {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetChar({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetChar { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x49, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the short at `arr[idx]` in register dest (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AGetShort { - #[pyo3(get)] - pub dest: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl AGetShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, arr: u8, idx: u8) -> Self { - Self { dest, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aget-short {} {} {}", self.dest, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AGetShort({}, {}, {}))", - self.dest, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AGetShort { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4a, - va: self.dest, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the value of register 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APut { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APut { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APut({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APut { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4b, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the value of the register pair 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutWide { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-wide {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutWide({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutWide { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4c, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the object reference in 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutObject { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-object {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutObject({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutObject { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4d, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the boolean in 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutBoolean { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-boolean {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutBoolean({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutBoolean { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4e, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the byte in 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutByte { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-byte {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutByte({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutByte { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x4f, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the char in 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutChar { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-char {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutChar({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutChar { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x50, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the short in 'from' in `arr[idx]` (all values are in registers) -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct APutShort { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub arr: u8, - #[pyo3(get)] - pub idx: u8, -} - -#[pymethods] -impl APutShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, arr: u8, idx: u8) -> Self { - Self { from, arr, idx } - } - - pub fn __str__(&self) -> String { - format!("aput-short {} {} {}", self.from, self.arr, self.idx) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(APutShort({}, {}, {}))", - self.from, self.arr, self.idx - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl APutShort { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x51, - va: self.from, - vb: self.arr, - vc: self.idx, - } - } -} - -/// Put the value in 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGet { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGet { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("iget {} {} {}", self.to, self.obj, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGet({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGet { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x52, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the value in the register pair 'to' in the instance field 'field' of 'obj' ('to' -/// and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetWide { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-wide uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-wide uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-wide {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetWide({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetWide { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x53, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the object reference 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetObject { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-object uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-object uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-object {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetObject({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetObject { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x54, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the boolean in 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetBoolean { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-boolean uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-boolean uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-boolean {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetBoolean({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetBoolean { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x55, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the byte in 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetByte { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-byte uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-byte uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-byte {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetByte({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetByte { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x56, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the char in 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetChar { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-char uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-char uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-char {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetChar({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetChar { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x57, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the short in 'to' in the instance field 'field' of 'obj' ('to' and 'obj' are register) -/// -/// The registers 'to' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IGetShort { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IGetShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, obj: u8, field: IdField) -> Result { - let ins = Self { to, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.to & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-short uses registers indexed on 4 bits, found {}", - self.to - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iget-short uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iget-short {} {} {}", - self.to, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IGetShort({}, {}, {}))", - self.to, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IGetShort { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x58, - va: self.to, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the value in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPut { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPut { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("iput {} {} {}", self.from, self.obj, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPut({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPut { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x59, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the value in the instance field 'field' of 'obj' in the register pair 'from' -/// ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutWide { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-wide uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-wide uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-wide {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutWide({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutWide { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5a, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the object reference in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutObject { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-object uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-object uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-object {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutObject({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutObject { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5b, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the boolean in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutBoolean { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-boolean uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-boolean uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-boolean {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutBoolean({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutBoolean { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5c, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the byte in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutByte { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-byte uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-byte uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-byte {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutByte({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutByte { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5d, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the char in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutChar { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-char uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-char uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-char {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutChar({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutChar { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5e, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the short in the instance field 'field' of 'obj' in 'from' ('from' and 'obj' are register) -/// -/// The registers 'from' and 'obj' are idexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct IPutShort { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub obj: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl IPutShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, obj: u8, field: IdField) -> Result { - let ins = Self { from, obj, field }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.from & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-short uses registers indexed on 4 bits, found {}", - self.from - )) - } else if self.obj & 0b1111_0000 != 0 { - Err(anyhow!( - "iput-short uses registers indexed on 4 bits, found {}", - self.obj - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!( - "iput-short {} {} {}", - self.from, - self.obj, - self.field.__str__() - ) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(IPutShort({}, {}, {}))", - self.from, - self.obj, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IPutShort { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format22C { - op: 0x5f, - va: self.from, - vb: self.obj, - c: field_idx as u16, - } - } -} - -/// Put the value in 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGet { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGet { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SGet({}, {}))", self.to, self.field.__repr__()) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGet { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x60, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the value in the register pair 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetWide { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-wide {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetWide({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetWide { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x61, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the object reference 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetObject { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-object {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetObject({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetObject { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x62, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the boolean in 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetBoolean { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-boolean {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetBoolean({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetBoolean { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x63, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the byte in 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetByte { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-byte {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetByte({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetByte { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x64, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the char in 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetChar { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-char {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetChar({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetChar { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x65, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the short in 'to' in the static field 'field' ('to' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SGetShort { - #[pyo3(get)] - pub to: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SGetShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, field: IdField) -> Self { - Self { to, field } - } - - pub fn __str__(&self) -> String { - format!("sget-short {} {}", self.to, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SGetShort({}, {}))", - self.to, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SGetShort { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x66, - va: self.to, - b: field_idx as u16, - } - } -} - -/// Put the value in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPut { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPut { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPut({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPut { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x67, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the value in the static field 'field' in the register pair 'from' -/// ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutWide { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutWide { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-wide {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutWide({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutWide { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x68, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the object reference in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutObject { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutObject { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-object {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutObject({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutObject { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x69, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the boolean in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutBoolean { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutBoolean { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-boolean {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutBoolean({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutBoolean { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x6a, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the byte in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutByte { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-byte {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutByte({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutByte { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x6b, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the char in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutChar { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-char {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutChar({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutChar { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x6c, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Put the short in the static field 'field' in 'from' ('from' is a register) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct SPutShort { - #[pyo3(get)] - pub from: u8, - #[pyo3(get)] - pub field: IdField, -} - -#[pymethods] -impl SPutShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(from: u8, field: IdField) -> Self { - Self { from, field } - } - - pub fn __str__(&self) -> String { - format!("sput-short {} {}", self.from, self.field.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SPutShort({}, {}))", - self.from, - self.field.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.field.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.field.get_all_types() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - let mut fields = HashSet::new(); - fields.insert(self.field.clone()); - fields - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SPutShort { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `field_idx` is the index of the field refered to. - pub fn get_raw_ins(&self, field_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0x6d, - va: self.from, - b: field_idx as u16, - } - } -} - -/// Call a normal virtual method. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokeVirtual { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeVirtual { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { - let invoke = Self { method, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-virtual instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-virtual {{{}}} {}", args, self.method.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeVirtual({}, {}))", - args, - self.method.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.method.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.method.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.method.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokeVirtual { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `method_idx` is the index of the refered method. - pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0x6e, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x74, - a, - vc, - b: meth_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Call the closest superclass's virtual method of a non interface class. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokeSuper { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeSuper { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { - let invoke = Self { method, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-super instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-super {{{}}} {}", args, self.method.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeSuper({}, {}))", - args, - self.method.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.method.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.method.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.method.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokeSuper { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `method_idx` is the index of the refered method. - pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0x6f, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x75, - a, - vc, - b: meth_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Call a direct method (non static non overridable, like private). -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokeDirect { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeDirect { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { - let invoke = Self { method, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-direct instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-direct {{{}}} {}", args, self.method.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeDirect({}, {}))", - args, - self.method.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.method.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.method.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.method.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokeDirect { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `method_idx` is the index of the refered method. - pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0x70, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x76, - a, - vc, - b: meth_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Call a static method. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokeStatic { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeStatic { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { - let invoke = Self { method, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-static instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-static {{{}}} {}", args, self.method.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeStatic({}, {}))", - args, - self.method.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.method.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.method.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.method.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokeStatic { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `method_idx` is the index of the refered method. - pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0x71, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x77, - a, - vc, - b: meth_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Call a interface method (method from an interface on an object whose class is unknown) -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokeInterface { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeInterface { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, args: Vec) -> Result { - let invoke = Self { method, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-interface instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-interface {{{}}} {}", args, self.method.__str__()) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeInterface({}, {}))", - args, - self.method.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.method.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.method.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.method.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokeInterface { - /// Return the raw instruction ([`InsFormat`]). - /// - /// `method_idx` is the index of the refered method. - pub fn get_raw_ins(&self, meth_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0x72, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0x78, - a, - vc, - b: meth_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Put -val in dest. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NegInt { - dest: u8, - val: u8, -} - -#[pymethods] -impl NegInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-int uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-int uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("neg-int {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NegInt({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NegInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x7b, - va: self.dest, - vb: self.val, - } - } -} - -/// Put ~val in dest -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NotInt { - dest: u8, - val: u8, -} - -#[pymethods] -impl NotInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "not-int uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "not-int uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("not-int {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NotInt({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NotInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x7c, - va: self.dest, - vb: self.val, - } - } -} - -/// Put -val in dest. dest and val are pair registers. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NegLong { - dest: u8, - val: u8, -} - -#[pymethods] -impl NegLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-long uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-long uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("neg-long {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NegLong({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NegLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x7d, - va: self.dest, - vb: self.val, - } - } -} - -/// Put ~val in dest. dest and val are pair registers. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NotLong { - dest: u8, - val: u8, -} - -#[pymethods] -impl NotLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "not-long uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "not-long uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("not-long {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NotLong({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NotLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x7e, - va: self.dest, - vb: self.val, - } - } -} - -/// Put -val in dest. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NegFloat { - dest: u8, - val: u8, -} - -#[pymethods] -impl NegFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-float uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-float uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("neg-float {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NegFloat({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NegFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x7f, - va: self.dest, - vb: self.val, - } - } -} - -/// Put -val in dest. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct NegDouble { - dest: u8, - val: u8, -} - -#[pymethods] -impl NegDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-double uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "neg-double uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("neg-double {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(NegDouble({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl NegDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x80, - va: self.dest, - vb: self.val, - } - } -} - -/// Convert copy val to dest an convert to long. -/// -/// TODO: dest is probably a pair register, but is val to? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToLong { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-long uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-long uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-long {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToLong({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x81, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the integer value to a float. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToFloat { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-float uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-float uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-float {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToFloat({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x82, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the integer value to a double -/// -/// TODO: dest is probably a pair register, but is val to? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToDouble { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-double uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-double uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-double {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToDouble({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x83, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the long value to an integer. -/// -/// TODO: val is probably a pair register, but is dest to? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct LongToInt { - dest: u8, - val: u8, -} - -#[pymethods] -impl LongToInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-int uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-int uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("long-to-int {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(LongToInt({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl LongToInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x84, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the long value to a float. -/// -/// TODO: val is probably a pair register, but is dest to? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct LongToFloat { - dest: u8, - val: u8, -} - -#[pymethods] -impl LongToFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-float uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-float uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("long-to-float {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(LongToFloat({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl LongToFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x85, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the long value to a double. -/// -/// dest and val are pair registers. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct LongToDouble { - dest: u8, - val: u8, -} - -#[pymethods] -impl LongToDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-double uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "long-to-double uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("long-to-double {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(LongToDouble({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl LongToDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x86, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the float value to an integer. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct FloatToInt { - dest: u8, - val: u8, -} - -#[pymethods] -impl FloatToInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-int uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-int uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("float-to-int {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(FloatToInt({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl FloatToInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x87, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the float value to a long. -/// -/// TODO: dest is probably a pair register, but is val too? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct FloatToLong { - dest: u8, - val: u8, -} - -#[pymethods] -impl FloatToLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-long uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-long uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("float-to-long {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(FloatToLong({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl FloatToLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x88, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the float value to a double. -/// -/// TODO: dest is probably a pair register, but is val too? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct FloatToDouble { - dest: u8, - val: u8, -} - -#[pymethods] -impl FloatToDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-double uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "float-to-double uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("float-to-double {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(FloatToDouble({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl FloatToDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x89, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the double value to an integer. -/// -/// TODO: val is probably a pair register, but is dest too? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DoubleToInt { - dest: u8, - val: u8, -} - -#[pymethods] -impl DoubleToInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-int uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-int uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("double-to-int {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DoubleToInt({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DoubleToInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8a, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the double value to a long. -/// -/// val and dest are pair registers. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DoubleToLong { - dest: u8, - val: u8, -} - -#[pymethods] -impl DoubleToLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-long uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-long uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("double-to-long {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DoubleToLong({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DoubleToLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8b, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the double value to a float. -/// -/// TODO: val is probably a pair register, but is dest too? -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DoubleToFloat { - dest: u8, - val: u8, -} - -#[pymethods] -impl DoubleToFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-float uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "double-to-float uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("double-to-float {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DoubleToFloat({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DoubleToFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8c, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the integer value to a byte. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToByte { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToByte { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-byte uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-byte uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-byte {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToByte({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToByte { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8d, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the integer value to a char. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToChar { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToChar { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-char uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-char uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-char {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToChar({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToChar { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8e, - va: self.dest, - vb: self.val, - } - } -} - -/// Copy val to dest and convert the integer value to a short. -/// -/// `dest` and `val` are registered indexed on 4 bits. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct IntToShort { - dest: u8, - val: u8, -} - -#[pymethods] -impl IntToShort { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, val: u8) -> Result { - let ins = Self { dest, val }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-short uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.val & 0b1111_0000 != 0 { - Err(anyhow!( - "int-to-short uses registers indexed on 4 bits, found {}", - self.val - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("int-to-short {} {}", self.dest, self.val) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(IntToShort({}, {}))", self.dest, self.val) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl IntToShort { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0x8f, - va: self.dest, - vb: self.val, - } - } -} - -/// Put a + b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AddInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("add-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AddInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x90, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a - b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl SubInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("sub-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SubInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x91, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a * b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl MulInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("mul-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MulInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x92, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a / b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl DivInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("div-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DivInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x93, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a % b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl RemInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("rem-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(RemInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x94, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a & b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AndInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AndInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("and-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AndInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AndInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x95, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a | b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct OrInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl OrInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("or-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(OrInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl OrInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x96, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a ^ b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct XorInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl XorInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("xor-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(XorInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl XorInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x97, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a << b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShlInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl ShlInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("shl-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShlInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShlInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x98, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a >> b (signed) in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShrInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl ShrInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("shr-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShrInt({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShrInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x99, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a >> b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct UshrInt { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl UshrInt { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("ushr-int {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(UshrInt({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl UshrInt { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9a, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a + b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AddLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("add-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AddLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9b, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a - b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl SubLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("sub-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SubLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9c, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a * b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl MulLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("mul-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(MulLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9d, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a / b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl DivLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("div-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(DivLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9e, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a % b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl RemLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("rem-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(RemLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0x9f, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a & b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AndLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AndLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("and-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AndLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AndLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa0, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a | b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct OrLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl OrLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("or-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(OrLong({}, {}, {}))", self.dest, self.b, self.c) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl OrLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa1, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a ^ b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct XorLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl XorLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("xor-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(XorLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl XorLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa2, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a << b in dest. -/// -/// dest, and b are register pairs, and c is a single register -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShlLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl ShlLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("shl-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ShlLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShlLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa3, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a >> b (signed) in dest. -/// -/// dest, and b are register pairs, and c is a single register -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShrLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl ShrLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("shr-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ShrLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShrLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa4, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a >> b in dest. -/// -/// dest, and b are register pairs, and c is a single register -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct UshrLong { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl UshrLong { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("ushr-long {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(UshrLong({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl UshrLong { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa5, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a + b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddFloat { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AddFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("add-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AddFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa6, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a - b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubFloat { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl SubFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("sub-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SubFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa7, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a * b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulFloat { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl MulFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("mul-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(MulFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa8, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a / b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivFloat { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl DivFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("div-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(DivFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xa9, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a % b in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemFloat { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl RemFloat { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("rem-float {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(RemFloat({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemFloat { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xaa, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a + b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddDouble { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl AddDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("add-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AddDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xab, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a - b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubDouble { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl SubDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("sub-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(SubDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xac, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a * b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulDouble { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl MulDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("mul-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(MulDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xad, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a / b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivDouble { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl DivDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("div-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(DivDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xae, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put a % b in dest. -/// -/// dest, b and c are register pairs -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemDouble { - dest: u8, - b: u8, - c: u8, -} - -#[pymethods] -impl RemDouble { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, c: u8) -> Self { - Self { dest, b, c } - } - - pub fn __str__(&self) -> String { - format!("rem-double {} {} {}", self.dest, self.b, self.c) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(RemDouble({}, {}, {}))", - self.dest, self.b, self.c - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemDouble { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format23X { - op: 0xaf, - va: self.dest, - vb: self.b, - vc: self.c, - } - } -} - -/// Put dest + b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AddInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "add-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "add-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("add-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AddInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb0, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest - b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl SubInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("sub-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SubInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb1, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest * b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl MulInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("mul-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MulInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb2, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest / b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl DivInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "div-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "div-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("div-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DivInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb3, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest % b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl RemInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rem-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(RemInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb4, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest & b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AndInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AndInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "and-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "and-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("and-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AndInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AndInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb5, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest | b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct OrInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl OrInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "or-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "or-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("or-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(OrInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl OrInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb6, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest ^ b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct XorInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl XorInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "xor-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "xor-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("xor-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(XorInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl XorInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb7, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest << b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShlInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl ShlInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "shl-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "shl-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("shl-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShlInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShlInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb8, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest >> b (signed) in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShrInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl ShrInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "shr-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "shr-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("shr-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShrInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShrInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xb9, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest >> b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct UshrInt2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl UshrInt2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "ushr-int/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "ushr-int/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("ushr-int/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(UshrInt2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl UshrInt2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xba, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest + b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AddLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "add-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "add-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("add-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AddLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xbb, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest - b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl SubLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("sub-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SubLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xbc, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest * b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl MulLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("mul-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MulLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xbd, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest / b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl DivLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "div-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "div-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("div-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DivLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xbe, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest % b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl RemLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rem-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(RemLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xbf, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest & b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AndLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AndLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "and-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "and-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("and-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AndLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AndLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc0, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest | b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct OrLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl OrLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "or-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "or-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("or-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(OrLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl OrLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc1, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest ^ b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct XorLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl XorLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "xor-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "xor-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("xor-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(XorLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl XorLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc2, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest << b in dest. -/// -/// dest is a register pair, and b is a single register -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShlLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl ShlLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "shl-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "shl-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("shl-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShlLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShlLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc3, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest >> b (signed) in dest. -/// -/// dest is a register pair, and b is a single register -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShrLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl ShrLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "shr-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "shr-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("shr-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(ShrLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShrLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc4, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest >> b in dest. -/// -/// dest is a register pair, and b is a single register -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct UshrLong2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl UshrLong2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "ushr-long/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "ushr-long/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("ushr-long/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(UshrLong2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl UshrLong2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc5, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest + b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddFloat2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AddFloat2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "add-float/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "add-float/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("add-float/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AddFloat2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddFloat2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc6, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest - b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubFloat2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl SubFloat2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-float/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-float/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("sub-float/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SubFloat2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubFloat2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc7, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest * b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulFloat2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl MulFloat2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-float/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-float/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("mul-float/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MulFloat2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulFloat2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc8, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest / b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivFloat2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl DivFloat2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "div-float/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "div-float/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("div-float/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DivFloat2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivFloat2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xc9, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest % b in dest. -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemFloat2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl RemFloat2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-float/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-float/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rem-float/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(RemFloat2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemFloat2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xca, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest + b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddDouble2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl AddDouble2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "add-double/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "add-double/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("add-double/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(AddDouble2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddDouble2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xcb, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest - b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct SubDouble2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl SubDouble2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-double/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "sub-double/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("sub-double/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(SubDouble2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl SubDouble2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xcc, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest * b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulDouble2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl MulDouble2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-double/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "mul-double/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("mul-double/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(MulDouble2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulDouble2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xcd, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest / b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivDouble2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl DivDouble2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "div-double/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "div-double/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("div-double/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(DivDouble2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivDouble2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xce, - va: self.dest, - vb: self.b, - } - } -} - -/// Put dest % b in dest. -/// -/// dest and b are register pairs -/// -/// `dest` and `b` are registers indexed on 4 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemDouble2Addr { - dest: u8, - b: u8, -} - -#[pymethods] -impl RemDouble2Addr { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8) -> Result { - let ins = Self { dest, b }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - if self.dest & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-double/2addr uses registers indexed on 4 bits, found {}", - self.dest - )) - } else if self.b & 0b1111_0000 != 0 { - Err(anyhow!( - "rem-double/2addr uses registers indexed on 4 bits, found {}", - self.b - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rem-double/2addr {} {}", self.dest, self.b) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(RemDouble2Addr({}, {}))", self.dest, self.b) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemDouble2Addr { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format12X { - op: 0xcf, - va: self.dest, - vb: self.b, - } - } -} - -/// Put b + lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AddIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl AddIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "add-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (add-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (add-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("add-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AddIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AddIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "add-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (add-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (add-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xd8, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd0, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put lit - b in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RsubIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl RsubIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "rsub-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (rsub-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (rsub-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rsub-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(RsubIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RsubIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "sub-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (sub-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (sub-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xd9, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd1, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b * lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct MulIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl MulIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "mul-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (mul-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (mul-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("mul-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(MulIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl MulIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "mul-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (mul-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (mul-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xda, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd2, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b / lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct DivIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl DivIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "div-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (div-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (div-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("div-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(DivIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl DivIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "div-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (div-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (div-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xdb, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd3, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b % lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct RemIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl RemIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "rem-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (rem-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (rem-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("rem-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(RemIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl RemIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "rem-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (rem-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (rem-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xdc, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd4, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b & lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct AndIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl AndIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "and-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (and-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (and-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("and-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(AndIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl AndIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "and-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (and-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (and-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xdd, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd5, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b | lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct OrIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl OrIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "or-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (or-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (or-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("or-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(OrIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl OrIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "or-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (or-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (or-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xde, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd6, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b ^ lit in dest. -/// -/// Either `dest` and `b` are registers indexed on 4 bits and lit is encoded in 16 bits -/// or `dest` and `b` are registers indexed on 8 bits and lit is encoded in 8 bits -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct XorIntLit { - dest: u8, - b: u8, - lit: i16, -} - -#[pymethods] -impl XorIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i16) -> Result { - let ins = Self { dest, b, lit }; - ins.sanity_check()?; - Ok(ins) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - Err(anyhow!( - "xor-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (xor-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (xor-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, - self.b, - self.lit - )) - } else { - Ok(()) - } - } - - pub fn __str__(&self) -> String { - format!("xor-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(XorIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl XorIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - let mut reg_on_4_bit = true; - let mut lit_on_8_bits = true; - if self.dest & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.b & 0b1111_0000 != 0 { - reg_on_4_bit = false; - } - if self.lit < I8_MIN_AS_I16 || self.lit > I8_MAX_AS_I16 { - lit_on_8_bits = false; - } - if !reg_on_4_bit && !lit_on_8_bits { - // Should not happen on a sanitized op - panic!( - "xor-int/lit uses either registers indexed on 4 bits, and a literal \ - encoded on 16 bits (xor-int/lit16), or registers indexed on 8 bits and \ - a literal encoded on 8 bits (xor-int/lit8). Found reg {} and {}, and lit \ - {}", - self.dest, self.b, self.lit - ) - } else if lit_on_8_bits { - InsFormat::Format22B { - op: 0xdf, - va: self.dest, - vb: self.b, - c: self.lit as i8, - } - } else { - InsFormat::Format22S { - op: 0xd7, - va: self.dest, - vb: self.b, - c: self.lit, - } - } - } -} - -/// Put b << lit in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShlIntLit { - dest: u8, - b: u8, - lit: i8, -} - -#[pymethods] -impl ShlIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i8) -> Self { - Self { dest, b, lit } - } - - pub fn __str__(&self) -> String { - format!("shl-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ShlIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShlIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format22B { - op: 0xe0, - va: self.dest, - vb: self.b, - c: self.lit, - } - } -} - -/// Put b >> lit (signed) in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct ShrIntLit { - dest: u8, - b: u8, - lit: i8, -} - -#[pymethods] -impl ShrIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i8) -> Self { - Self { dest, b, lit } - } - - pub fn __str__(&self) -> String { - format!("shr-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ShrIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ShrIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format22B { - op: 0xe1, - va: self.dest, - vb: self.b, - c: self.lit, - } - } -} - -/// Put b >> lit in dest. -#[pyclass] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] -pub struct UshrIntLit { - dest: u8, - b: u8, - lit: i8, -} - -#[pymethods] -impl UshrIntLit { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(dest: u8, b: u8, lit: i8) -> Self { - Self { dest, b, lit } - } - - pub fn __str__(&self) -> String { - format!("ushr-int/lit {} {} {}", self.dest, self.b, self.lit) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(UshrIntLit({}, {}, {}))", - self.dest, self.b, self.lit - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - self.get_raw_ins().size() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl UshrIntLit { - /// Return the raw instruction ([`InsFormat`]). - pub fn get_raw_ins(&self) -> InsFormat { - InsFormat::Format22B { - op: 0xe2, - va: self.dest, - vb: self.b, - c: self.lit, - } - } -} - -/// Call a polymorphic method. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct InvokePolymorphic { - #[pyo3(get)] - pub method: IdMethod, - #[pyo3(get)] - pub proto: IdMethodType, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokePolymorphic { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(method: IdMethod, proto: IdMethodType, args: Vec) -> Result { - let invoke = Self { - method, - proto, - args, - }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-polymorphic instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "invoke-polymorphic {{{}}} {} {}", - args, - self.method.__str__(), - self.proto.__str__() - ) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokePolymorphic({}, {}, {}))", - args, - self.method.__str__(), - self.proto.__str__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 8 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - let mut strings = self.method.get_all_strings(); - strings.extend(self.proto.get_all_strings()); - strings - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = self.method.get_all_types(); - types.extend(self.proto.get_all_types()); - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - let mut protos = self.method.get_all_protos(); - protos.insert(self.proto.clone()); - protos - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - let mut methods = HashSet::new(); - methods.insert(self.method.clone()); - methods - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl InvokePolymorphic { - /// Return the raw instruction ([`InsFormat`]). - /// - /// - `method_idx` is the index of the refered method. - /// - `proto_idx` is the index of the protoype used. - pub fn get_raw_ins(&self, meth_idx: u16, proto_idx: u16) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format45CC { - op: 0xfa, - a, - vc, - ve, - vd, - vf, - vg, - b: meth_idx, - h: proto_idx, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format4RCC { - op: 0xfb, - a, - vc, - b: meth_idx, - h: proto_idx, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Invoke a method from a call site. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct InvokeCustom { - #[pyo3(get)] - pub call_site: CallSite, - #[pyo3(get)] - pub args: Vec, -} - -#[pymethods] -impl InvokeCustom { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(call_site: CallSite, args: Vec) -> Result { - let invoke = Self { call_site, args }; - invoke.sanity_check()?; - Ok(invoke) - } - - pub fn sanity_check(&self) -> Result<()> { - let mut last = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if (four_bites && len <= 5) || (consec && len <= 255) { - Ok(()) - } else { - Err(anyhow!( - "invoke-custom instruction must either use 5 or \ - less register indexed on 4 bites or less than 255 \ - consecutive registers" - )) - } - } - - pub fn __str__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!("invoke-custom {{{}}} {}", args, self.call_site.__str__(),) - } - - pub fn __repr__(&self) -> String { - let args = if self.args.len() >= 5 { - format!("{} .. {}", self.args[0], self.args[self.args.len() - 1]) - } else { - self.args - .iter() - .map(|v| format!("{v}")) - .collect::>() - .join(" ") - }; - format!( - "Instruction(InvokeCustom({}, {}))", - args, - self.call_site.__str__(), - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 6 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.call_site.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.call_site.get_all_types() - } - - /// Return all strings referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.call_site.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - self.call_site.get_all_field_ids() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - self.call_site.get_all_method_ids() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - self.call_site.get_all_method_handles() - } -} - -impl InvokeCustom { - /// Return the raw instruction ([`InsFormat`]). - /// - /// - `call_site_idx` is the index of the call site. - pub fn get_raw_ins(&self, call_site_idx: usize) -> InsFormat { - let mut last = None; - let mut first = None; - let mut consec = true; - let mut four_bites = true; - let len = self.args.len(); - for r in self.args.iter().cloned() { - if first.is_none() { - first = Some(r); - } - if let Some(last) = last { - if r != last + 1 { - consec = false; - } - } - if r & 0b1111_0000 != 0 { - four_bites = false; - } - last = Some(r); - } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in self.args.iter().cloned() { - regs.push(reg); - } - while regs.len() != 5 { - regs.push(0); - } - let [vc, vd, ve, vf, vg]: [u8; 5] = regs - .into_iter() - .map(|r| r as u8) - .collect::>() - .try_into() - .ok() - .unwrap(); - let a = self.args.len() as u8; - InsFormat::Format35C { - op: 0xfc, - a, - vc, - ve, - vd, - vf, - vg, - b: call_site_idx as u16, - } - } else if consec && len <= 255 { - let a = self.args.len() as u8; - let vc = if let Some(vc) = first { vc } else { 0 }; - InsFormat::Format3RC { - op: 0xfd, - a, - vc, - b: call_site_idx as u16, - } - } else { - // Not supposed to happend with a sanitized invoke - panic!("Invalid Invoke instruction {self:?}") - } - } -} - -/// Put contents reference to the method handle in the register. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct ConstMethodHandle { - #[pyo3(get)] - pub handle: MethodHandle, - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl ConstMethodHandle { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, handle: MethodHandle) -> Self { - Self { to, handle } - } - - pub fn __str__(&self) -> String { - format!("const-method-handle {} {}", self.to, self.handle.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ConstMethodHandle({}, {}))", - self.to, - self.handle.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.handle.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.handle.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - self.handle.get_all_protos() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - self.handle.get_all_field_ids() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - self.handle.get_all_method_ids() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - self.handle.get_all_method_handles() - } -} - -impl ConstMethodHandle { - /// Return the raw instruction ([`InsFormat`]). - /// - /// - `method_handle_idx` is the index of the method handle. - pub fn get_raw_ins(&self, method_handle_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0xfe, - va: self.to, - b: method_handle_idx as u16, - } - } -} - -/// Put contents reference to the prototype in the register. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct ConstMethodType { - #[pyo3(get)] - pub proto: IdMethodType, - #[pyo3(get)] - pub to: u8, -} - -#[pymethods] -impl ConstMethodType { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(to: u8, proto: IdMethodType) -> Self { - Self { to, proto } - } - - pub fn __str__(&self) -> String { - format!("const-method-type {} {}", self.to, self.proto.__str__()) - } - - pub fn __repr__(&self) -> String { - format!( - "Instruction(ConstMethodType({}, {}))", - self.to, - self.proto.__repr__() - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 4 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - self.proto.get_all_strings() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - self.proto.get_all_types() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - let mut protos = HashSet::new(); - protos.insert(self.proto.clone()); - protos - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -impl ConstMethodType { - /// Return the raw instruction ([`InsFormat`]). - /// - /// - `proto_idx` is the index of the method protoype. - pub fn get_raw_ins(&self, proto_idx: usize) -> InsFormat { - InsFormat::Format21C { - op: 0xff, - va: self.to, - b: proto_idx as u16, - } - } -} - -/// Try block. It does not match an dalvik instruction but is derived from the code item struct. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct Try { - #[pyo3(get)] - pub end_label: String, - /// The list of exceptions and their associated handler label. - /// - /// # Warning - /// - /// The handler are sorted: if severat Exception Type match an exceptions, the - /// the handler used is the first in the list. - #[pyo3(get)] - pub handlers: Vec<(IdType, String)>, - #[pyo3(get)] - pub default_handler: Option, -} - -#[pymethods] -impl Try { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new( - end_label: String, - handlers: Vec<(IdType, String)>, - default_handler: Option, - ) -> Self { - Self { - end_label, - default_handler, - handlers, - } - } - - pub fn __str__(&self) -> String { - let handlers = self - .handlers - .iter() - .map(|(ty, label)| format!(" {}: {label}", ty.__str__())) - .collect::>() - .join("\n "); - let default_handler = if let Some(label) = &self.default_handler { - format!(" default: {label}") - } else { - "".into() - }; - - format!( - "try until {}{}{}", - self.end_label, handlers, default_handler - ) - } - - pub fn __repr__(&self) -> String { - let handlers = self - .handlers - .iter() - .map(|(ty, label)| format!("{}, {label}", ty.__repr__())) - .collect::>() - .join(", "); - format!( - "Instruction(Try({}, [{}], {:?}))", - self.end_label, handlers, self.default_handler, - ) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 0 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - let mut strings = HashSet::new(); - for (ty, _) in &self.handlers { - strings.extend(ty.get_all_strings()); - } - strings - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - let mut types = HashSet::new(); - for (ty, _) in &self.handlers { - types.insert(ty.clone()); - } - types - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -} - -/// Label marker. It does not match an dalvik instruction, but it's use as a marker for a -/// jump destination. -#[pyclass] -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub struct Label { - #[pyo3(get)] - pub name: String, -} - -#[pymethods] -impl Label { - pub fn __eq__(&self, other: &Self) -> bool { - self == other - } - - pub fn to_json(&self) -> Result { - Ok(serde_json::to_string(self)?) - } - - #[staticmethod] - pub fn from_json(json: &str) -> Result { - Ok(serde_json::from_str(json)?) - } - - #[new] - pub fn new(name: String) -> Self { - Self { name } - } - - pub fn __str__(&self) -> String { - format!("{}:", self.name) - } - - pub fn __repr__(&self) -> String { - format!("Instruction(Label({}))", self.name) - } - /// Return the smallest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn min_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the bigest size possible for the associated instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn max_ins_size(&self) -> usize { - self.ins_size() - } - - /// Return the actual size of the instruction. - /// - /// # Warning - /// - /// The returned size is the size in bytes (`u8`) (the same as the value return - /// by the `Serializable::size()` method), but instructions in the bytecode - /// count addresses by unit of `u16`. - pub fn ins_size(&self) -> usize { - 0 - } - - /// Return all strings referenced in the instruction. - pub fn get_all_strings(&self) -> HashSet { - HashSet::new() - } - - /// Return all types referenced in the instruction. - pub fn get_all_types(&self) -> HashSet { - HashSet::new() - } - - /// Return all prototypes referenced in the instruction. - pub fn get_all_protos(&self) -> HashSet { - HashSet::new() - } - - /// Return all field ids referenced in the instruction. - pub fn get_all_field_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method ids referenced in the instruction. - pub fn get_all_method_ids(&self) -> HashSet { - HashSet::new() - } - - /// Return all method handles referenced in the instruction. - pub fn get_all_method_handles(&self) -> HashSet { - HashSet::new() - } -}