From a05c130af1288bada75a522976f06072ae0b1a13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Sun, 8 Sep 2024 23:56:15 +0200 Subject: [PATCH] Better optimizations --- cilly/src/bin/linker/main.rs | 19 +++- cilly/src/v2/asm.rs | 4 +- cilly/src/v2/asm_link.rs | 12 +++ cilly/src/v2/builtins/math.rs | 68 ++++++++++++++- cilly/src/v2/builtins/mod.rs | 56 ++++++++---- cilly/src/v2/cilroot.rs | 18 +++- cilly/src/v2/float.rs | 14 +++ cilly/src/v2/il_exporter/mod.rs | 6 ++ cilly/src/v2/iter.rs | 21 +++++ cilly/src/v2/method.rs | 3 + cilly/src/v2/opt/mod.rs | 149 +++++++++++++++++++++++++++++--- cilly/src/v2/opt/opt_node.rs | 41 ++++++--- cilly/src/v2/tpe.rs | 2 +- test/arthm/num_test.rs | 4 + 14 files changed, 369 insertions(+), 48 deletions(-) diff --git a/cilly/src/bin/linker/main.rs b/cilly/src/bin/linker/main.rs index 4d788f13..191eb3d1 100644 --- a/cilly/src/bin/linker/main.rs +++ b/cilly/src/bin/linker/main.rs @@ -160,7 +160,22 @@ fn main() { // Load assemblies from files let (mut final_assembly, _) = load::load_assemblies(to_link.as_slice(), ar_to_link.as_slice()); - + /* + { + let msg = final_assembly.alloc_string("Starting constant initialization"); + let msg = final_assembly.alloc_node(Const::PlatformString(msg)); + let console = ClassRef::console(&mut final_assembly); + let fn_name = final_assembly.alloc_string("WriteLine"); + let mref = final_assembly.class_ref(console).clone().static_mref( + &[Type::PlatformString], + Type::Void, + fn_name, + &mut final_assembly, + ); + let stat = final_assembly.alloc_root(CILRoot::Call(Box::new((mref, [msg].into())))); + final_assembly.add_cctor(&[stat]); + } + */ let path: std::path::PathBuf = output_file_path.into(); let is_lib = output_file_path.contains(".dll") @@ -357,7 +372,7 @@ fn main() { cilly::v2::builtins::instert_threading(&mut final_assembly, &mut overrides); cilly::v2::builtins::insert_swap_at_generic(&mut final_assembly, &mut overrides); cilly::v2::builtins::insert_bounds_check(&mut final_assembly, &mut overrides); - + cilly::v2::builtins::math::math(&mut final_assembly, &mut overrides); // Ensure the cctor and tcctor exist! let _ = final_assembly.tcctor(); let _ = final_assembly.cctor(); diff --git a/cilly/src/v2/asm.rs b/cilly/src/v2/asm.rs index f1e05931..1ab62f43 100644 --- a/cilly/src/v2/asm.rs +++ b/cilly/src/v2/asm.rs @@ -109,7 +109,7 @@ impl Assembly { pub fn methods_with<'a>( &'a self, mut filter: impl FnMut(&Self, MethodDefIdx, &MethodDef) -> bool + 'a, - ) -> impl Iterator + 'a { + ) -> impl Iterator + 'a { self.method_defs .iter() .filter(move |(id, def)| filter(self, **id, def)) @@ -141,7 +141,7 @@ impl Assembly { pub fn find_strs_containing<'a, P: std::str::pattern::Pattern + Clone + 'a>( &'a self, pat: P, - ) -> impl Iterator + '_ { + ) -> impl Iterator + 'a { self.strings .0 .iter() diff --git a/cilly/src/v2/asm_link.rs b/cilly/src/v2/asm_link.rs index 52eb2bc5..f7df25c5 100644 --- a/cilly/src/v2/asm_link.rs +++ b/cilly/src/v2/asm_link.rs @@ -429,6 +429,18 @@ impl Assembly { let tpe = self.translate_type(source, *tpe); CILRoot::StInd(Box::new((addr, val, tpe, *volitile))) } + CILRoot::CpObj { src, dst, tpe } => { + let src = self.translate_node(source, source.get_node(src).clone()); + let src = self.alloc_node(src); + let dst = self.translate_node(source, source.get_node(dst).clone()); + let dst = self.alloc_node(dst); + let tpe = self.translate_type(source, *source.get_type(tpe)); + CILRoot::CpObj { + src, + dst, + tpe: self.alloc_type(tpe), + } + } CILRoot::InitBlk(info) => { let (dst, val, count) = info.as_ref(); let dst = self.translate_node(source, source.get_node(*dst).clone()); diff --git a/cilly/src/v2/builtins/math.rs b/cilly/src/v2/builtins/math.rs index 96d41e0e..0be6f712 100644 --- a/cilly/src/v2/builtins/math.rs +++ b/cilly/src/v2/builtins/math.rs @@ -1,4 +1,10 @@ -use crate::v2::{cilnode::MethodKind, Assembly, CILNode, ClassRef, Int, MethodRef, NodeIdx, Type}; +use crate::v2::{ + asm::MissingMethodPatcher, + cilnode::MethodKind, + hashable::{HashableF32, HashableF64}, + Assembly, BasicBlock, BinOp, CILNode, CILRoot, ClassRef, Const, Float, Int, MethodImpl, + MethodRef, NodeIdx, Type, +}; pub fn int_max(asm: &mut Assembly, lhs: NodeIdx, rhs: NodeIdx, int: Int) -> NodeIdx { let math = ClassRef::math(asm); @@ -27,3 +33,63 @@ pub fn int_min(asm: &mut Assembly, lhs: NodeIdx, rhs: NodeIdx, int: Int) -> Node )); asm.alloc_node(CILNode::Call(Box::new((mref, Box::new([lhs, rhs]))))) } +pub fn ldexpf(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { + let name = asm.alloc_string("ldexpf"); + let generator = move |_, asm: &mut Assembly| { + let arg = asm.alloc_node(CILNode::LdArg(0)); + let exp = asm.alloc_node(CILNode::LdArg(1)); + let exp = asm.alloc_node(CILNode::FloatCast { + input: exp, + target: Float::F32, + is_signed: true, + }); + let two = asm.alloc_node(Const::F32(HashableF32(2.0))); + let pow = Float::F32.pow(two, exp, asm); + let res_val = asm.alloc_node(CILNode::BinOp(arg, pow, BinOp::Mul)); + let ret = asm.alloc_root(CILRoot::Ret(res_val)); + MethodImpl::MethodBody { + blocks: vec![BasicBlock::new(vec![ret], 0, None)], + locals: vec![], + } + }; + patcher.insert(name, Box::new(generator)); +} +pub fn ldexp(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { + let name = asm.alloc_string("ldexp"); + let generator = move |_, asm: &mut Assembly| { + let arg = asm.alloc_node(CILNode::LdArg(0)); + let exp = asm.alloc_node(CILNode::LdArg(1)); + let exp = asm.alloc_node(CILNode::FloatCast { + input: exp, + target: Float::F64, + is_signed: true, + }); + let two = asm.alloc_node(Const::F64(HashableF64(2.0))); + let pow = Float::F64.pow(two, exp, asm); + let res_val = asm.alloc_node(CILNode::BinOp(arg, pow, BinOp::Mul)); + let ret = asm.alloc_root(CILRoot::Ret(res_val)); + MethodImpl::MethodBody { + blocks: vec![BasicBlock::new(vec![ret], 0, None)], + locals: vec![], + } + }; + patcher.insert(name, Box::new(generator)); +} +/* +pub fn bitreverse_u128(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { + let name = asm.alloc_string("bitreverse_u128"); + let generator = move |_, asm: &mut Assembly| { + let arg = asm.alloc_node(CILNode::LdArg(0)); + let loc0 = asm.alloc_node(CILNode::LdLoc(0)); + let ret = asm.alloc_root(CILRoot::Ret(res_val)); + MethodImpl::MethodBody { + blocks: vec![BasicBlock::new(vec![ret], 0, None)], + locals: vec![(None, asm.alloc_type(Type::Int(Int::I128)))], + } + }; + patcher.insert(name, Box::new(generator)); +} */ +pub fn math(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { + ldexp(asm, patcher); + ldexpf(asm, patcher); +} diff --git a/cilly/src/v2/builtins/mod.rs b/cilly/src/v2/builtins/mod.rs index 16e5efb9..a51a7ef3 100644 --- a/cilly/src/v2/builtins/mod.rs +++ b/cilly/src/v2/builtins/mod.rs @@ -1,6 +1,7 @@ use super::{ - asm::MissingMethodPatcher, cilnode::MethodKind, Access, Assembly, BasicBlock, CILNode, CILRoot, - ClassDef, ClassRef, Const, FieldDesc, Int, MethodDef, MethodImpl, MethodRef, Type, + asm::MissingMethodPatcher, cilnode::MethodKind, cilroot::BranchCond, Access, Assembly, + BasicBlock, CILNode, CILRoot, ClassDef, ClassRef, Const, FieldDesc, Int, MethodDef, MethodImpl, + MethodRef, Type, }; pub mod atomics; @@ -159,6 +160,7 @@ pub fn insert_heap(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { insert_rust_realloc(asm, patcher); insert_rust_dealloc(asm, patcher); insert_catch_unwind(asm, patcher); + insert_pause(asm, patcher); let rust_exception = asm.alloc_string("RustException"); let data_pointer = asm.alloc_string("data_pointer"); let this = asm.alloc_string("this"); @@ -200,6 +202,18 @@ pub fn insert_heap(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { vec![Some(this), Some(data_pointer)], )); } + +fn insert_pause(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { + let name = asm.alloc_string("llvm.x86.sse2.pause"); + let generator = move |_, asm: &mut Assembly| { + let ret = asm.alloc_root(CILRoot::VoidRet); + MethodImpl::MethodBody { + blocks: vec![BasicBlock::new(vec![ret], 0, None)], + locals: vec![], + } + }; + patcher.insert(name, Box::new(generator)); +} fn insert_catch_unwind(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { let name = asm.alloc_string("catch_unwind"); let generator = move |_, asm: &mut Assembly| { @@ -233,6 +247,14 @@ fn insert_catch_unwind(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { asm.alloc_class_ref(ClassRef::new(rust_exception, None, false, [].into())); let rust_exception_tpe = Type::ClassRef(rust_exception); let rust_exception_tpe = asm.alloc_type(rust_exception_tpe); + // Check if exception is the right type, otherwise jump away + let check_exception_tpe = asm.alloc_node(CILNode::IsInst(ldloc_1, rust_exception_tpe)); + let rethrow_if_wrong_exception = asm.alloc_root(CILRoot::Branch(Box::new(( + 0, + 4, + Some(BranchCond::False(check_exception_tpe)), + )))); + // Cast the excpetion let cast_exception = asm.alloc_node(CILNode::CheckedCast(ldloc_1, rust_exception_tpe)); let data_pointer = asm.alloc_string("data_pointer"); let ptr_field = asm.alloc_field(FieldDesc::new( @@ -253,27 +275,25 @@ fn insert_catch_unwind(asm: &mut Assembly, patcher: &mut MissingMethodPatcher) { let const_1 = asm.alloc_node(Const::I32(1)); let ret_0 = asm.alloc_root(CILRoot::Ret(const_0)); let ret_1 = asm.alloc_root(CILRoot::Ret(const_1)); - // Debug - let console = ClassRef::console(asm); - let write_line = asm.alloc_string("WriteLine"); - let write_line = asm.class_ref(console).clone().static_mref( - &[Type::PlatformObject], - Type::Void, - write_line, - asm, - ); - let print_exception = - asm.alloc_root(CILRoot::Call(Box::new((write_line, Box::new([ldloc_1]))))); + let rethrow = asm.alloc_root(CILRoot::ReThrow); MethodImpl::MethodBody { blocks: vec![ BasicBlock::new( vec![calli_try, exit_try_success], 0, - Some(vec![BasicBlock::new( - vec![set_exception, calli_catch, exit_try_faliure], - 1, - None, - )]), + Some(vec![ + BasicBlock::new( + vec![ + set_exception, + rethrow_if_wrong_exception, + calli_catch, + exit_try_faliure, + ], + 1, + None, + ), + BasicBlock::new(vec![rethrow], 4, None), + ]), ), BasicBlock::new(vec![ret_0], 2, None), BasicBlock::new(vec![ret_1], 3, None), diff --git a/cilly/src/v2/cilroot.rs b/cilly/src/v2/cilroot.rs index 0e02e631..b58eb550 100644 --- a/cilly/src/v2/cilroot.rs +++ b/cilly/src/v2/cilroot.rs @@ -5,7 +5,7 @@ use super::{ cilnode::MethodKind, field::FieldIdx, Assembly, CILNode, FieldDesc, Float, FnSig, Int, MethodRef, MethodRefIdx, NodeIdx, SigIdx, - StaticFieldDesc, StaticFieldIdx, StringIdx, Type, + StaticFieldDesc, StaticFieldIdx, StringIdx, Type, TypeIdx, }; use crate::cil_root::CILRoot as V1Root; //use crate::cil_node::CILNode as V1Node; @@ -51,6 +51,11 @@ pub enum CILRoot { field: StaticFieldIdx, val: NodeIdx, }, + CpObj { + src: NodeIdx, + dst: NodeIdx, + tpe: TypeIdx, + }, } #[derive(Hash, PartialEq, Eq, Clone, Debug, Serialize, Deserialize)] @@ -130,6 +135,7 @@ impl CILRoot { args.push(ptr); args.into() } + CILRoot::CpObj { src, dst, tpe } => [src, dst].into(), } } #[allow(clippy::too_many_lines)] @@ -552,6 +558,16 @@ impl CILRoot { ))); root_map(root, asm) } + CILRoot::CpObj { src, dst, tpe } => { + let src = asm.get_node(src).clone().map(asm, node_map); + let dst = asm.get_node(dst).clone().map(asm, node_map); + let root = CILRoot::CpObj { + src: asm.alloc_node(src), + dst: asm.alloc_node(dst), + tpe, + }; + root_map(root, asm) + } CILRoot::InitBlk(blk) => { let (dst, val, count) = *blk; let dst = asm.get_node(dst).clone().map(asm, node_map); diff --git a/cilly/src/v2/float.rs b/cilly/src/v2/float.rs index 2310f36a..4e1e3537 100644 --- a/cilly/src/v2/float.rs +++ b/cilly/src/v2/float.rs @@ -101,6 +101,20 @@ impl Float { Float::F128 => todo!(), } } + /// Raises base to power. + pub fn pow(&self, base: NodeIdx, exp: NodeIdx, asm: &mut Assembly) -> NodeIdx { + let pow = asm.alloc_string("Pow"); + let class = self.class(asm); + let sig = asm.sig([Type::Float(*self), Type::Float(*self)], *self); + let mref = asm.alloc_methodref(MethodRef::new( + class, + pow, + sig, + MethodKind::Static, + [].into(), + )); + asm.alloc_node(CILNode::Call(Box::new((mref, Box::new([base, exp]))))) + } } impl From for Type { fn from(value: Float) -> Self { diff --git a/cilly/src/v2/il_exporter/mod.rs b/cilly/src/v2/il_exporter/mod.rs index c60b09b4..05a23b2e 100644 --- a/cilly/src/v2/il_exporter/mod.rs +++ b/cilly/src/v2/il_exporter/mod.rs @@ -951,6 +951,12 @@ impl ILExporter { call.0 ) } + super::CILRoot::CpObj { src, dst, tpe } => { + self.export_node(asm, out, *src)?; + self.export_node(asm, out, *dst)?; + let tpe = type_il(asm.get_type(*tpe), asm); + writeln!(out, "cpobj {tpe}") + } super::CILRoot::StInd(stind) => { self.export_node(asm, out, stind.0)?; self.export_node(asm, out, stind.1)?; diff --git a/cilly/src/v2/iter.rs b/cilly/src/v2/iter.rs index b96ed852..43a2d7f4 100644 --- a/cilly/src/v2/iter.rs +++ b/cilly/src/v2/iter.rs @@ -89,6 +89,24 @@ impl<'asm> Iterator for CILIter<'asm> { continue; } }, + CILIterElem::Root(CILRoot::CpObj { src, dst, tpe }) => match idx { + 1 => { + *idx += 1; + let lhs = self.asm.get_node(*src); + self.elems.push((CILIterElem::Node(lhs.clone()), 0)); + continue; + } + 2 => { + *idx += 1; + let rhs = self.asm.get_node(*dst); + self.elems.push((CILIterElem::Node(rhs.clone()), 0)); + continue; + } + _ => { + self.elems.pop(); + continue; + } + }, CILIterElem::Node( CILNode::BinOp(lhs, rhs, _) | CILNode::LdElelemRef { @@ -511,6 +529,9 @@ impl<'this, T: Iterator + 'this> TpeIter<'this> for T { let tpe = field.tpe(); Some(Box::new([class, tpe].into_iter())) } + CILRoot::CpObj { tpe, .. } => { + Some(Box::new(std::iter::once(*asm.get_type(tpe)))) + } // Since this method is called, then if it uses an "internal" type, we must assume it is defined in this module. Thus, its types are already included, and we don't need to include them again. CILRoot::Call(_) | CILRoot::CallI(_) => None, CILRoot::StInd(info) => Some(Box::new(std::iter::once(info.2))), diff --git a/cilly/src/v2/method.rs b/cilly/src/v2/method.rs index 42c16500..42f005e9 100644 --- a/cilly/src/v2/method.rs +++ b/cilly/src/v2/method.rs @@ -278,6 +278,9 @@ impl MethodDef { arg_debug_count, v1.call_site().name() ); + for arg in &arg_names { + println!("{:?}", arg.map(|arg| asm.get_string(arg))); + } arg_names.truncate(arg_sig_count); } } diff --git a/cilly/src/v2/opt/mod.rs b/cilly/src/v2/opt/mod.rs index b7f5fc1b..2bd859b7 100644 --- a/cilly/src/v2/opt/mod.rs +++ b/cilly/src/v2/opt/mod.rs @@ -1,8 +1,8 @@ use simplify_handlers::simplify_bbs; use super::{ - cilroot::BranchCond, method::LocalDef, BasicBlock, CILIter, CILIterElem, CILNode, CILRoot, - Const, Int, MethodImpl, NodeIdx, RootIdx, Type, + cilroot::BranchCond, method::LocalDef, BasicBlock, BinOp, CILIter, CILIterElem, CILNode, + CILRoot, Const, Int, MethodImpl, NodeIdx, RootIdx, Type, }; use crate::v2::{Assembly, MethodDef}; use std::collections::HashMap; @@ -76,8 +76,25 @@ impl CILNode { | Type::FnPtr(_) | Type::Ptr(_) | Type::ClassRef(_) - | Type::Int(Int::USize | Int::I64 | Int::U64 | Int::U32 | Int::I32) + | Type::Int( + Int::I128 + | Int::U128 + | Int::USize + | Int::ISize + | Int::I64 + | Int::U64 + | Int::U32 + | Int::I32, + ) | Type::Ref(_) => asm.get_node(new_node).clone(), + /*Type::Int(int @ (Int::I8 | Int::U8 | Int::I16 | Int::U16)) => { + CILNode::IntCast { + input: new_node, + target: int, + // Does not matter, since this does nothing for ints < 32 bits, which this arm handles. + extend: super::cilnode::ExtendKind::ZeroExtend, + } + }*/ _ => CILNode::LdLoc(*loc), } } else { @@ -539,29 +556,141 @@ impl MethodDef { CILNode::LdLoc(_) => CILRoot::Nop, _ => root, }, + /* + CILRoot::StInd(ref info) => match asm.get_node(info.1) { + CILNode::LdInd { + addr: src_addr, + tpe, + volitale:_, + } => { + assert_eq!(*asm.get_type(*tpe), info.2); + CILRoot::CpObj { + src: *src_addr, + dst: info.0, + tpe: asm.alloc_type(info.2), + } + } + _ => root, + },*/ CILRoot::Branch(ref info) => { let (target, sub_target, cond) = info.as_ref(); match cond { - Some(BranchCond::False(cond)) => match asm.get_node(*cond) { - CILNode::Const(cst) => match cst.as_ref() { - Const::Bool(false) => { - CILRoot::Branch(Box::new((*target, *sub_target, None))) + Some(BranchCond::False(cond)) => { + match asm.get_node(*cond) { + CILNode::Const(cst) => match cst.as_ref() { + Const::Bool(false) => { + CILRoot::Branch(Box::new((*target, *sub_target, None))) + } + Const::Bool(true) => CILRoot::Nop, + _ => root, + }, + // a == b is false <=> a != b + CILNode::BinOp(lhs, rhs, BinOp::Eq) => { + CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::Ne(*lhs, *rhs)), + ))) } - Const::Bool(true) => CILRoot::Nop, _ => root, - }, + } + } + Some(BranchCond::True(cond)) => match asm.get_node(*cond) { + // a == b is true <=> a == b + CILNode::BinOp(lhs, rhs, BinOp::Eq) => CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::Eq(*lhs, *rhs)), + ))), _ => root, }, + Some(BranchCond::Ne(lhs, rhs)) => { + match (asm.get_node(*lhs), asm.get_node(*rhs)) { + (_, CILNode::Const(cst)) => match cst.as_ref() { + // val != false <=> val is true + Const::Bool(false) + | Const::ISize(0) + | Const::USize(0) + | Const::I64(0) + | Const::U64(0) + | Const::I32(0) + | Const::U32(0) + | Const::I16(0) + | Const::U16(0) + | Const::I8(0) + | Const::U8(0) => CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::True(*lhs)), + ))), + // val != true <=> val is false + Const::Bool(true) => CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::False(*lhs)), + ))), + _ => root, + }, + (CILNode::Const(cst), _) => match cst.as_ref() { + // val != false <=> val is true + Const::Bool(false) + | Const::ISize(0) + | Const::USize(0) + | Const::I64(0) + | Const::U64(0) + | Const::I32(0) + | Const::U32(0) + | Const::I16(0) + | Const::U16(0) + | Const::I8(0) + | Const::U8(0) => CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::True(*rhs)), + ))), + _ => root, + }, + _ => root, + } + } Some(BranchCond::Eq(lhs, rhs)) => { match (asm.get_node(*lhs), asm.get_node(*rhs)) { (_, CILNode::Const(cst)) => match cst.as_ref() { - Const::ISize(0) => CILRoot::Branch(Box::new(( + Const::Bool(false) + | Const::ISize(0) + | Const::USize(0) + | Const::I64(0) + | Const::U64(0) + | Const::I32(0) + | Const::U32(0) + | Const::I16(0) + | Const::U16(0) + | Const::I8(0) + | Const::U8(0) => CILRoot::Branch(Box::new(( *target, *sub_target, Some(BranchCond::False(*lhs)), ))), _ => root, }, + (CILNode::Const(cst), _) => match cst.as_ref() { + Const::Bool(false) + | Const::ISize(0) + | Const::USize(0) + | Const::I64(0) + | Const::U64(0) + | Const::I32(0) + | Const::U32(0) + | Const::I16(0) + | Const::U16(0) + | Const::I8(0) + | Const::U8(0) => CILRoot::Branch(Box::new(( + *target, + *sub_target, + Some(BranchCond::False(*rhs)), + ))), + _ => root, + }, _ => root, } } diff --git a/cilly/src/v2/opt/opt_node.rs b/cilly/src/v2/opt/opt_node.rs index f845b9c8..c93edc2d 100644 --- a/cilly/src/v2/opt/opt_node.rs +++ b/cilly/src/v2/opt/opt_node.rs @@ -10,17 +10,33 @@ pub fn opt_node(node: crate::v2::CILNode, asm: &mut Assembly) -> CILNode { CILNode::Const(cst) => match (cst.as_ref(), target) { (Const::U64(val), Int::USize) => Const::USize(*val).into(), (Const::I64(val), Int::ISize) => Const::ISize(*val).into(), + (Const::U64(val), Int::U64) => Const::U64(*val).into(), + (Const::I64(val), Int::I64) => Const::I64(*val).into(), + (Const::U32(val), Int::U32) => Const::U32(*val).into(), + (Const::I32(val), Int::I32) => Const::I32(*val).into(), + (Const::I32(val), Int::U32) => Const::U32(*val as u32).into(), _ => node, }, CILNode::IntCast { - input: _input2, + input: input2, target: target2, extend: extend2, } => { if target == *target2 && extend == *extend2 { return asm.get_node(input).clone(); } - node + match (target, target2) { + (Int::USize | Int::ISize, Int::USize | Int::ISize) => { + // A usize to isize cast does nothing, except change the type on the evaulation stack(the bits are unchanged). + // So, we can just create a cast like it. + CILNode::IntCast { + input: *input2, + target, + extend: *extend2, + } + } + _ => node, + } } _ => node, }, @@ -28,17 +44,16 @@ pub fn opt_node(node: crate::v2::CILNode, asm: &mut Assembly) -> CILNode { addr, tpe, volitale, - } => { - if let CILNode::RefToPtr(inner) = asm.get_node(addr) { - CILNode::LdInd { - addr: *inner, - tpe, - volitale, - } - } else { - node - } - } + } => match asm.get_node(addr) { + CILNode::RefToPtr(inner) => CILNode::LdInd { + addr: *inner, + tpe, + volitale, + }, + CILNode::LdLocA(loc) => CILNode::LdLoc(*loc), + CILNode::LdArgA(loc) => CILNode::LdArg(*loc), + _ => node, + }, CILNode::LdField { addr, field } => match asm.get_node(addr) { CILNode::RefToPtr(addr) => CILNode::LdField { addr: *addr, field }, diff --git a/cilly/src/v2/tpe.rs b/cilly/src/v2/tpe.rs index a0378b3a..6fd232c8 100644 --- a/cilly/src/v2/tpe.rs +++ b/cilly/src/v2/tpe.rs @@ -67,7 +67,7 @@ impl Type { tmp } #[must_use] - pub fn deref<'a, 'b: 'a>(&'a self, asm: &'b Assembly) -> &Self { + pub fn deref<'a, 'b: 'a>(&'a self, asm: &'b Assembly) -> &'a Self { match self { Type::Ptr(inner) | Type::Ref(inner) => asm.get_type(*inner), _ => panic!(), diff --git a/test/arthm/num_test.rs b/test/arthm/num_test.rs index be2edc1c..fede9279 100644 --- a/test/arthm/num_test.rs +++ b/test/arthm/num_test.rs @@ -18,6 +18,9 @@ #![no_std] use core::num::NonZero; include!("../common.rs"); +extern "C" { + fn ldexpf(arg: f32, exp: f32) -> f32; +} #[inline(never)] #[no_mangle] fn check_float_nan() { @@ -37,6 +40,7 @@ pub fn test_variadic_fnptr() { test!(!(p < q)); } fn main() { + unsafe { black_box(ldexpf(black_box(434.43), 1232.3434)) }; check_float_nan(); const A: u32 = 0b0101100; const B: u32 = 0b0100001;