From 7077509460c0b72a4a8a7185154b09170aac522a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=8D=9A=E6=96=87?= Date: Sun, 14 Apr 2024 00:24:47 +0800 Subject: [PATCH] feat: Implements lua constants dump --- Cargo.lock | 7 ++++ lib/Cargo.toml | 1 + lib/src/backend/lua/bytecode.rs | 29 +++++++++++----- lib/src/backend/lua/dump.rs | 37 +++++++++++++-------- lib/src/backend/lua/mod.rs | 19 ++++++++++- viewer/test_projects/example1/test_proj.xml | 1 + 6 files changed, 71 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3159015..16be1cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,12 @@ version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -1648,6 +1654,7 @@ name = "stc-rs" version = "0.1.0" dependencies = [ "bitflags 2.5.0", + "byteorder", "cbindgen", "chrono", "crc", diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 324bcc0..dd26921 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -25,6 +25,7 @@ smallvec = { version = "*", features = ["union", "const_generics", "const_new"] smallmap = "*" log = "*" indexmap = "*" +byteorder = "*" uuid = { version = "*", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } inkwell = { version = "*", optional = true, features = ["llvm16-0-no-llvm-linking"] } diff --git a/lib/src/backend/lua/bytecode.rs b/lib/src/backend/lua/bytecode.rs index acb7444..22c1492 100644 --- a/lib/src/backend/lua/bytecode.rs +++ b/lib/src/backend/lua/bytecode.rs @@ -6,7 +6,7 @@ use crate::ast::SmallVec8; use crate::parser::StString; use super::register::Register; -use super::ConstantIndex; +use super::{ConstantIndex, LuaType}; macro_rules! excess_k { ($v: expr, $k: expr) => { @@ -149,6 +149,17 @@ pub enum LuaConstants { Function(fn(&mut LuaExecState) -> i32), } +impl LuaConstants { + pub fn lua_type(&self) -> LuaType { + match *self { + Self::Nil => LuaType::NIL, + Self::Function(..) => LuaType::FUNCTION, + Self::String(..) => LuaType::STRING, + Self::Float(..) | Self::Integer(..) => LuaType::NUMBER, + } + } +} + #[derive(Debug, Clone, Default)] pub struct LuaUpValue { pub name: Option, @@ -274,7 +285,7 @@ impl LuaByteCode { // AsBx LuaByteCode::LoadI(a, sbx) => excess_sBx!(sbx) << 8 | a.num() as u32, // A B - LuaByteCode::Move(a, b) => todo!(), + LuaByteCode::Move(a, b) => (b.num() as u32) << 9 | a.num() as u32, // A only LuaByteCode::VarArgPrep(a) => (a as u32) << 8, }; @@ -311,17 +322,17 @@ impl LuaCompiledCode { match code { // ABC LuaByteCode::Add(a, b, c) => { - write!(s, "{} {} {}", a.num(), b.num(), c.num()).unwrap(); + write!(s, "R{} R{} R{}", a.num(), b.num(), c.num()).unwrap(); } // A B k LuaByteCode::Eq(a, b, k) => { - write!(s, "{} {} {k}", a.num(), b.num()).unwrap(); + write!(s, "R{} R{} {k}", a.num(), b.num()).unwrap(); } // A sB k LuaByteCode::GetTabUp(a, b, c) | LuaByteCode::Gti(a, b, c) | LuaByteCode::Gei(a, b, c) => { - write!(s, "{} {b} {c}", a.num()).unwrap(); + write!(s, "R{} {b} {c}", a.num()).unwrap(); } // A B C all literal LuaByteCode::Call(a, b, c) => { @@ -333,15 +344,15 @@ impl LuaCompiledCode { } // ABx LuaByteCode::LoadK(a, bx) => { - write!(s, "{} {bx}", a.num()).unwrap(); + write!(s, "R{} {bx}", a.num()).unwrap(); } // AsBx LuaByteCode::LoadI(a, sbx) => { - write!(s, "{} {sbx}", a.num()).unwrap(); + write!(s, "R{} {sbx}", a.num()).unwrap(); } // A B LuaByteCode::Move(a, b) => { - write!(s, "{} {}", a.num(), b.num()).unwrap(); + write!(s, "R{} R{}", a.num(), b.num()).unwrap(); } // A only LuaByteCode::VarArgPrep(a) => { @@ -351,7 +362,7 @@ impl LuaCompiledCode { match code { LuaByteCode::LoadK(a, bx) => { - write!(s, " ; {}", self.constants[*bx as usize]).unwrap(); + write!(s, " ; K[{}] = {}", bx, self.constants[*bx as usize]).unwrap(); } LuaByteCode::GetTabUp(a, b, c) => { write!(s, " ; _ENV \"{}\"", self.constants[*c as usize]).unwrap(); diff --git a/lib/src/backend/lua/dump.rs b/lib/src/backend/lua/dump.rs index 9e16a44..da7bb3e 100644 --- a/lib/src/backend/lua/dump.rs +++ b/lib/src/backend/lua/dump.rs @@ -1,4 +1,6 @@ -use super::utils::*; +use byteorder::{LittleEndian, WriteBytesExt}; + +use super::{utils::*, LuaConstants}; use super::{Function, LuaBackend, Prototype}; use crate::backend::lua::bytecode::LuaCompiledCode; @@ -65,9 +67,9 @@ fn lua_dump_function( // TODO: source file name lua_dump_string(w, None)?; // TODO: linedefined - lua_dump_int(w, 0)?; + lua_dump_size(w, 0)?; // TODO: lastlinedefined - lua_dump_int(w, 0)?; + lua_dump_size(w, 0)?; // numparams lua_dump_byte(w, num_params(p))?; // is_vararg @@ -84,19 +86,23 @@ fn lua_dump_function( // Dump Code for c in lua_code.byte_codes() { - let data = c.encode(); - w.write_all(&[ - (data & 0xff) as u8, - ((data >> 8) & 0xff) as u8, - ((data >> 16) & 0xff) as u8, - ((data >> 24) & 0xff) as u8, - ])?; + w.write_u32::(c.encode())?; } // Dump size of constants lua_dump_size(w, lua_code.constants_len() as u64)?; // Dump Constants + for constant in lua_code.constants() { + lua_dump_byte(w, constant.lua_type().bits())?; + + match *constant { + LuaConstants::Integer(i) => lua_dump_integer(w, i)?, + LuaConstants::Float(f) => lua_dump_float(w, f)?, + LuaConstants::String(ref s) => lua_dump_string(w, Some(s))?, + _ => todo!(), + } + } // Dump size of UpValues lua_dump_size(w, lua_code.upvalues.len() as u64)?; @@ -128,8 +134,13 @@ fn lua_dump_function( } #[inline] -fn lua_dump_int(w: &mut dyn Write, i: i32) -> io::Result<()> { - lua_dump_size(w, i as u32 as u64) +fn lua_dump_integer(w: &mut dyn Write, n: i64) -> io::Result<()> { + w.write_i64::(n) +} + +#[inline] +fn lua_dump_float(w: &mut dyn Write, f: f64) -> io::Result<()> { + w.write_f64::(f) } #[inline] @@ -170,7 +181,7 @@ fn lua_dump_bytes(w: &mut dyn Write, bytes: &[u8]) -> io::Result<()> { } #[inline] -fn lua_dump_string(w: &mut dyn Write, opt_str: Option) -> io::Result<()> { +fn lua_dump_string(w: &mut dyn Write, opt_str: Option<&String>) -> io::Result<()> { match opt_str { Some(s) => todo!(), None => lua_dump_size(w, 0), diff --git a/lib/src/backend/lua/mod.rs b/lib/src/backend/lua/mod.rs index 7a38654..1f310ef 100644 --- a/lib/src/backend/lua/mod.rs +++ b/lib/src/backend/lua/mod.rs @@ -37,6 +37,23 @@ bitflags! { } } +bitflags! { + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + pub struct LuaType: u8 { + const NONE = 0xff; + + const NIL = 0; + const BOOLEAN = 1; + const LIGHTUSERDATA = 2; + const NUMBER = 3; + const STRING = 4; + const TABLE = 5; + const FUNCTION = 6; + const USERDATA = 7; + const THREAD = 8; + } +} + #[derive(Clone)] pub struct LuaBackendStates { variable: Option>, @@ -358,7 +375,7 @@ impl AstVisitorMut for LuaBackend { } self.push_code(LuaByteCode::Call( - callee_index.unwrap() as u8, + callee_index.unwrap(), call.arguments().len() as u8, 0, )) diff --git a/viewer/test_projects/example1/test_proj.xml b/viewer/test_projects/example1/test_proj.xml index 58acd0e..e5e1ff9 100644 --- a/viewer/test_projects/example1/test_proj.xml +++ b/viewer/test_projects/example1/test_proj.xml @@ -23,6 +23,7 @@ end_program a := 123; + a := b;