From bfec8a798103b2a29c621e380225b388af79a262 Mon Sep 17 00:00:00 2001 From: Guillaume Anthouard Date: Mon, 18 Jul 2022 19:12:25 +0200 Subject: [PATCH] Fix decompiling calls to native functions --- src/decompiler/mod.rs | 41 ++++++++++++++++++++++++++++------------- src/types.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/decompiler/mod.rs b/src/decompiler/mod.rs index c286755..a086bce 100644 --- a/src/decompiler/mod.rs +++ b/src/decompiler/mod.rs @@ -7,7 +7,7 @@ use std::collections::{HashMap, HashSet}; use ast::*; -use crate::types::{Function, RefField, Reg, Type, TypeObj}; +use crate::types::{FunPtr, Function, RefField, Reg, Type, TypeObj}; use crate::Bytecode; use crate::Opcode; @@ -344,16 +344,27 @@ pub fn decompile_function(code: &Bytecode, f: &Function) -> Vec { expr_ctx.pop(); } } else { - let func = $fun.resolve_as_fn(code).unwrap(); - let call = if func.is_method() { - Call::new(Expr::Field(Box::new(expr!($arg0)), func.name.clone().unwrap().resolve(&code.strings).to_owned()), make_args!($($args),*)) - } else { - Call::new_fun($fun, make_args!($arg0 $(, $args)*)) - }; - if func.ty(code).ret.is_void() { - push_stmt!(Statement::Call(call)); - } else { - push_expr!($i, $dst, Expr::Call(Box::new(call))); + match $fun.resolve(code) { + FunPtr::Fun(func) => { + let call = if func.is_method() { + Call::new(Expr::Field(Box::new(expr!($arg0)), func.name.clone().unwrap().resolve(&code.strings).to_owned()), make_args!($($args),*)) + } else { + Call::new_fun($fun, make_args!($arg0 $(, $args)*)) + }; + if func.ty(code).ret.is_void() { + push_stmt!(Statement::Call(call)); + } else { + push_expr!($i, $dst, Expr::Call(Box::new(call))); + } + } + FunPtr::Native(n) => { + let call = Call::new_fun($fun, make_args!($arg0 $(, $args)*)); + if n.ty(code).ret.is_void() { + push_stmt!(Statement::Call(call)); + } else { + push_expr!($i, $dst, Expr::Call(Box::new(call))); + } + } } } }; @@ -459,7 +470,7 @@ pub fn decompile_function(code: &Bytecode, f: &Function) -> Vec { //region CALLS &Opcode::Call0 { dst, fun } => { - if fun.resolve_as_fn(code).unwrap().ty(code).ret.is_void() { + if fun.ty(code).ret.is_void() { push_stmt!(Statement::Call(Call::new_fun(fun, Vec::new()))); } else { push_expr!(i, dst, call_fun(fun, Vec::new())); @@ -836,7 +847,11 @@ pub fn decompile_function(code: &Bytecode, f: &Function) -> Vec { } } &Opcode::EnumAlloc { dst, construct } => { - // TODO enum constructor + push_expr!( + i, + dst, + Expr::EnumConstr(f.regtype(dst), construct, Vec::new()) + ); } Opcode::MakeEnum { dst, diff --git a/src/types.rs b/src/types.rs index 0f35716..059d39f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -230,6 +230,26 @@ pub struct Native { pub findex: RefFun, } +impl Native { + pub fn name<'a>(&self, code: &'a Bytecode) -> &'a str { + self.name.resolve(&code.strings) + } + + /// Get the native function signature type + pub fn ty<'a>(&self, code: &'a Bytecode) -> &'a TypeFun { + // Guaranteed to be a TypeFun + self.t.resolve_as_fun(&code.types).expect("Unknown type ?") + } + + pub fn args<'a>(&self, code: &'a Bytecode) -> &'a [RefType] { + &self.ty(code).args + } + + pub fn ret<'a>(&self, code: &'a Bytecode) -> &'a Type { + self.ty(code).ret.resolve(&code.types) + } +} + /// A function definition with its code. #[derive(Debug, Clone)] pub struct Function { @@ -325,6 +345,28 @@ impl RefFun { pub fn resolve_as_fn<'a>(&self, code: &'a Bytecode) -> Option<&'a Function> { code.findexes[self.0].resolve_as_fn(code) } + + pub fn name<'a>(&self, code: &'a Bytecode) -> Option<&'a str> { + match self.resolve(code) { + FunPtr::Fun(fun) => fun.name(code), + FunPtr::Native(n) => Some(n.name.resolve(&code.strings)), + } + } + + pub fn ty<'a>(&self, code: &'a Bytecode) -> &'a TypeFun { + match self.resolve(code) { + FunPtr::Fun(fun) => fun.ty(code), + FunPtr::Native(n) => n.ty(code), + } + } + + pub fn args<'a>(&self, code: &'a Bytecode) -> &'a [RefType] { + &self.ty(code).args + } + + pub fn ret<'a>(&self, code: &'a Bytecode) -> &'a Type { + self.ty(code).ret.resolve(&code.types) + } } // Reference to a function or a native in the pool, but we know what is is.