From 02af17c6e9600b886d23fb95fd6fddb171a6c0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Wed, 25 Sep 2024 01:29:59 +0200 Subject: [PATCH] Added a missing file --- cilly/src/v2/il_exporter/mod.rs | 88 +++++++++++++++++++++++------ cilly/src/v2/opt/mod.rs | 34 ++++------- cilly/src/v2/typecheck.rs | 2 +- src/terminator/intrinsics/utilis.rs | 9 ++- test/intrinsics/atomics.rs | 15 +++++ test/std/uninit_fill.rs | 26 +++++++++ 6 files changed, 131 insertions(+), 43 deletions(-) create mode 100644 test/std/uninit_fill.rs diff --git a/cilly/src/v2/il_exporter/mod.rs b/cilly/src/v2/il_exporter/mod.rs index 9e9918d9..6af0c699 100644 --- a/cilly/src/v2/il_exporter/mod.rs +++ b/cilly/src/v2/il_exporter/mod.rs @@ -205,7 +205,7 @@ impl ILExporter { writeln!(out,"// targets:{}",block.targets(asm).count())?; writeln!(out," bb{}:",block.block_id())?; for root in block.roots(){ - self.export_root(asm,out,*root,false,sig,locals)?; + self.export_root(asm,out,*root,false, block.handler().is_some(),sig,locals)?; } if let Some(handler) = block.handler(){ if Some(handler) == blocks_iter.peek().and_then(|block|block.handler()){ @@ -219,7 +219,7 @@ impl ILExporter { for hblock in handler{ writeln!(out," h{}_{}:",block.block_id(),hblock.block_id())?; for root in hblock.roots(){ - self.export_root(asm,out,*root,true,sig,locals)?; + self.export_root(asm,out,*root,true,false,sig,locals)?; } } writeln!(out,"}}")?; @@ -709,12 +709,14 @@ impl ILExporter { } } } + #[allow(clippy::too_many_arguments)] fn export_root( &self, asm: &mut super::Assembly, out: &mut impl Write, root: RootIdx, is_handler: bool, + has_handler: bool, sig: SigIdx, locals: &[LocalDef], ) -> std::io::Result<()> { @@ -764,9 +766,13 @@ impl ILExporter { writeln!(out, "beq bb{}", branch.0) } else if is_handler { writeln!(out, "beq h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "beq jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just blt.un + else { + writeln!(out, "beq bb{}", branch.1) + } } Some(BranchCond::Ne(a, b)) => { self.export_node(asm, out, *a, sig, locals)?; @@ -775,9 +781,13 @@ impl ILExporter { writeln!(out, "bne.un bb{}", branch.0) } else if is_handler { writeln!(out, "bne.un h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "bne.un jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just blt.un + else { + writeln!(out, "bne.un bb{}", branch.1) + } } Some(BranchCond::Lt(a, b, kind)) => { self.export_node(asm, out, *a, sig, locals)?; @@ -788,18 +798,26 @@ impl ILExporter { writeln!(out, "blt bb{}", branch.0) } else if is_handler { writeln!(out, "blt h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "blt jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just blt + else { + writeln!(out, "blt bb{}", branch.1) + } } super::cilroot::CmpKind::Unordered | super::cilroot::CmpKind::Unsigned => { if branch.1 == 0 { writeln!(out, "blt.un bb{}", branch.0) } else if is_handler { writeln!(out, "blt.un h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "blt.un jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just blt.un + else { + writeln!(out, "blt.un bb{}", branch.1) + } } } } @@ -812,18 +830,26 @@ impl ILExporter { writeln!(out, "bgt bb{}", branch.0) } else if is_handler { writeln!(out, "bgt h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "bgt jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just bgt + else { + writeln!(out, "bgt bb{}", branch.1) + } } super::cilroot::CmpKind::Unordered | super::cilroot::CmpKind::Unsigned => { if branch.1 == 0 { writeln!(out, "bgt.un bb{}", branch.0) } else if is_handler { writeln!(out, "bgt.un h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "bgt.un jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just bgt.un + else { + writeln!(out, "bgt.un bb{}", branch.1) + } } } } @@ -836,18 +862,26 @@ impl ILExporter { writeln!(out, "ble bb{}", branch.0) } else if is_handler { writeln!(out, "ble h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "ble jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just ble + else { + writeln!(out, "ble bb{}", branch.1) + } } super::cilroot::CmpKind::Unordered | super::cilroot::CmpKind::Unsigned => { if branch.1 == 0 { writeln!(out, "ble.un bb{}", branch.0) } else if is_handler { writeln!(out, "ble.un h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "ble.un jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just ble.un + else { + writeln!(out, "ble.un bb{}", branch.1) + } } } } @@ -860,18 +894,26 @@ impl ILExporter { writeln!(out, "bge bb{}", branch.0) } else if is_handler { writeln!(out, "bge h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "bge jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just bge + else { + writeln!(out, "bge bb{}", branch.1) + } } super::cilroot::CmpKind::Unordered | super::cilroot::CmpKind::Unsigned => { if branch.1 == 0 { writeln!(out, "bge.un bb{}", branch.0) } else if is_handler { writeln!(out, "bge.un h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "bge.un jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just bge.un + else { + writeln!(out, "bge.un bb{}", branch.1) + } } } } @@ -881,9 +923,13 @@ impl ILExporter { writeln!(out, "brtrue bb{}", branch.0) } else if is_handler { writeln!(out, "brtrue h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "brtrue jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just brtrue + else { + writeln!(out, "brtrue bb{}", branch.1) + } } Some(BranchCond::False(cond)) => { self.export_node(asm, out, *cond, sig, locals)?; @@ -891,9 +937,13 @@ impl ILExporter { writeln!(out, "brfalse bb{}", branch.0) } else if is_handler { writeln!(out, "brfalse h{}_{}", branch.0, branch.1) - } else { + } else if has_handler { writeln!(out, "brfalse jp{}_{}", branch.0, branch.1) } + // If the handler was removed, we can just brfalse + else { + writeln!(out, "brfalse bb{}", branch.1) + } } None => { if branch.1 == 0 { @@ -902,9 +952,13 @@ impl ILExporter { writeln!(out, "br h{}_{}", branch.0, branch.1) } // If it is not a handler, then this is the only block in this try, then all jumps are extern, then we can just use leave - else { + else if has_handler { writeln!(out, "leave bb{}", branch.1) } + // If the handler was removed, we can just br + else { + writeln!(out, "br bb{}", branch.1) + } } }, super::CILRoot::SourceFileInfo { @@ -1063,8 +1117,10 @@ impl ILExporter { super::CILRoot::ExitSpecialRegion { target, source } => { if is_handler { writeln!(out, "h{source}_{target}: leave bb{target}") - } else { + } else if has_handler { writeln!(out, "jp{source}_{target}: leave bb{target}") + } else { + Ok(()) } } super::CILRoot::ReThrow => { diff --git a/cilly/src/v2/opt/mod.rs b/cilly/src/v2/opt/mod.rs index 23a61b06..35f7e454 100644 --- a/cilly/src/v2/opt/mod.rs +++ b/cilly/src/v2/opt/mod.rs @@ -504,22 +504,6 @@ impl MethodDef { self.implementation_mut().realloc_locals(asm); } - if fuel.consume(1) { - // Remove unneded SFI - if let Some(roots) = self.iter_roots_mut() { - let mut peekable = (roots).into_iter().peekable(); - while let Some(curr) = peekable.next() { - let Some(peek) = peekable.peek() else { - continue; - }; - if let (CILRoot::SourceFileInfo { .. }, CILRoot::SourceFileInfo { .. }) = - (asm.get_root(*curr), asm.get_root(**peek)) - { - *curr = nop; - } - } - } - } if fuel.consume(15) { if let Some(roots) = self.iter_roots_mut() { let roots: Vec<_> = roots @@ -536,14 +520,11 @@ impl MethodDef { continue; }; match (asm.get_root(*curr), asm.get_root(**peek)) { + (CILRoot::SourceFileInfo { .. }, CILRoot::SourceFileInfo { .. }) => { + *curr = nop + } // If a rethrow is followed by a rethrow, this is effectively just a single rethrow (CILRoot::ReThrow, CILRoot::ReThrow) => *curr = nop, - /*// If SFI is followed by an uncodtional branch, then it has no effect, then it can be safely ommited. - (CILRoot::SourceFileInfo { .. }, CILRoot::Branch(info)) - if is_branch_unconditional(info) => - { - *curr = nop - }*/ // If we return var a immeditaly after assigining it, we can just return it. (CILRoot::StLoc(set_loc, tree), CILRoot::Ret(ret_loc)) => { let CILNode::LdLoc(ret_loc) = asm.get_node(*ret_loc) else { @@ -588,7 +569,14 @@ impl MethodDef { match root { CILRoot::Pop(pop) => match asm.get_node(pop) { CILNode::LdLoc(_) => CILRoot::Nop, - _ => root, + _ => { + let has_side_effects = cache.has_side_effects(pop, asm); + if has_side_effects { + root + } else { + CILRoot::Nop + } + } }, CILRoot::Call(info) => { inline_trivial_call_root(info.0, &info.1, *root_fuel, asm) diff --git a/cilly/src/v2/typecheck.rs b/cilly/src/v2/typecheck.rs index adde5acc..1bbe3c96 100644 --- a/cilly/src/v2/typecheck.rs +++ b/cilly/src/v2/typecheck.rs @@ -498,7 +498,7 @@ impl CILNode { let arg = asm.get_node(*arg).clone(); let arg_type = arg.typecheck(sig, locals, asm)?; match arg_type { - Type::Int(_) | Type::Float(_) => Ok(arg_type), + Type::Int(_) | Type::Float(_) | Type::Ptr(_) => Ok(arg_type), _ => Err(TypeCheckError::WrongUnOpArgs { tpe: arg_type, op: op.clone(), diff --git a/src/terminator/intrinsics/utilis.rs b/src/terminator/intrinsics/utilis.rs index 051e0c60..28d8d77a 100644 --- a/src/terminator/intrinsics/utilis.rs +++ b/src/terminator/intrinsics/utilis.rs @@ -19,7 +19,7 @@ pub fn atomic_add(addr: CILNode, addend: CILNode, tpe: Type, asm: &mut Assembly) ), true ), - [addr, addend.clone()] + [addr, addend] ) } Type::Int(Int::U32 | Int::I32) => { @@ -33,7 +33,7 @@ pub fn atomic_add(addr: CILNode, addend: CILNode, tpe: Type, asm: &mut Assembly) ), true ), - [addr, addend.clone()] + [addr, addend] ) } Type::Int(Int::USize | Int::ISize) | Type::Ptr(_) => call!( @@ -45,7 +45,10 @@ pub fn atomic_add(addr: CILNode, addend: CILNode, tpe: Type, asm: &mut Assembly) ), true ), - [addr, addend.clone()] + [ + addr.cast_ptr(asm.nptr(Type::Int(Int::USize))), + addend.cast_ptr(Type::Int(Int::USize)) + ] ), _ => todo!(), diff --git a/test/intrinsics/atomics.rs b/test/intrinsics/atomics.rs index 64c5c080..833cc915 100644 --- a/test/intrinsics/atomics.rs +++ b/test/intrinsics/atomics.rs @@ -91,4 +91,19 @@ fn ptr_bitops_tagging() { ptr.map_addr(|a| a | 0b1001) ); test_eq!(atom.load(SeqCst), ptr); + //add_data(); +} +fn add_data() { + let atom = AtomicPtr::::new(core::ptr::null_mut()); + test_eq!(atom.fetch_ptr_add(1, SeqCst).addr(), 0); + test_eq!(atom.load(SeqCst).addr(), 8); + + test_eq!(atom.fetch_byte_add(1, SeqCst).addr(), 8); + test_eq!(atom.load(SeqCst).addr(), 9); + + test_eq!(atom.fetch_ptr_sub(1, SeqCst).addr(), 9); + test_eq!(atom.load(SeqCst).addr(), 1); + + test_eq!(atom.fetch_byte_sub(1, SeqCst).addr(), 1); + test_eq!(atom.load(SeqCst).addr(), 0); } diff --git a/test/std/uninit_fill.rs b/test/std/uninit_fill.rs new file mode 100644 index 00000000..eed346fb --- /dev/null +++ b/test/std/uninit_fill.rs @@ -0,0 +1,26 @@ +#![feature( + maybe_uninit_fill, + unsized_const_params, + core_intrinsics, + lang_items, + start +)] +#![allow( + unused_variables, + incomplete_features, + unused_imports, + dead_code, + internal_features +)] +#![no_std] +include!("../common.rs"); +extern "C" { + fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32; +} +use core::mem::MaybeUninit; +fn main() { + let mut dst = [MaybeUninit::new(255); 64]; + let expect = [0; 64]; + + assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); +}