add instruction using pseudo-instruction format

This commit is contained in:
Jean-Marie Mineau 2023-12-15 14:55:55 +01:00
parent 95f4686f3f
commit 2d164362a7
Signed by: histausse
GPG key ID: B66AEEDA9B645AD2
2 changed files with 209 additions and 8 deletions

View file

@ -8,6 +8,8 @@ use crate::{DexString, IdField, IdMethod, IdMethodType, IdType, MethodHandle, Re
use anyhow::anyhow;
use pyo3::prelude::*;
use std::collections::HashMap;
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CallSite; // TODO
@ -743,7 +745,83 @@ impl FilledNewArray {
}
}
// TODO: fill-array-data
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FillArrayData {
pub arr: u8,
pub elt_width: u16,
pub data: Vec<u8>,
}
#[pymethods]
impl FillArrayData {
#[new]
pub fn new(arr: u8, elt_width: u16, data: Vec<u8>) -> Self {
Self {
arr,
elt_width,
data,
}
}
pub fn __str__(&self) -> String {
let data: String = if self.data.len() / self.elt_width as usize == 0 {
"".into()
} else if self.data.len() / self.elt_width as usize <= 2 {
let mut arr = "".into();
for (i, v) in self.data.iter().enumerate() {
if i == 0 {
arr += "0x"
} else if i % self.elt_width as usize == 0 {
arr += " 0x"
}
arr += format!("{v:02x}").as_str();
}
arr
} else {
let mut arr = "0x".into();
for v in &self.data[..self.elt_width as usize] {
arr += format!("{v:02x}").as_str();
}
arr += " ... 0x";
for v in &self.data[self.data.len() - self.elt_width as usize..] {
arr += format!("{v:02x}").as_str();
}
arr
};
format!("fill-array-data {} {}", self.arr, data)
}
pub fn __repr__(&self) -> String {
let data: String = if self.data.len() / self.elt_width as usize == 0 {
"".into()
} else if self.data.len() / self.elt_width as usize <= 2 {
let mut arr = "".into();
for (i, v) in self.data.iter().enumerate() {
if i == 0 {
arr += "0x"
} else if i % self.elt_width as usize == 0 {
arr += ", 0x"
}
arr += format!("{v:02x}").as_str();
}
arr
} else {
let mut arr = "0x".into();
for v in &self.data[..self.elt_width as usize] {
arr += format!("{v:02x}").as_str();
}
arr += ", ..., 0x";
for v in &self.data[self.data.len() - self.elt_width as usize..] {
arr += format!("{v:02x}").as_str();
}
arr
};
format!("Instruction(FillArrayData({}, [{}]))", self.arr, data)
}
}
/// Throws the exception in the register.
#[pyclass]
@ -791,8 +869,36 @@ impl Goto {
}
}
// TODO packed-switch
/// Jump to a label depending on the value of a register. If the value
/// is not matched, continue the extecution at the next instruction.
#[pyclass]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Switch {
pub reg: u8,
pub branches: HashMap<i32, String>,
}
#[pymethods]
impl Switch {
#[new]
pub fn new(reg: u8, branches: HashMap<i32, String>) -> Self {
Self { reg, branches }
}
pub fn __str__(&self) -> String {
let mut branches_str: String = "".into();
let mut branches: Vec<_> = self.branches.iter().collect();
branches.sort_by_key(|(key, _)| key);
for (key, label) in branches {
branches_str += &format!("\n {key}: goto {label}");
}
format!("switch {} {}", self.reg, branches_str)
}
pub fn __repr__(&self) -> String {
format!("Instruction(Switch({}, ...))", self.reg)
}
}
/// Store the result of the comparison between the registers.
///
/// - b < c: a = -1