From 82e989cfc3171dc50b91568828b84641f4686986 Mon Sep 17 00:00:00 2001 From: Stuart Pernsteiner Date: Fri, 5 Jul 2024 15:36:31 -0700 Subject: [PATCH] analyze: implement calloc rewrite --- c2rust-analyze/src/rewrite/expr/convert.rs | 30 +++++++++++++++++----- c2rust-analyze/src/rewrite/expr/mir_op.rs | 26 ++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/c2rust-analyze/src/rewrite/expr/convert.rs b/c2rust-analyze/src/rewrite/expr/convert.rs index e62541544..3815eb4cf 100644 --- a/c2rust-analyze/src/rewrite/expr/convert.rs +++ b/c2rust-analyze/src/rewrite/expr/convert.rs @@ -290,17 +290,33 @@ impl<'tcx> ConvertVisitor<'tcx> { ref zero_ty, elem_size, single, + } + | mir_op::RewriteKind::CallocSafe { + ref zero_ty, + elem_size, + single, } => { // `malloc(n)` -> `Box::new(z)` or similar assert!(matches!(hir_rw, Rewrite::Identity)); let zeroize_expr = generate_zeroize_expr(zero_ty); - let mut stmts = vec![ - Rewrite::Let(vec![("byte_len".into(), self.get_subexpr(ex, 0))]), - Rewrite::Let1( - "n".into(), - Box::new(format_rewrite!("byte_len as usize / {elem_size}")), - ), - ]; + let mut stmts = match *rw { + mir_op::RewriteKind::MallocSafe { .. } => vec![ + Rewrite::Let(vec![("byte_len".into(), self.get_subexpr(ex, 0))]), + Rewrite::Let1( + "n".into(), + Box::new(format_rewrite!("byte_len as usize / {elem_size}")), + ), + ], + mir_op::RewriteKind::CallocSafe { .. } => vec![ + Rewrite::Let(vec![ + ("count".into(), self.get_subexpr(ex, 0)), + ("size".into(), self.get_subexpr(ex, 1)), + ]), + format_rewrite!("assert_eq!(size, {elem_size})"), + Rewrite::Let1("n".into(), Box::new(format_rewrite!("count as usize"))), + ], + _ => unreachable!(), + }; let expr = if single { stmts.push(Rewrite::Text("assert_eq!(n, 1)".into())); format_rewrite!("Box::new({})", zeroize_expr) diff --git a/c2rust-analyze/src/rewrite/expr/mir_op.rs b/c2rust-analyze/src/rewrite/expr/mir_op.rs index 54187cf10..968e9528f 100644 --- a/c2rust-analyze/src/rewrite/expr/mir_op.rs +++ b/c2rust-analyze/src/rewrite/expr/mir_op.rs @@ -109,6 +109,11 @@ pub enum RewriteKind { src_single: bool, dest_single: bool, }, + CallocSafe { + zero_ty: ZeroizeType, + elem_size: u64, + single: bool, + }, /// Convert `Option` to `T` by calling `.unwrap()`. OptionUnwrap, @@ -641,7 +646,7 @@ impl<'a, 'tcx> ExprRewriteVisitor<'a, 'tcx> { }); } - Callee::Malloc => { + ref callee @ (Callee::Malloc | Callee::Calloc) => { self.enter_rvalue(|v| { let dest_lty = v.acx.type_of(destination); let dest_pointee = v.pointee_lty(dest_lty); @@ -667,11 +672,20 @@ impl<'a, 'tcx> ExprRewriteVisitor<'a, 'tcx> { None => return, }; - v.emit(RewriteKind::MallocSafe { - zero_ty, - elem_size, - single, - }); + let rw = match *callee { + Callee::Malloc => RewriteKind::MallocSafe { + zero_ty, + elem_size, + single, + }, + Callee::Calloc => RewriteKind::CallocSafe { + zero_ty, + elem_size, + single, + }, + _ => unreachable!(), + }; + v.emit(rw); // `MallocSafe` produces either `Box` or `Box<[T]>`. Emit a cast // from that type to the required output type.