From e3057de8297c857d064325cc2810804e2d441f2d Mon Sep 17 00:00:00 2001 From: Stuart Pernsteiner Date: Fri, 2 Aug 2024 10:58:44 -0700 Subject: [PATCH] analyze: run equiv remapping before pointee_type pass --- c2rust-analyze/src/analyze.rs | 70 ++++++++++------------- c2rust-analyze/src/pointee_type/mod.rs | 33 ----------- c2rust-analyze/src/pointee_type/solve.rs | 4 -- c2rust-analyze/tests/filecheck/pointee.rs | 4 +- 4 files changed, 33 insertions(+), 78 deletions(-) diff --git a/c2rust-analyze/src/analyze.rs b/c2rust-analyze/src/analyze.rs index 484c03406..008baaf63 100644 --- a/c2rust-analyze/src/analyze.rs +++ b/c2rust-analyze/src/analyze.rs @@ -587,45 +587,18 @@ fn run(tcx: TyCtxt) { do_recent_writes(&gacx, &mut func_info, &all_fn_ldids); // ---------------------------------- - // Infer pointee types - // ---------------------------------- - - let mut global_pointee_types = do_pointee_type(&mut gacx, &mut func_info, &all_fn_ldids); - debug_print_pointee_types( - &mut gacx, - &mut func_info, - &all_fn_ldids, - &global_pointee_types, - ); - - // ---------------------------------- - // Compute dataflow constraints + // Remap `PointerId`s by equivalence class // ---------------------------------- - // Initial pass to assign local `PointerId`s and gather equivalence constraints, which state - // that two pointer types must be converted to the same reference type. Some additional data - // computed during this the process is kept around for use in later passes. + // Initial pass to gather equivalence constraints, which state that two pointer types must be + // converted to the same reference type. Some additional data computed during this the process + // is kept around for use in later passes. let global_equiv = build_equiv_constraints(&mut gacx, &mut func_info, &all_fn_ldids); - build_dataflow_constraints( - &mut gacx, - &mut func_info, - &all_fn_ldids, - &global_pointee_types, - ); - - // ---------------------------------- - // Remap `PointerId`s by equivalence class - // ---------------------------------- // Remap pointers based on equivalence classes, so all members of an equivalence class now use // the same `PointerId`. let (global_counter, global_equiv_map) = global_equiv.renumber(); debug!("global_equiv_map = {global_equiv_map:?}"); - pointee_type::remap_pointers_global( - &mut global_pointee_types, - &global_equiv_map, - global_counter.num_pointers(), - ); gacx.remap_pointers(&global_equiv_map, global_counter.num_pointers()); let mut local_counter = global_counter.into_local(); @@ -637,15 +610,6 @@ fn run(tcx: TyCtxt) { .local_equiv .renumber(&global_equiv_map, &mut local_counter); debug!("local_equiv_map = {local_equiv_map:?}"); - if info.local_pointee_types.is_set() { - pointee_type::remap_pointers_local( - &mut global_pointee_types, - &mut info.local_pointee_types, - global_equiv_map.and(&local_equiv_map), - local_base, - local_count, - ); - } info.acx_data.remap_pointers( &mut gacx, global_equiv_map.and(&local_equiv_map), @@ -659,6 +623,32 @@ fn run(tcx: TyCtxt) { info.local_equiv.clear(); } + // ---------------------------------- + // Infer pointee types + // ---------------------------------- + + // This runs after equivalence class remapping because it lets us get better pointee results in + // pointer-to-pointer cases without implementing full type unification. + + let global_pointee_types = do_pointee_type(&mut gacx, &mut func_info, &all_fn_ldids); + debug_print_pointee_types( + &mut gacx, + &mut func_info, + &all_fn_ldids, + &global_pointee_types, + ); + + // ---------------------------------- + // Compute dataflow constraints + // ---------------------------------- + + build_dataflow_constraints( + &mut gacx, + &mut func_info, + &all_fn_ldids, + &global_pointee_types, + ); + // ---------------------------------- // Build initial assignment // ---------------------------------- diff --git a/c2rust-analyze/src/pointee_type/mod.rs b/c2rust-analyze/src/pointee_type/mod.rs index 0075bcc30..6ee27621a 100644 --- a/c2rust-analyze/src/pointee_type/mod.rs +++ b/c2rust-analyze/src/pointee_type/mod.rs @@ -1,7 +1,5 @@ use crate::context::AnalysisCtxt; -use crate::pointer_id::{GlobalPointerTable, LocalPointerTable, PointerId, PointerTable}; use rustc_middle::mir::Body; -use std::mem; mod constraint_set; mod solve; @@ -17,34 +15,3 @@ pub fn generate_constraints<'tcx>( ) -> ConstraintSet<'tcx> { type_check::visit(acx, mir, vars) } - -pub fn remap_pointers_global<'tcx>( - pointee_types: &mut GlobalPointerTable>, - map: &GlobalPointerTable, - count: usize, -) { - let mut old = mem::replace(pointee_types, GlobalPointerTable::new(count)); - let new = pointee_types; - for (old_ptr, old_val) in old.iter_mut() { - // If there are multiple old pointers that map to the same new pointer, merge their sets. - new[map[old_ptr]].merge(mem::take(old_val)); - } -} - -pub fn remap_pointers_local<'tcx>( - global_pointee_types: &mut GlobalPointerTable>, - local_pointee_types: &mut LocalPointerTable>, - map: PointerTable, - local_base: u32, - local_count: usize, -) { - let mut old = mem::replace( - local_pointee_types, - LocalPointerTable::new(local_base, local_count), - ); - let mut new = global_pointee_types.and_mut(local_pointee_types); - for (old_ptr, old_val) in old.iter_mut() { - // If there are multiple old pointers that map to the same new pointer, merge their sets. - new[map[old_ptr]].merge(mem::take(old_val)); - } -} diff --git a/c2rust-analyze/src/pointee_type/solve.rs b/c2rust-analyze/src/pointee_type/solve.rs index cf24055ee..66e35642b 100644 --- a/c2rust-analyze/src/pointee_type/solve.rs +++ b/c2rust-analyze/src/pointee_type/solve.rs @@ -145,10 +145,6 @@ impl<'tcx> PointeeTypes<'tcx> { } } - pub fn merge(&mut self, other: PointeeTypes<'tcx>) { - self.tys.extend(other.tys); - } - pub fn simplify(&mut self, vars: &VarTable<'tcx>) { let mut add = Vec::new(); let mut remove = Vec::new(); diff --git a/c2rust-analyze/tests/filecheck/pointee.rs b/c2rust-analyze/tests/filecheck/pointee.rs index 290d030bb..46120a15f 100644 --- a/c2rust-analyze/tests/filecheck/pointee.rs +++ b/c2rust-analyze/tests/filecheck/pointee.rs @@ -34,7 +34,9 @@ unsafe fn remove_cast() { unsafe fn malloc_fresh() { let mut p = 0 as *mut libc::c_void; let fresh = &mut p; - // CHECK: malloc(4) + // CHECK-NOT: malloc(4) + // CHECK: Box::new + // CHECK-NOT: malloc(4) let q = malloc(4); *fresh = q; *(p as *mut i32) = 1;