From 920cc181dc0cb4cdc9d43fc34f00b2f21514ff21 Mon Sep 17 00:00:00 2001 From: Jean-Marie Mineau Date: Tue, 16 Jul 2024 17:31:37 +0200 Subject: [PATCH] WIP --- androscalpel/src/dex_writer.rs | 591 +----- androscalpel/src/instructions.rs | 3152 +++++++++++++++++++++++------- 2 files changed, 2473 insertions(+), 1270 deletions(-) diff --git a/androscalpel/src/dex_writer.rs b/androscalpel/src/dex_writer.rs index 04c55b9..7402361 100644 --- a/androscalpel/src/dex_writer.rs +++ b/androscalpel/src/dex_writer.rs @@ -445,7 +445,7 @@ impl DexWriter { } Instruction::ConstString { .. } => { let size = ins - .get_raw_ins(Some(&self.strings)) + .get_raw_ins(Some(&self.strings), None, None, None, None, None) .with_context(|| format!("In code of {}", method_id.__repr__()))? .size() / 2; @@ -469,7 +469,10 @@ impl DexWriter { addr += ins.max_ins_size() / 2; } Instruction::ConstString { .. } => { - addr += ins.get_raw_ins(Some(&self.strings, None))?.size() / 2; + addr += ins + .get_raw_ins(Some(&self.strings), None, None, None, None, None)? + .size() + / 2; // should not fail after // first loop, no need // for context @@ -514,33 +517,35 @@ impl DexWriter { // https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1347 // The ART check if the array data table is 4 bytes aligned (= 2 ins alligned) // TODO: check how it is donne in android and other dex generation code. - let nop = (Instruction::Nop {}).get_raw_ins(None, None)?; + let nop = (Instruction::Nop {}) + .get_raw_ins(None, None, None, None, None, None)?; payload_addr += nop.size() / 2; payloads.push(nop); } let data_offset = payload_addr as i32 - addr as i32; payload_addr += payload.size() / 2; payloads.push(payload); - let ins = ins.get_raw_ins(data_offset); + let ins = ins.get_raw_ins(None, None, None, None, None, Some(data_offset))?; addr += ins.size() / 2; insns.push(ins); } - Instruction::Goto(ins) => { + Instruction::Goto { .. } => { let goto_size = goto_sizes[goto_idx]; goto_idx += 1; - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found goto with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - let ins = ins.get_raw_ins(branch_offset, goto_size); + let ins = ins.get_raw_ins( + None, + None, + None, + Some((addr, &label_addrs)), + Some(goto_size), + None, + )?; addr += ins.size() / 2; insns.push(ins); } - Instruction::Switch(ins) => { + Instruction::Switch { branches, .. } => { let mut key_targets = vec![]; - for (key, label) in &ins.branches { + for (key, label) in branches { let label_addr = label_addrs.get(label).ok_or(anyhow!( "Label {} not found in code of {}, but found goto with this label", label, @@ -550,7 +555,7 @@ impl DexWriter { key_targets.push((*key, branch_offset)); } key_targets.sort_by_key(|(key, _)| *key); - let payload = if ins.is_packed() { + let payload = if ins.is_packed()? { let (first_key, _) = *key_targets.first().ok_or(anyhow!( "Found empty swith in code of {}", method_id.__repr__() @@ -565,554 +570,15 @@ impl DexWriter { // https://cs.android.com/android/platform/superproject/main/+/main:art/runtime/verifier/method_verifier.cc;drc=e8c3e7be783937a340cd4f3280b69962d6f1ea0c;l=1464 // The ART check if the switch table is 4 bytes aligned (= 2 ins alligned) // TODO: check how it is donne in android and other dex generation code. - let nop = (Instruction::Nop {}).get_raw_ins()?; + let nop = (Instruction::Nop {}) + .get_raw_ins(None, None, None, None, None, None)?; payload_addr += nop.size() / 2; payloads.push(nop); } let data_offset = payload_addr as i32 - addr as i32; payload_addr += payload.size() / 2; payloads.push(payload); - let ins = ins.get_raw_ins(data_offset); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfEq(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfNe(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfLt(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfGe(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfGt(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfLe(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfEqZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfNeZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfLtZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfGeZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfGtZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IfLeZ(ins) => { - let label_addr = label_addrs.get(&ins.label).ok_or(anyhow!( - "Label {} not found in code of {}, but found if with this label", - ins.label, - method_id.__repr__() - ))?; - let branch_offset = *label_addr as i32 - addr as i32; - if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { - bail!( - "Found an if that jump to far from the instruction in code of {}", - method_id.__repr__() - ); - } - let ins = ins.get_raw_ins(branch_offset as i16); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGet(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetWide(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetObject(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetBoolean(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetByte(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetChar(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IGetShort(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPut(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutWide(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutObject(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutBoolean(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutByte(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutChar(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::IPutShort(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGet(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetWide(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetObject(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetBoolean(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetByte(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetChar(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SGetShort(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPut(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutWide(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutObject(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutBoolean(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutByte(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutChar(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); - addr += ins.size() / 2; - insns.push(ins); - } - Instruction::SPutShort(ins) => { - let field = &ins.field; - let field_idx = self.field_ids.get(field).ok_or(anyhow!( - "Field {} (field of class {}, found in code of {}) not found in dex builder", - field.__repr__(), - field.class_.__repr__(), - method_id.__repr__() - ))?; - let ins = ins.get_raw_ins(*field_idx); + let ins = ins.get_raw_ins(None, None, None, None, None, Some(data_offset))?; addr += ins.size() / 2; insns.push(ins); } @@ -1308,7 +774,14 @@ impl DexWriter { Instruction::Label { .. } => (), _ => { let ins = ins - .get_raw_ins(Some(&self.strings), Some(&self.type_ids)) + .get_raw_ins( + Some(&self.strings), + Some(&self.type_ids), + Some(&self.field_ids), + Some((addr, &label_addrs)), + None, + None, + ) .with_context(|| { format!( "Failed to convert instruction {} (found in code of {}) to raw instruction", @@ -1323,7 +796,7 @@ impl DexWriter { } if addr % 2 != 0 { // make sure the payload section is 4 bytes aligned - let nop = (Instruction::Nop {}).get_raw_ins(None, None)?; + let nop = (Instruction::Nop {}).get_raw_ins(None, None, None, None, None, None)?; //addr += nop.size() / 2; insns.push(nop); } diff --git a/androscalpel/src/instructions.rs b/androscalpel/src/instructions.rs index 7bb15db..ee76295 100644 --- a/androscalpel/src/instructions.rs +++ b/androscalpel/src/instructions.rs @@ -14,7 +14,7 @@ use crate::{ use androscalpel_serializer::Instruction as InsFormat; use androscalpel_serializer::Serializable; -use anyhow::anyhow; +use anyhow::{anyhow, bail}; use pyo3::prelude::*; use std::collections::{HashMap, HashSet}; @@ -1897,6 +1897,74 @@ macro_rules! sanity_check_22b_or_22s { }}; } +macro_rules! raw_ins_if { + ($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident, $r2:ident) => {{ + let label_addr = $label_addrs.get($label).ok_or(anyhow!( + "Label {} not found in code, but found `if` with this label", + $label, + ))?; + let branch_offset = *label_addr as i32 - $addr as i32; + if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { + bail!("Found an `if` that jump to far from the instruction",); + } + Ok(InsFormat::Format22T { + op: $ins_op, + va: *$r1, + vb: *$r2, + c: branch_offset as i16, + }) + }}; +} + +macro_rules! raw_ins_ifz { + ($ins_op:tt, $label_addrs:ident, $label:ident, $addr:ident, $r1:ident) => {{ + let label_addr = $label_addrs.get($label).ok_or(anyhow!( + "Label {} not found in code, but found `if` with this label", + $label, + ))?; + let branch_offset = *label_addr as i32 - $addr as i32; + if branch_offset > i16::MAX as i32 || branch_offset < i16::MIN as i32 { + bail!("Found an `if` that jump to far from the instruction",); + } + Ok(InsFormat::Format21T { + op: $ins_op, + va: *$r1, + b: branch_offset as i16, + }) + }}; +} + +macro_rules! raw_ins_iget_put { + ($ins_op:tt, $field_ids:ident, $field:ident, $r1:ident, $r2:ident) => {{ + let field_idx = $field_ids.get($field).ok_or(anyhow!( + "Field {} (field of class {}) not found in dex builder", + $field.__repr__(), + $field.class_.__repr__(), + ))?; + Ok(InsFormat::Format22C { + op: $ins_op, + va: *$r1, + vb: *$r2, + c: *field_idx as u16, + }) + }}; +} + +macro_rules! raw_ins_sget_put { + ($ins_op:tt, $field_ids:ident, $field:ident, $r1:ident) => {{ + let field_idx = $field_ids.get($field).ok_or(anyhow!( + "Field {} (field of class {}) not found in dex builder", + $field.__repr__(), + $field.class_.__repr__(), + ))?; + Ok(InsFormat::Format21C { + op: $ins_op, + va: *$r1, + b: *field_idx as u16, + }) + }}; +} + #[pymethods] impl Instruction { pub fn __eq__(&self, other: &Self) -> bool { @@ -3886,13 +3954,13 @@ impl Instruction { /// /// # Variants that require `strings` /// - /// `strings` is a lookup table that associate it's idx to a string. + /// `strings` is a lookup table that associate its idx to a string. /// /// - `ConstString` /// /// # Variants that require `types_ids` /// - /// `types_ids` is a lookup table that associate it'ss idx to a type. + /// `types_ids` is a lookup table that associate its idx to a type. /// /// - `ConstClass` /// - `CheckCast` @@ -3901,23 +3969,10 @@ impl Instruction { /// - `NewArray` /// - `FilledNewArray` /// - /// # Variants that do not implement this method: + /// # Variants that require `field_ids` + /// + /// `field_ids` is a lookup table that associate its idx to a field. /// - /// - `FillArrayData` - /// - `Goto` - /// - `Switch` - /// - `IfEq` - /// - `IfNe` - /// - `IfLt` - /// - `IfGe` - /// - `IfGt` - /// - `IfLe` - /// - `IfEqZ` - /// - `IfNeZ` - /// - `IfLtZ` - /// - `IfGeZ` - /// - `IfGtZ` - /// - `IfLeZ` /// - `IGet` /// - `IGetWide` /// - `IGetObject` @@ -3932,6 +3987,42 @@ impl Instruction { /// - `IPutByte` /// - `IPutChar` /// - `IPutShort` + /// + /// # Variants that require `data_offset` + /// + /// `data_offset` is the offset from the instruction to the location of the data table. + /// + /// - `FillArrayData` + /// - `Switch` + /// + /// # Variants that require `goto_size` + /// + /// `goto_size` is the size of the goto instruction (wich can be greater than the best size + /// beause the algo used to compute offset trash) + /// + /// - `Goto` + /// + /// # Variants that require `jump_data` + /// + /// `jump_data` is the address of the current instruction and the lookup table that associate a + /// label with its addresse. + /// + /// - `Goto` + /// - `IfEq` + /// - `IfNe` + /// - `IfLt` + /// - `IfGe` + /// - `IfGt` + /// - `IfLe` + /// - `IfEqZ` + /// - `IfNeZ` + /// - `IfLtZ` + /// - `IfGeZ` + /// - `IfGtZ` + /// - `IfLeZ` + /// + /// # Variants that do not implement this method: + /// /// - `SGet` /// - `SGetWide` /// - `SGetObject` @@ -3961,12 +4052,40 @@ impl Instruction { &self, strings: Option<&HashMap>, type_ids: Option<&HashMap>, + field_ids: Option<&HashMap>, + jump_data: Option<(usize, &HashMap)>, + goto_size: Option, + data_offset: Option, ) -> Result { - match (self, strings, type_ids) { - (Self::ConstString { .. }, None, _type_ids) => Err(anyhow!( + match ( + self, + strings, + type_ids, + field_ids, + jump_data, + goto_size, + data_offset, + ) { + ( + Self::ConstString { .. }, + None, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a const-string without knowing the string idx" )), - (Self::ConstString { reg, lit }, Some(strings), _type_ids) => { + ( + Self::ConstString { reg, lit }, + Some(strings), + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let string_idx = strings.get(lit).ok_or(anyhow!( "String {} not found in dex builder", lit.__repr__(), @@ -3984,10 +4103,26 @@ impl Instruction { }), } } - (Self::ConstClass { .. }, _strings, None) => Err(anyhow!( + ( + Self::ConstClass { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a const-class without knowing the class idx" )), - (Self::ConstClass { reg, lit }, _strings, Some(types)) => Ok(InsFormat::Format21C { + ( + Self::ConstClass { reg, lit }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format21C { op: 0x1c, va: *reg, b: *types @@ -3995,10 +4130,26 @@ impl Instruction { .ok_or(anyhow!("Class {} not found in dex builder", lit.__repr__(),))? as u16, }), - (Self::CheckCast { .. }, _strings, None) => Err(anyhow!( + ( + Self::CheckCast { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a check-cast without knowing the type idx" )), - (Self::CheckCast { reg, lit }, _strings, Some(types)) => Ok(InsFormat::Format21C { + ( + Self::CheckCast { reg, lit }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format21C { op: 0x1f, va: *reg, b: *types @@ -4006,24 +4157,54 @@ impl Instruction { .ok_or(anyhow!("Class {} not found in dex builder", lit.__repr__(),))? as u16, }), - (Self::InstanceOf { .. }, _strings, None) => Err(anyhow!( + ( + Self::InstanceOf { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a instance-of without knowing the type idx" )), - (Self::InstanceOf { dest, obj, lit }, _strings, Some(types)) => { - Ok(InsFormat::Format22C { - op: 0x20, - va: *dest, - vb: *obj, - c: *types - .get(lit) - .ok_or(anyhow!("Class {} not found in dex builder", lit.__repr__(),))? - as u16, - }) - } - (Self::NewInstance { .. }, _strings, None) => Err(anyhow!( + ( + Self::InstanceOf { dest, obj, lit }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format22C { + op: 0x20, + va: *dest, + vb: *obj, + c: *types + .get(lit) + .ok_or(anyhow!("Class {} not found in dex builder", lit.__repr__(),))? + as u16, + }), + ( + Self::NewInstance { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a new-instance without knowing the class idx" )), - (Self::NewInstance { reg, lit }, _strings, Some(types)) => Ok(InsFormat::Format21C { + ( + Self::NewInstance { reg, lit }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format21C { op: 0x22, va: *reg, b: *types @@ -4031,24 +4212,54 @@ impl Instruction { .ok_or(anyhow!("Class {} not found in dex builder", lit.__repr__(),))? as u16, }), - (Self::NewArray { .. }, _strings, None) => Err(anyhow!( + ( + Self::NewArray { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a new-array without knowing the type idx" )), - (Self::NewArray { reg, size_reg, lit }, _strings, Some(types)) => { - Ok(InsFormat::Format22C { - op: 0x23, - va: *reg, - vb: *size_reg, - c: *types - .get(lit) - .ok_or(anyhow!("Type {} not found in dex builder", lit.__repr__(),))? - as u16, - }) - } - (Self::FilledNewArray { .. }, _strings, None) => Err(anyhow!( + ( + Self::NewArray { reg, size_reg, lit }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format22C { + op: 0x23, + va: *reg, + vb: *size_reg, + c: *types + .get(lit) + .ok_or(anyhow!("Type {} not found in dex builder", lit.__repr__(),))? + as u16, + }), + ( + Self::FilledNewArray { .. }, + _strings, + None, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a filled-new-array without knowing the type idx" )), - (Self::FilledNewArray { reg_values, type_ }, _strings, Some(types)) => { + ( + Self::FilledNewArray { reg_values, type_ }, + _strings, + Some(types), + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut last = None; let mut first = None; let mut consec = true; @@ -4092,9 +4303,10 @@ impl Instruction { vd, vf, vg, - b: *types - .get(type_) - .ok_or(anyhow!("Type {} not found in dex builder", type_.__repr__(),))? as u16, + b: *types.get(type_).ok_or(anyhow!( + "Type {} not found in dex builder", + type_.__repr__(), + ))? as u16, }) } else if consec && len <= 255 { let a = reg_values.len() as u8; @@ -4103,202 +4315,953 @@ impl Instruction { op: 0x25, a, vc, - b: *types - .get(type_) - .ok_or(anyhow!("Type {} not found in dex builder", type_.__repr__(),))? as u16, + b: *types.get(type_).ok_or(anyhow!( + "Type {} not found in dex builder", + type_.__repr__(), + ))? as u16, }) } else { // Not supposed to happend with a sanitized array panic!("Invalid NewArrayInstruction {self:?}") } } - (Self::FillArrayData { .. }, _strings, _types) => Err(anyhow!( + ( + Self::FillArrayData { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + None, + ) => Err(anyhow!( "Cannot get the raw instruction of a fill-array-data without knowing the offset \ to the -fill-array-data-payload" )), - (Self::Goto { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the size of a goto without knowing the branch offset" - )), - (Self::Switch { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a switch without knowing the offset \ + ( + Self::FillArrayData { arr, .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + Some(data_offset), + ) => Ok(InsFormat::Format31T { + op: 0x26, + va: *arr, + b: data_offset, + }), + (Self::Goto { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => Err( + anyhow!("Cannot get the size of a goto without knowing the branch offset"), + ), + (Self::Goto { .. }, _strings, _types, _fields, _jump_data, None, _data_offset) => { + Err(anyhow!( + "Cannot get the size of a goto without knowing the size of the instruction" + )) + } + ( + Self::Goto { label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + Some(goto_size), + _data_offset, + ) => { + let label_addr = label_addrs.get(label).ok_or(anyhow!( + "Label {} not found, but found goto with this label", + label, + ))?; + let branch_offset = *label_addr as i32 - addr as i32; + if goto_size == 2 && (I8_MIN_AS_I32..=I8_MAX_AS_I32).contains(&branch_offset) { + Ok(InsFormat::Format10T { + op: 0x28, + a: branch_offset as i8, + }) + } else if goto_size == 4 + && (I16_MIN_AS_I32..=I16_MAX_AS_I32).contains(&branch_offset) + { + Ok(InsFormat::Format20T { + op: 0x29, + a: branch_offset as i16, + }) + } else if goto_size == 6 { + Ok(InsFormat::Format30T { + op: 0x2a, + a: branch_offset, + }) + } else { + Err(anyhow!("Invalid goto_size and/or data_offset value")) + } + } + (Self::Switch { .. }, _strings, _types, _fields, _jump_data, _goto_size, None) => { + Err(anyhow!( + "Cannot get the raw instruction of a switch without knowing the offset \ to the packed/sparse-switch-payload" - )), - (Self::IfEq { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-eq without knowing \ + )) + } + ( + Self::Switch { reg, .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + Some(data_offset), + ) => Ok(InsFormat::Format31T { + op: if self.is_packed()? { 0x2b } else { 0x2c }, + va: *reg, + b: data_offset, + }), + (Self::IfEq { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-eq without knowing \ the offset to the branch" - )), - (Self::IfNe { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-ne without knowing \ + )) + } + (Self::IfNe { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-ne without knowing \ the offset to the branch" - )), - (Self::IfLt { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-lt without knowing \ + )) + } + (Self::IfLt { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-lt without knowing \ the offset to the branch" - )), - (Self::IfGe { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-ge without knowing \ + )) + } + (Self::IfGe { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-ge without knowing \ the offset to the branch" - )), - (Self::IfGt { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-gt without knowing \ + )) + } + (Self::IfGt { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-gt without knowing \ the offset to the branch" - )), - (Self::IfLe { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-le without knowing \ + )) + } + (Self::IfLe { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-le without knowing \ the offset to the branch" - )), - (Self::IfEqZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-eqz without knowing \ + )) + } + (Self::IfEqZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-eqz without knowing \ the offset to the branch" - )), - (Self::IfNeZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-nez without knowing \ + )) + } + (Self::IfNeZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-nez without knowing \ the offset to the branch" - )), - (Self::IfLtZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-ltz without knowing \ + )) + } + (Self::IfLtZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-ltz without knowing \ the offset to the branch" - )), - (Self::IfGeZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-gez without knowing \ + )) + } + (Self::IfGeZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-gez without knowing \ the offset to the branch" - )), - (Self::IfGtZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-gtz without knowing \ + )) + } + (Self::IfGtZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-gtz without knowing \ the offset to the branch" - )), - (Self::IfLeZ { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a if-lez without knowing \ + )) + } + (Self::IfLeZ { .. }, _strings, _types, _fields, None, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a if-lez without knowing \ the offset to the branch" - )), - (Self::IGet { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a iget without knowing the field idx" - )), - (Self::IGetWide { .. }, _strings, _types) => Err(anyhow!( + )) + } + ( + Self::IfEq { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x32, label_addrs, label, addr, a, b), + ( + Self::IfNe { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x33, label_addrs, label, addr, a, b), + ( + Self::IfLt { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x34, label_addrs, label, addr, a, b), + ( + Self::IfGe { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x35, label_addrs, label, addr, a, b), + ( + Self::IfGt { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x36, label_addrs, label, addr, a, b), + ( + Self::IfLe { a, b, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_if!(0x37, label_addrs, label, addr, a, b), + ( + Self::IfEqZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x38, label_addrs, label, addr, a), + ( + Self::IfNeZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x39, label_addrs, label, addr, a), + ( + Self::IfLtZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x3a, label_addrs, label, addr, a), + ( + Self::IfGeZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x3b, label_addrs, label, addr, a), + ( + Self::IfGtZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x3c, label_addrs, label, addr, a), + ( + Self::IfLeZ { a, label }, + _strings, + _types, + _fields, + Some((addr, label_addrs)), + _goto_size, + _data_offset, + ) => raw_ins_ifz!(0x3b, label_addrs, label, addr, a), + (Self::IGet { .. }, _strings, _types, None, _jump_data, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a iget without knowing the field idx" + )) + } + ( + Self::IGetWide { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-wide without knowing the field idx" )), - (Self::IGetObject { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGetObject { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-object without knowing the field idx" )), - (Self::IGetBoolean { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGetBoolean { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-boolean without knowing the field idx" )), - (Self::IGetByte { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGetByte { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-byte without knowing the field idx" )), - (Self::IGetChar { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGetChar { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-char without knowing the field idx" )), - (Self::IGetShort { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGetShort { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iget-short without knowing the field idx" )), - (Self::IPut { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a iput without knowing the field idx" - )), - (Self::IPutWide { .. }, _strings, _types) => Err(anyhow!( + (Self::IPut { .. }, _strings, _types, None, _jump_data, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a iput without knowing the field idx" + )) + } + ( + Self::IPutWide { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-wide without knowing the field idx" )), - (Self::IPutObject { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IPutObject { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-object without knowing the field idx" )), - (Self::IPutBoolean { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IPutBoolean { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-boolean without knowing the field idx" )), - (Self::IPutByte { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IPutByte { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-byte without knowing the field idx" )), - (Self::IPutChar { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IPutChar { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-char without knowing the field idx" )), - (Self::IPutShort { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IPutShort { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a iput-short without knowing the field idx" )), - (Self::SGet { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a sget without knowing the field idx" - )), - (Self::SGetWide { .. }, _strings, _types) => Err(anyhow!( + ( + Self::IGet { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x52, fields, field, to, obj), + ( + Self::IGetWide { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x53, fields, field, to, obj), + ( + Self::IGetObject { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x54, fields, field, to, obj), + ( + Self::IGetBoolean { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x55, fields, field, to, obj), + ( + Self::IGetByte { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x56, fields, field, to, obj), + ( + Self::IGetChar { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x57, fields, field, to, obj), + ( + Self::IGetShort { to, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x58, fields, field, to, obj), + ( + Self::IPut { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x59, fields, field, from, obj), + ( + Self::IPutWide { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5a, fields, field, from, obj), + ( + Self::IPutObject { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5b, fields, field, from, obj), + ( + Self::IPutBoolean { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5c, fields, field, from, obj), + ( + Self::IPutByte { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5d, fields, field, from, obj), + ( + Self::IPutChar { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5e, fields, field, from, obj), + ( + Self::IPutShort { from, obj, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_iget_put!(0x5f, fields, field, from, obj), + (Self::SGet { .. }, _strings, _types, None, _jump_data, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a sget without knowing the field idx" + )) + } + ( + Self::SGetWide { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-wide without knowing the field idx" )), - (Self::SGetObject { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGetObject { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-object without knowing the field idx" )), - (Self::SGetBoolean { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGetBoolean { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-boolean without knowing the field idx" )), - (Self::SGetByte { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGetByte { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-byte without knowing the field idx" )), - (Self::SGetChar { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGetChar { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-char without knowing the field idx" )), - (Self::SGetShort { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGetShort { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sget-short without knowing the field idx" )), - (Self::SPut { .. }, _strings, _types) => Err(anyhow!( - "Cannot get the raw instruction of a sput without knowing the field idx" - )), - (Self::SPutWide { .. }, _strings, _types) => Err(anyhow!( + (Self::SPut { .. }, _strings, _types, None, _jump_data, _goto_size, _data_offset) => { + Err(anyhow!( + "Cannot get the raw instruction of a sput without knowing the field idx" + )) + } + ( + Self::SPutWide { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-wide without knowing the field idx" )), - (Self::SPutObject { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SPutObject { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-object without knowing the field idx" )), - (Self::SPutBoolean { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SPutBoolean { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-boolean without knowing the field idx" )), - (Self::SPutByte { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SPutByte { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-byte without knowing the field idx" )), - (Self::SPutChar { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SPutChar { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-char without knowing the field idx" )), - (Self::SPutShort { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SPutShort { .. }, + _strings, + _types, + None, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a sput-short without knowing the field idx" )), - (Self::InvokeVirtual { .. }, _strings, _types) => Err(anyhow!( + ( + Self::SGet { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x60, fields, field, to), + ( + Self::SGetWide { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x61, fields, field, to), + ( + Self::SGetObject { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x62, fields, field, to), + ( + Self::SGetBoolean { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x63, fields, field, to), + ( + Self::SGetByte { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x64, fields, field, to), + ( + Self::SGetChar { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x65, fields, field, to), + ( + Self::SGetShort { to, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x66, fields, field, to), + ( + Self::SPut { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x67, fields, field, from), + ( + Self::SPutWide { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x68, fields, field, from), + ( + Self::SPutObject { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x69, fields, field, from), + ( + Self::SPutBoolean { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x6a, fields, field, from), + ( + Self::SPutByte { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x6b, fields, field, from), + ( + Self::SPutChar { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x6c, fields, field, from), + ( + Self::SPutShort { from, field }, + _strings, + _types, + Some(fields), + _jump_data, + _goto_size, + _data_offset, + ) => raw_ins_sget_put!(0x6d, fields, field, from), + ( + Self::InvokeVirtual { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-virtual without knowing \ the method idx" )), - (Self::InvokeSuper { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokeSuper { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-super without knowing \ the method idx" )), - (Self::InvokeDirect { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokeDirect { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-direct without knowing \ the method idx" )), - (Self::InvokeStatic { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokeStatic { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-static without knowing \ the method idx" )), - (Self::InvokeInterface { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokeInterface { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-interface without knowing \ the method idx" )), - (Self::InvokePolymorphic { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokePolymorphic { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-polymorphic without knowing \ the method idx and proto idx" )), - (Self::InvokeCustom { .. }, _strings, _types) => Err(anyhow!( + ( + Self::InvokeCustom { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a invoke-custom without knowing the \ call site idx" )), - (Self::ConstMethodHandle { .. }, _strings, _types) => Err(anyhow!( + ( + Self::ConstMethodHandle { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a const-method-handle \ without knowing the method handle idx" )), - (Self::ConstMethodType { .. }, _strings, _types) => Err(anyhow!( + ( + Self::ConstMethodType { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!( "Cannot get the raw instruction of a const-method-type \ without knowing the proto idx" )), - (Self::Try { .. }, _strings, _types) => Err(anyhow!( - "Try instruction cannot be converted to raw instruction" - )), - (Self::Label { .. }, _strings, _types) => { - Err(anyhow!("Label cannot be converted to raw instruction")) + (Self::Try { .. }, _strings, _types, _fields, _jump_data, _goto_size, _data_offset) => { + Err(anyhow!( + "Try instruction cannot be converted to raw instruction" + )) } - (Self::Nop {}, _strings, _types) => Ok(InsFormat::Format10X { op: 0x00 }), - (Self::Move { from, to }, _strings, _types) => match (to, from) { + ( + Self::Label { .. }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Err(anyhow!("Label cannot be converted to raw instruction")), + (Self::Nop {}, _strings, _types, _fields, _jump_data, _goto_size, _data_offset) => { + Ok(InsFormat::Format10X { op: 0x00 }) + } + ( + Self::Move { from, to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => match (to, from) { (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { op: 0x01, va: *to as u8, @@ -4315,7 +5278,15 @@ impl Instruction { vb: *from, }), }, - (Self::MoveWide { from, to }, _strings, _types) => match (to, from) { + ( + Self::MoveWide { from, to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => match (to, from) { (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { op: 0x04, va: *to as u8, @@ -4332,7 +5303,15 @@ impl Instruction { vb: *from, }), }, - (Self::MoveObject { from, to }, _strings, _types) => match (to, from) { + ( + Self::MoveObject { from, to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => match (to, from) { (0..=0b0000_1111, 0..=0b0000_1111) => Ok(InsFormat::Format12X { op: 0x07, va: *to as u8, @@ -4349,29 +5328,87 @@ impl Instruction { vb: *from, }), }, - (Self::MoveResult { to }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x0a, va: *to }) - } - (Self::MoveResultWide { to }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x0b, va: *to }) - } - (Self::MoveResultObject { to }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x0c, va: *to }) - } - (Self::MoveException { to }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x0d, va: *to }) - } - (Self::ReturnVoid {}, _strings, _types) => Ok(InsFormat::Format10X { op: 0x0e }), - (Self::Return { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x0f, va: *reg }) - } - (Self::ReturnWide { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x10, va: *reg }) - } - (Self::ReturnObject { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x11, va: *reg }) - } - (Self::Const { lit, reg }, _strings, _types) => match (reg, lit) { + ( + Self::MoveResult { to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x0a, va: *to }), + ( + Self::MoveResultWide { to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x0b, va: *to }), + ( + Self::MoveResultObject { to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x0c, va: *to }), + ( + Self::MoveException { to }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x0d, va: *to }), + ( + Self::ReturnVoid {}, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format10X { op: 0x0e }), + ( + Self::Return { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x0f, va: *reg }), + ( + Self::ReturnWide { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x10, va: *reg }), + ( + Self::ReturnObject { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x11, va: *reg }), + ( + Self::Const { lit, reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => match (reg, lit) { (0..=0b0000_1111, -8..=7) => Ok(InsFormat::Format11N { op: 0x12, va: *reg, @@ -4393,7 +5430,15 @@ impl Instruction { b: *lit, }), }, - (Self::ConstWide { lit, reg }, _strings, _types) => match lit { + ( + Self::ConstWide { lit, reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => match lit { I16_MIN_AS_I64..=I16_MAX_AS_I64 => Ok(InsFormat::Format21S { op: 0x16, va: *reg, @@ -4415,398 +5460,314 @@ impl Instruction { b: *lit, }), }, - (Self::MonitorEnter { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x1d, va: *reg }) - } - (Self::MonitorExit { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x1e, va: *reg }) - } - (Self::ArrayLength { dest, arr }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::MonitorEnter { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x1d, va: *reg }), + ( + Self::MonitorExit { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x1e, va: *reg }), + ( + Self::ArrayLength { dest, arr }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x21, va: *dest, vb: *arr, }), - */ - /* needs data_offset - (Self::FillArrayData { arr, data_offset }, _strings, _types) => Ok(InsFormat::Format31T { - op: 0x26, - va: *arr, - b: data_offset, - }), - */ - (Self::Throw { reg }, _strings, _types) => { - Ok(InsFormat::Format11X { op: 0x27, va: *reg }) - } - /* needs data_offset - (Self::Goto { data_offset }, _strings, _types) => { - 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}, _strings, _types) => Ok(InsFormat::Format31T { - op: if is_packed() { 0x2b } else { 0x2c }, - va: *reg, - b: data_offset, - }), - */ - (Self::CmpLFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::Throw { reg }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format11X { op: 0x27, va: *reg }), + ( + Self::CmpLFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x2d, va: *dest, vb: *b, vc: *c, }), - (Self::CmpGFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::CmpGFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x2e, va: *dest, vb: *b, vc: *c, }), - (Self::CmpLDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::CmpLDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x2f, va: *dest, vb: *b, vc: *c, }), - (Self::CmpGDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::CmpGDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x30, va: *dest, vb: *b, vc: *c, }), - (Self::CmpLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::CmpLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x31, va: *dest, vb: *b, vc: *c, }), - /* needs branch_offset - (Self::IfEq { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x32, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfNe { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x33, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfLt { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x34, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfGe { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x35, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfGt { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x36, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfLe { a, b }, _strings, _types) => Ok(InsFormat::Format22T { - op: 0x37, - va: *a, - vb: *b, - c: *branch_offset, - }), - (Self::IfEqZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x38, - va: *a, - b: *branch_offset, - }), - (Self::IfNeZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x39, - va: *a, - b: *branch_offset, - }), - (Self::IfLtZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x3a, - va: *a, - b: *branch_offset, - }), - (Self::IfGeZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x3b, - va: *a, - b: *branch_offset, - }), - (Self::IfGtZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x3c, - va: *a, - b: *branch_offset, - }), - (Self::IfLeZ { a }, _strings, _types) => Ok(InsFormat::Format21T { - op: 0x3d, - va: *a, - b: *branch_offset, - }), - */ - (Self::AGet { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGet { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x44, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetWide { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetWide { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x45, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetObject { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetObject { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x46, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetBoolean { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetBoolean { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x47, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetByte { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetByte { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x48, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetChar { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetChar { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x49, va: *dest, vb: *arr, vc: *idx, }), - (Self::AGetShort { dest, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AGetShort { dest, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4a, va: *dest, vb: *arr, vc: *idx, }), - (Self::APut { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APut { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4b, va: *from, vb: *arr, vc: *idx, }), - (Self::APutWide { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutWide { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4c, va: *from, vb: *arr, vc: *idx, }), - (Self::APutObject { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutObject { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4d, va: *from, vb: *arr, vc: *idx, }), - (Self::APutBoolean { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutBoolean { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4e, va: *from, vb: *arr, vc: *idx, }), - (Self::APutByte { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutByte { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x4f, va: *from, vb: *arr, vc: *idx, }), - (Self::APutChar { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutChar { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x50, va: *from, vb: *arr, vc: *idx, }), - (Self::APutShort { from, arr, idx }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::APutShort { from, arr, idx }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x51, va: *from, vb: *arr, vc: *idx, }), - /* needs field_idx - (Self::IGet { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x52, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetWide { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x53, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetObject { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x54, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetBoolean { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x55, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetByte { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x56, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetChar { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x57, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IGetShort { to, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x58, - va: *to, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPut { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x59, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutWide { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5a, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutObject { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5b, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutBoolean { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5c, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutByte { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5d, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutChar { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5e, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::IPutShort { from, obj, field }, _strings, _types) => Ok(InsFormat::Format22C { - op: 0x5f, - va: *from, - vb: *obj, - c: field_idx as u16, - }), - (Self::SGet { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x60, - va: *to, - b: field_idx as u16, - }), - (Self::SGetWide { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x61, - va: *to, - b: field_idx as u16, - }), - (Self::SGetObject { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x62, - va: *to, - b: field_idx as u16, - }), - (Self::SGetBoolean { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x63, - va: *to, - b: field_idx as u16, - }), - (Self::SGetByte { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x64, - va: *to, - b: field_idx as u16, - }), - (Self::SGetChar { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x65, - va: *to, - b: field_idx as u16, - }), - (Self::SGetShort { to, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x66, - va: *to, - b: field_idx as u16, - }), - (Self::SPut { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x67, - va: *from, - b: field_idx as u16, - }), - (Self::SPutWide { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x68, - va: *from, - b: field_idx as u16, - }), - (Self::SPutObject { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x69, - va: *from, - b: field_idx as u16, - }), - (Self::SPutBoolean { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x6a, - va: *from, - b: field_idx as u16, - }), - (Self::SPutByte { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x6b, - va: *from, - b: field_idx as u16, - }), - (Self::SPutChar { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x6c, - va: *from, - b: field_idx as u16, - }), - (Self::SPutShort { from, field }, _strings, _types) => Ok(InsFormat::Format21C { - op: 0x6d, - va: *from, - b: field_idx as u16, - }), - */ /* needs meth_idx - (Self::InvokeVirtual { args, method }, _strings, _types) => { + (Self::InvokeVirtual { args, method }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { let mut last = None; let mut first = None; let mut consec = true; @@ -4866,7 +5827,7 @@ impl Instruction { panic!("Invalid Invoke instruction {self:?}") } } - (Self::InvokeSuper { args, method }, _strings, _types) => { + (Self::InvokeSuper { args, method }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { let mut last = None; let mut first = None; let mut consec = true; @@ -4926,7 +5887,7 @@ impl Instruction { panic!("Invalid Invoke instruction {self:?}") } } - (Self::InvokeDirect { args, method }, _strings, _types) => { + (Self::InvokeDirect { args, method }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { let mut last = None; let mut first = None; let mut consec = true; @@ -4986,7 +5947,7 @@ impl Instruction { panic!("Invalid Invoke instruction {self:?}") } } - (Self::InvokeStatic { args, method }, _strings, _types) => { + (Self::InvokeStatic { args, method }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { let mut last = None; let mut first = None; let mut consec = true; @@ -5046,7 +6007,7 @@ impl Instruction { panic!("Invalid Invoke instruction {self:?}") } } - (Self::InvokeInterface { args, method }, _strings, _types) => { + (Self::InvokeInterface { args, method }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { let mut last = None; let mut first = None; let mut consec = true; @@ -5107,464 +6068,1152 @@ impl Instruction { } } */ - (Self::NegInt { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NegInt { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x7b, va: *dest, vb: *val, }), - (Self::NotInt { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NotInt { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x7c, va: *dest, vb: *val, }), - (Self::NegLong { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NegLong { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x7d, va: *dest, vb: *val, }), - (Self::NotLong { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NotLong { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x7e, va: *dest, vb: *val, }), - (Self::NegFloat { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NegFloat { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x7f, va: *dest, vb: *val, }), - (Self::NegDouble { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::NegDouble { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x80, va: *dest, vb: *val, }), - (Self::IntToLong { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToLong { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x81, va: *dest, vb: *val, }), - (Self::IntToFloat { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToFloat { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x82, va: *dest, vb: *val, }), - (Self::IntToDouble { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToDouble { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x83, va: *dest, vb: *val, }), - (Self::LongToInt { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::LongToInt { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x84, va: *dest, vb: *val, }), - (Self::LongToFloat { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::LongToFloat { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x85, va: *dest, vb: *val, }), - (Self::LongToDouble { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::LongToDouble { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x86, va: *dest, vb: *val, }), - (Self::FloatToInt { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::FloatToInt { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x87, va: *dest, vb: *val, }), - (Self::FloatToLong { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::FloatToLong { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x88, va: *dest, vb: *val, }), - (Self::FloatToDouble { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::FloatToDouble { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x89, va: *dest, vb: *val, }), - (Self::DoubleToInt { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DoubleToInt { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8a, va: *dest, vb: *val, }), - (Self::DoubleToLong { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DoubleToLong { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8b, va: *dest, vb: *val, }), - (Self::DoubleToFloat { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DoubleToFloat { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8c, va: *dest, vb: *val, }), - (Self::IntToByte { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToByte { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8d, va: *dest, vb: *val, }), - (Self::IntToChar { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToChar { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8e, va: *dest, vb: *val, }), - (Self::IntToShort { dest, val }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::IntToShort { dest, val }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0x8f, va: *dest, vb: *val, }), - (Self::AddInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AddInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x90, va: *dest, vb: *b, vc: *c, }), - (Self::SubInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::SubInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x91, va: *dest, vb: *b, vc: *c, }), - (Self::MulInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::MulInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x92, va: *dest, vb: *b, vc: *c, }), - (Self::DivInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::DivInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x93, va: *dest, vb: *b, vc: *c, }), - (Self::RemInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::RemInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x94, va: *dest, vb: *b, vc: *c, }), - (Self::AndInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AndInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x95, va: *dest, vb: *b, vc: *c, }), - (Self::OrInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::OrInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x96, va: *dest, vb: *b, vc: *c, }), - (Self::XorInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::XorInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x97, va: *dest, vb: *b, vc: *c, }), - (Self::ShlInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::ShlInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x98, va: *dest, vb: *b, vc: *c, }), - (Self::ShrInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::ShrInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x99, va: *dest, vb: *b, vc: *c, }), - (Self::UshrInt { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::UshrInt { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9a, va: *dest, vb: *b, vc: *c, }), - (Self::AddLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AddLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9b, va: *dest, vb: *b, vc: *c, }), - (Self::SubLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::SubLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9c, va: *dest, vb: *b, vc: *c, }), - (Self::MulLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::MulLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9d, va: *dest, vb: *b, vc: *c, }), - (Self::DivLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::DivLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9e, va: *dest, vb: *b, vc: *c, }), - (Self::RemLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::RemLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0x9f, va: *dest, vb: *b, vc: *c, }), - (Self::AndLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AndLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa0, va: *dest, vb: *b, vc: *c, }), - (Self::OrLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::OrLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa1, va: *dest, vb: *b, vc: *c, }), - (Self::XorLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::XorLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa2, va: *dest, vb: *b, vc: *c, }), - (Self::ShlLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::ShlLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa3, va: *dest, vb: *b, vc: *c, }), - (Self::ShrLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::ShrLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa4, va: *dest, vb: *b, vc: *c, }), - (Self::UshrLong { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::UshrLong { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa5, va: *dest, vb: *b, vc: *c, }), - (Self::AddFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AddFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa6, va: *dest, vb: *b, vc: *c, }), - (Self::SubFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::SubFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa7, va: *dest, vb: *b, vc: *c, }), - (Self::MulFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::MulFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa8, va: *dest, vb: *b, vc: *c, }), - (Self::DivFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::DivFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xa9, va: *dest, vb: *b, vc: *c, }), - (Self::RemFloat { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::RemFloat { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xaa, va: *dest, vb: *b, vc: *c, }), - (Self::AddDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::AddDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xab, va: *dest, vb: *b, vc: *c, }), - (Self::SubDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::SubDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xac, va: *dest, vb: *b, vc: *c, }), - (Self::MulDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::MulDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xad, va: *dest, vb: *b, vc: *c, }), - (Self::DivDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::DivDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xae, va: *dest, vb: *b, vc: *c, }), - (Self::RemDouble { dest, b, c }, _strings, _types) => Ok(InsFormat::Format23X { + ( + Self::RemDouble { dest, b, c }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format23X { op: 0xaf, va: *dest, vb: *b, vc: *c, }), - (Self::AddInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AddInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb0, va: *dest, vb: *b, }), - (Self::SubInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::SubInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb1, va: *dest, vb: *b, }), - (Self::MulInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::MulInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb2, va: *dest, vb: *b, }), - (Self::DivInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DivInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb3, va: *dest, vb: *b, }), - (Self::RemInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::RemInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb4, va: *dest, vb: *b, }), - (Self::AndInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AndInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb5, va: *dest, vb: *b, }), - (Self::OrInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::OrInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb6, va: *dest, vb: *b, }), - (Self::XorInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::XorInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb7, va: *dest, vb: *b, }), - (Self::ShlInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::ShlInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb8, va: *dest, vb: *b, }), - (Self::ShrInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::ShrInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xb9, va: *dest, vb: *b, }), - (Self::UshrInt2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::UshrInt2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xba, va: *dest, vb: *b, }), - (Self::AddLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AddLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xbb, va: *dest, vb: *b, }), - (Self::SubLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::SubLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xbc, va: *dest, vb: *b, }), - (Self::MulLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::MulLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xbd, va: *dest, vb: *b, }), - (Self::DivLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DivLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xbe, va: *dest, vb: *b, }), - (Self::RemLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::RemLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xbf, va: *dest, vb: *b, }), - (Self::AndLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AndLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc0, va: *dest, vb: *b, }), - (Self::OrLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::OrLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc1, va: *dest, vb: *b, }), - (Self::XorLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::XorLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc2, va: *dest, vb: *b, }), - (Self::ShlLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::ShlLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc3, va: *dest, vb: *b, }), - (Self::ShrLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::ShrLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc4, va: *dest, vb: *b, }), - (Self::UshrLong2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::UshrLong2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc5, va: *dest, vb: *b, }), - (Self::AddFloat2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AddFloat2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc6, va: *dest, vb: *b, }), - (Self::SubFloat2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::SubFloat2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc7, va: *dest, vb: *b, }), - (Self::MulFloat2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::MulFloat2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc8, va: *dest, vb: *b, }), - (Self::DivFloat2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DivFloat2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xc9, va: *dest, vb: *b, }), - (Self::RemFloat2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::RemFloat2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xca, va: *dest, vb: *b, }), - (Self::AddDouble2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::AddDouble2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xcb, va: *dest, vb: *b, }), - (Self::SubDouble2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::SubDouble2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xcc, va: *dest, vb: *b, }), - (Self::MulDouble2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::MulDouble2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xcd, va: *dest, vb: *b, }), - (Self::DivDouble2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::DivDouble2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xce, va: *dest, vb: *b, }), - (Self::RemDouble2Addr { b, dest }, _strings, _types) => Ok(InsFormat::Format12X { + ( + Self::RemDouble2Addr { b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format12X { op: 0xcf, va: *dest, vb: *b, }), - (Self::AddIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::AddIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5601,7 +7250,15 @@ impl Instruction { }) } } - (Self::RsubIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::RsubIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5638,7 +7295,15 @@ impl Instruction { }) } } - (Self::MulIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::MulIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5675,7 +7340,15 @@ impl Instruction { }) } } - (Self::DivIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::DivIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5712,7 +7385,15 @@ impl Instruction { }) } } - (Self::RemIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::RemIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5749,7 +7430,15 @@ impl Instruction { }) } } - (Self::AndIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::AndIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5786,7 +7475,15 @@ impl Instruction { }) } } - (Self::OrIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::OrIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5823,7 +7520,15 @@ impl Instruction { }) } } - (Self::XorIntLit { lit, b, dest }, _strings, _types) => { + ( + Self::XorIntLit { lit, b, dest }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => { let mut reg_on_4_bit = true; let mut lit_on_8_bits = true; if dest & 0b1111_0000 != 0 { @@ -5860,169 +7565,194 @@ impl Instruction { }) } } - (Self::ShlIntLit { dest, b, lit }, _strings, _types) => Ok(InsFormat::Format22B { + ( + Self::ShlIntLit { dest, b, lit }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format22B { op: 0xe0, va: *dest, vb: *b, c: *lit, }), - (Self::ShrIntLit { dest, b, lit }, _strings, _types) => Ok(InsFormat::Format22B { + ( + Self::ShrIntLit { dest, b, lit }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format22B { op: 0xe1, va: *dest, vb: *b, c: *lit, }), - (Self::UshrIntLit { dest, b, lit }, _strings, _types) => Ok(InsFormat::Format22B { + ( + Self::UshrIntLit { dest, b, lit }, + _strings, + _types, + _fields, + _jump_data, + _goto_size, + _data_offset, + ) => Ok(InsFormat::Format22B { op: 0xe2, va: *dest, vb: *b, c: *lit, - }), - /* needs method_idx and proto_idx - (Self::InvokePolymorphic { args, method, proto }, _strings, _types) => { - 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; + }), /* needs method_idx and proto_idx + (Self::InvokePolymorphic { args, method, proto }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { + 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 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 }, _strings, _types) => { - 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 let Some(last) = last { + if r != last + 1 { + consec = false; + } } + if r & 0b1111_0000 != 0 { + four_bites = false; + } + last = Some(r); } - if r & 0b1111_0000 != 0 { - four_bites = false; + 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:?}") } - last = Some(r); } - if four_bites && len <= 5 { - let mut regs = vec![]; - for reg in args.iter().cloned() { - regs.push(reg); + */ + /* needs call_site_idx + (Self::InvokeCustom { args, call_site }, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => { + 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); } - while regs.len() != 5 { - regs.push(0); + 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:?}") } - 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}, _strings, _types) => Ok(InsFormat::Format21C { - op: 0xfe, - va: *to, - b: method_handle_idx as u16, - }), - */ - /* needs proto_idx - (Self::ConstMethodType {to, proto}, _strings, _types) => Ok(InsFormat::Format21C { - op: 0xff, - va: *to, - b: proto_idx as u16, - }), - */ + */ + /* needs method_handle_idx + (Self::ConstMethodHandle {to, handle}, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => Ok(InsFormat::Format21C { + op: 0xfe, + va: *to, + b: method_handle_idx as u16, + }), + */ + /* needs proto_idx + (Self::ConstMethodType {to, proto}, _strings, _types,_fields, _jump_data, _goto_size, _data_offset) => Ok(InsFormat::Format21C { + op: 0xff, + va: *to, + b: proto_idx as u16, + }), + */ } } - /// TODO: remove? tmp solution for now, only implemented for Switch - pub fn is_packed(&self) -> bool { + /// Test is a switch instruction is packed or not. + /// + /// Return an error if the instruction is not a `Switch`. + pub fn is_packed(&self) -> Result { match self { Self::Switch { branches, .. } => { let mut last = None; @@ -6031,14 +7761,14 @@ impl Instruction { for key in keys.into_iter().cloned() { if let Some(last) = &last { if *last != key - 1 { - return false; + return Ok(false); } } last = Some(key); } - true + Ok(true) } - _ => todo!(), // TODO: leave as is? + _ => Err(anyhow!("Instruction is not a Switch")), } }