From 5ad88d854ab507dadb1010d8a63459b698a3be61 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 19 Jul 2024 22:12:05 -0700 Subject: [PATCH 01/17] Handle nested fields and other projections Record field and index projections for pointers by recording a Project event with a base and target pointer pair. --- analysis/runtime/src/events.rs | 8 +- analysis/runtime/src/handlers.rs | 4 +- dynamic_instrumentation/src/instrument.rs | 253 ++++++++++++------ dynamic_instrumentation/src/into_operand.rs | 14 +- .../src/mir_utils/deref.rs | 24 -- pdg/src/builder.rs | 8 +- pdg/src/graph.rs | 8 +- pdg/src/info.rs | 89 +++--- 8 files changed, 238 insertions(+), 170 deletions(-) diff --git a/analysis/runtime/src/events.rs b/analysis/runtime/src/events.rs index 9338119b39..1dea82d532 100644 --- a/analysis/runtime/src/events.rs +++ b/analysis/runtime/src/events.rs @@ -30,10 +30,8 @@ pub enum EventKind { CopyRef, - /// Field projection. Used for operations like `_2 = &(*_1).0`. Nested field - /// accesses like `_4 = &(*_1).x.y.z` are broken into multiple `Node`s, each - /// covering one level. - Field(Pointer, u32), + /// Projection. Used for operations like `_2 = &(*_1).0`. + Project(Pointer, Pointer), Alloc { size: usize, @@ -90,7 +88,7 @@ impl Debug for EventKind { use EventKind::*; match *self { CopyPtr(ptr) => write!(f, "copy(0x{:x})", ptr), - Field(ptr, id) => write!(f, "field(0x{:x}, {})", ptr, id), + Project(ptr, new_ptr) => write!(f, "project(0x{:x}, 0x{:x})", ptr, new_ptr), Alloc { size, ptr } => { write!(f, "malloc({}) -> 0x{:x}", size, ptr) } diff --git a/analysis/runtime/src/handlers.rs b/analysis/runtime/src/handlers.rs index 03b2075f66..1b121656d2 100644 --- a/analysis/runtime/src/handlers.rs +++ b/analysis/runtime/src/handlers.rs @@ -110,10 +110,10 @@ pub const HOOK_FUNCTIONS: &[&str] = &[ hook_fn!(offset), ]; -pub fn ptr_field(mir_loc: MirLocId, ptr: usize, field_id: u32) { +pub fn ptr_project(mir_loc: MirLocId, ptr: usize, new_ptr: usize) { RUNTIME.send_event(Event { mir_loc, - kind: EventKind::Field(ptr, field_id), + kind: EventKind::Project(ptr, new_ptr), }); } diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index ec31abd0ca..7bcde0f143 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -8,7 +8,9 @@ use indexmap::IndexSet; use log::{debug, trace}; use rustc_ast::Mutability; use rustc_index::vec::Idx; -use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::visit::{ + MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, +}; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, BorrowKind, ClearCrossCrate, HasLocalDecls, Local, LocalDecl, Location, Operand, Place, PlaceElem, ProjectionElem, Rvalue, Safety, SourceInfo, SourceScope, @@ -24,7 +26,8 @@ use std::sync::Mutex; use crate::arg::{ArgKind, InstrumentationArg}; use crate::hooks::Hooks; -use crate::mir_utils::{has_outer_deref, remove_outer_deref, strip_all_deref}; +use crate::into_operand::IntoOperand; +use crate::mir_utils::remove_outer_deref; use crate::point::InstrumentationApplier; use crate::point::{cast_ptr_to_usize, InstrumentationPriority}; use crate::point::{ @@ -343,31 +346,175 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { self.super_place(place, context, location); - let field_fn = self.hooks().find("ptr_field"); + if !place.is_indirect() { + return; + } + if !context.is_use() { + return; + } + + let copy_fn = self.hooks().find("ptr_copy"); + let project_fn = self.hooks().find("ptr_project"); + let load_fn = self.hooks().find("ptr_load"); + let load_value_fn = self.hooks().find("load_value"); + let store_fn = self.hooks().find("ptr_store"); + + let tcx = self.tcx(); + + // Instrument nested projections and derefs + let mut proj_iter = place.iter_projections().peekable(); - let base_ty = self.local_decls()[place.local].ty; + // Skip over the initial projections of the local since we do + // not want to take its address; we only care about the ones + // past the first dereference since at that point we have an + // actual pointer. + while let Some((_, elem)) = proj_iter.peek() { + if matches!(elem, PlaceElem::Deref) { + break; + } + let _ = proj_iter.next(); + } + + while let Some((inner_deref_base, PlaceElem::Deref)) = proj_iter.next() { + // Find the next Deref or end of projections + let (outer_deref_base, have_outer_deref) = loop { + match proj_iter.peek() { + Some((base, PlaceElem::Deref)) => break (base.clone(), true), + // Reached the end, we can use the full place + None => break (place.as_ref(), false), + _ => { + let _ = proj_iter.next(); + } + } + }; - // Instrument field projections on raw-ptr places - if is_region_or_unsafe_ptr(base_ty) && context.is_use() { - for (base, elem) in place.iter_projections() { - if let PlaceElem::Field(field, _) = elem { - let proj_dest = || { + // We need to convert the inner base into an operand that + // we can pass to `.source()` below since we don't have + // an implementation of `Source for PlaceRef`. + let inner_deref_op: Operand = inner_deref_base.op(tcx); + + // We have some other elements between the two projections + let have_other_projections = + outer_deref_base.projection.len() - inner_deref_base.projection.len() > 1; + if have_other_projections { + let dest = || { + if have_outer_deref { // Only the last field projection gets a destination - self.assignment() - .as_ref() - .map(|(dest, _)| dest) - .copied() - .filter(|_| base.projection.len() == place.projection.len() - 1) - }; - self.loc(location, location, field_fn) - .arg_var(place.local) - .arg_index_of(field) - .source(place) - .dest_from(proj_dest) - .add_to(self); + return None; + } + if !context.is_borrow() + && !matches!( + context, + NonMutatingUse(NonMutatingUseContext::AddressOf) + | MutatingUse(MutatingUseContext::AddressOf) + ) + { + // The only cases we care about here are the same as + // `copy_fn`: taking the address of a projection, + // e.g., `_1 = &((*_2).x)`. + return None; + } + self.assignment().as_ref().map(|(dest, _)| dest).copied() + }; + + // There are non-deref projection elements between the two derefs. + // Add a Project event between the start pointer of those field/index + // projections and their final address. + // + // E.g. for `p.*` and `p.*.x.y.*` the inner base is `p` and + // the outer base is `p.*.x.y`. The inner one is already a pointer + // so we pass it by value, but the outer base is a field of + // a structure (pointed to by the inner base), + // which means we need to take the address of the field. + // The event we emit is `Project(p, &(p.*.x.y))`. + self.loc(location, location, project_fn) + .arg_var(inner_deref_base) + .arg_addr_of(outer_deref_base.clone()) + .source(&inner_deref_op) + .dest_from(dest) + .add_to(self); + } + + use PlaceContext::*; + if let Some(ptr_fn) = match context { + // We are just loading the value of the inner dereference + // so we can offset from it to get the pointer of the outer one + _ if have_outer_deref => Some(load_fn), + + NonMutatingUse(NonMutatingUseContext::Copy) + | NonMutatingUse(NonMutatingUseContext::Move) => Some(load_fn), + + // We get here with !have_outer_deref, so this is the + // full access to the final place. Use the actual operation + // that depends on the context the place is used in. + MutatingUse(MutatingUseContext::Store) + | MutatingUse(MutatingUseContext::Call) + | MutatingUse(MutatingUseContext::AsmOutput) => Some(store_fn), + + NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + | NonMutatingUse(NonMutatingUseContext::SharedBorrow) + | NonMutatingUse(NonMutatingUseContext::UniqueBorrow) + | NonMutatingUse(NonMutatingUseContext::AddressOf) + | MutatingUse(MutatingUseContext::Borrow) + | MutatingUse(MutatingUseContext::AddressOf) => Some(copy_fn), + + NonMutatingUse(NonMutatingUseContext::Inspect) + | NonMutatingUse(NonMutatingUseContext::Projection) + | MutatingUse(MutatingUseContext::SetDiscriminant) + | MutatingUse(MutatingUseContext::Deinit) + | MutatingUse(MutatingUseContext::Yield) + | MutatingUse(MutatingUseContext::Drop) + | MutatingUse(MutatingUseContext::Projection) + | MutatingUse(MutatingUseContext::Retag) + | NonUse(_) => None, + } { + let dest = || { + // The only pattern we can handle here is + // taking an address of a Deref, e.g., + // `_1 = &(*_2)`. + if ptr_fn != copy_fn { + return None; + } + if have_other_projections { + // Projections are handled separately above. + return None; + } + self.assignment().as_ref().map(|(dest, _)| dest).copied() + }; + + // We take the address of the outer dereference here. + // E.g. `LoadAddr(&(p.*.x.y))` + let ib = self + .loc(location, location, ptr_fn) + .arg_addr_of(outer_deref_base) + .source(&inner_deref_op) + .dest_from(dest); + + // If we are copying a pointer with projections, e.g. + // `_1 = &(*_2).x`, we emit that as a Project event instead. + if ptr_fn != copy_fn || !have_other_projections { + ib.add_to(self); } } + + if have_outer_deref { + // Add an event for loading the base of the next projection. + // Note that if the deref is followed by other projections, + // we need to include all of them, e.g., if there is a field + // then we're loading from it and not the base structure. + // This happens to be the same as the base of the outer deref, + // so we just use that as the value. + // + // E.g. for `p.*.x.y.*` the outer base is `p.*.x.y` + // and we emit `LoadValue(p.*.x.y)`. + self.loc(location, location, load_value_fn) + .arg_var(outer_deref_base.clone()) + .add_to(self); + } } + // If this algorithm is correct, + // we should have consumed the entire iterator + assert!(proj_iter.peek().is_none()); } fn visit_assign(&mut self, dest: &Place<'tcx>, value: &Rvalue<'tcx>, location: Location) { @@ -377,9 +524,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { let ptr_to_int_fn = self.hooks().find("ptr_to_int"); let load_value_fn = self.hooks().find("load_value"); let store_value_fn = self.hooks().find("store_value"); - let store_fn = self.hooks().find("ptr_store"); let store_addr_taken_fn = self.hooks().find("ptr_store_addr_taken"); - let load_fn = self.hooks().find("ptr_load"); let dest = *dest; self.with_assignment((dest, value.clone()), |this| { @@ -391,7 +536,6 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { let op_ty = |op: &Operand<'tcx>| op.ty(&locals, ctx); let place_ty = |p: &Place<'tcx>| p.ty(&locals, ctx).ty; - let local_ty = |p: &Place| place_ty(&p.local.into()); let value_ty = value.ty(self, self.tcx()); self.visit_place( @@ -427,33 +571,8 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { _ => (), } - let mut add_load_instr = |p: &Place<'tcx>| { - self.loc(location, location, load_fn) - .arg_var(p.local) - .source(&remove_outer_deref(*p, ctx)) - .add_to(self); - }; - - // add instrumentation for load-from-address operations - match value { - Rvalue::Use(Operand::Copy(p) | Operand::Move(p)) - if p.is_indirect() && is_region_or_unsafe_ptr(local_ty(p)) => - { - add_load_instr(p) - } - _ => (), - } - match value { _ if dest.is_indirect() => { - // Strip all derefs to set base_dest to the pointer that is deref'd - let base_dest = strip_all_deref(&dest, self.tcx()); - - self.loc(location, location, store_fn) - .arg_var(base_dest) - .source(&remove_outer_deref(dest, self.tcx())) - .add_to(self); - if is_region_or_unsafe_ptr(value_ty) { self.loc(location, location.successor_within_block(), store_value_fn) .arg_var(dest) @@ -473,19 +592,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { } } _ if !is_region_or_unsafe_ptr(value_ty) => {} - Rvalue::AddressOf(_, p) - if has_outer_deref(p) - && is_region_or_unsafe_ptr(place_ty(&remove_outer_deref(*p, self.tcx()))) => - { - let source = remove_outer_deref(*p, self.tcx()); - // Instrument which local's address is taken - self.loc(location, location.successor_within_block(), copy_fn) - .arg_var(dest) - .source(&source) - .dest(&dest) - .add_to(self); - } - Rvalue::AddressOf(_, p) => { + Rvalue::AddressOf(_, p) if !p.is_indirect() => { // Instrument which local's address is taken self.loc(location, location.successor_within_block(), addr_local_fn) .arg_var(dest) @@ -531,28 +638,6 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { .dest(&dest) .add_to(self); } - Rvalue::Ref(_, bkind, p) - if has_outer_deref(p) - && is_region_or_unsafe_ptr(place_ty(&remove_outer_deref(*p, self.tcx()))) => - { - // this is a reborrow or field reference, i.e. _2 = &(*_1) - let source = remove_outer_deref(*p, self.tcx()); - if let BorrowKind::Mut { .. } = bkind { - // Instrument which local's address is taken - self.loc(location, location, copy_fn) - .arg_addr_of(*p) - .source(&source) - .dest(&dest) - .add_to(self); - } else { - // Instrument immutable borrows by tracing the reference itself - self.loc(location, location.successor_within_block(), copy_fn) - .arg_var(dest) - .source(&source) - .dest(&dest) - .add_to(self); - }; - } Rvalue::Ref(_, bkind, p) if !p.is_indirect() => { let source = remove_outer_deref(*p, self.tcx()); if let BorrowKind::Mut { .. } = bkind { diff --git a/dynamic_instrumentation/src/into_operand.rs b/dynamic_instrumentation/src/into_operand.rs index fcf0c4ed58..49c9527f5e 100644 --- a/dynamic_instrumentation/src/into_operand.rs +++ b/dynamic_instrumentation/src/into_operand.rs @@ -1,5 +1,5 @@ use rustc_middle::{ - mir::{Constant, ConstantKind, Local, Operand, Place}, + mir::{Constant, ConstantKind, Local, Operand, Place, PlaceRef}, ty::{self, ParamEnv, TyCtxt}, }; use rustc_span::DUMMY_SP; @@ -10,11 +10,21 @@ pub trait IntoOperand<'tcx> { } impl<'tcx> IntoOperand<'tcx> for Place<'tcx> { - fn op(self, _tcx: TyCtxt) -> Operand<'tcx> { + fn op(self, _tcx: TyCtxt<'tcx>) -> Operand<'tcx> { Operand::Copy(self) } } +impl<'tcx> IntoOperand<'tcx> for PlaceRef<'tcx> { + fn op(self, tcx: TyCtxt<'tcx>) -> Operand<'tcx> { + let place = Place { + local: self.local, + projection: tcx.mk_place_elems(self.projection.iter()), + }; + place.op(tcx) + } +} + impl<'tcx> IntoOperand<'tcx> for u32 { fn op(self, tcx: TyCtxt<'tcx>) -> Operand<'tcx> { make_const(tcx, self) diff --git a/dynamic_instrumentation/src/mir_utils/deref.rs b/dynamic_instrumentation/src/mir_utils/deref.rs index 75418e7076..a9b136a273 100644 --- a/dynamic_instrumentation/src/mir_utils/deref.rs +++ b/dynamic_instrumentation/src/mir_utils/deref.rs @@ -3,30 +3,6 @@ use rustc_middle::{ ty::TyCtxt, }; -pub fn has_outer_deref(p: &Place) -> bool { - matches!( - p.iter_projections().last(), - Some((_, ProjectionElem::Deref)) - ) -} - -/// Get the inner-most dereferenced [`Place`]. -pub fn strip_all_deref<'tcx>(p: &Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> { - let mut base_dest = p.as_ref(); - let mut place_ref = p.clone().as_ref(); - while let Some((cur_ref, proj)) = place_ref.last_projection() { - if let ProjectionElem::Deref = proj { - base_dest = cur_ref; - } - place_ref = cur_ref; - } - - Place { - local: base_dest.local, - projection: tcx.intern_place_elems(base_dest.projection), - } -} - /// Strip the initital [`Deref`](ProjectionElem::Deref) /// from a [`projection`](PlaceRef::projection) sequence. pub fn remove_outer_deref<'tcx>(p: Place<'tcx>, tcx: TyCtxt<'tcx>) -> Place<'tcx> { diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index e8b30ef3e4..d14ca1334e 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -44,7 +44,7 @@ impl EventKindExt for EventKind { use EventKind::*; Some(match *self { CopyPtr(lhs) => lhs, - Field(ptr, ..) => ptr, + Project(ptr, ..) => ptr, Free { ptr } => ptr, Ret(ptr) => ptr, LoadAddr(ptr) => ptr, @@ -70,7 +70,7 @@ impl EventKindExt for EventKind { Realloc { .. } => NodeKind::Alloc(1), Free { .. } => NodeKind::Free, CopyPtr(..) | CopyRef => NodeKind::Copy, - Field(_, field) => NodeKind::Field(field.into()), + Project(base_ptr, new_ptr) => NodeKind::Project(new_ptr - base_ptr), LoadAddr(..) => NodeKind::LoadAddr, StoreAddr(..) => NodeKind::StoreAddr, StoreAddrTaken(..) => NodeKind::StoreAddr, @@ -188,7 +188,7 @@ pub fn add_node( if let Some((gid, _)) = latest_assignment { if let Some((nid, n)) = graphs.graphs[gid].nodes.iter_enumerated().rev().next() { - if let NodeKind::Field(..) = n.kind { + if let NodeKind::Project(..) = n.kind { return Some((gid, nid)); } } @@ -197,7 +197,7 @@ pub fn add_node( if !matches!(event.kind, EventKind::AddrOfLocal(..)) && src.projection.is_empty() { latest_assignment - } else if let EventKind::Field(..) = event.kind { + } else if let EventKind::Project(..) = event.kind { latest_assignment } else { provenance diff --git a/pdg/src/graph.rs b/pdg/src/graph.rs index e921018e9a..01b9fa3ff6 100644 --- a/pdg/src/graph.rs +++ b/pdg/src/graph.rs @@ -2,7 +2,7 @@ use c2rust_analysis_rt::mir_loc::{self, DefPathHash, Func}; use c2rust_analysis_rt::mir_loc::{FuncId, MirPlace}; use rustc_index::newtype_index; use rustc_index::vec::IndexVec; -use rustc_middle::mir::{BasicBlock, Field, Local}; +use rustc_middle::mir::{BasicBlock, Local}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fmt::Display; use std::{ @@ -25,9 +25,7 @@ pub enum NodeKind { /// [`Field`] projection. /// /// Used for operations like `_2 = &(*_1).0`. - /// Nested field accesses like `_4 = &(*_1).x.y.z` - /// are broken into multiple [`Node`]s, each covering one level. - Field(#[serde(with = "crate::util::serde::FieldDef")] Field), + Project(usize), /// Pointer arithmetic. /// @@ -121,7 +119,7 @@ impl Display for NodeKind { use NodeKind::*; match self { Copy => write!(f, "copy"), - Field(field) => write!(f, "field.{}", field.as_usize()), + Project(offset) => write!(f, "project.{offset}"), Offset(offset) => write!(f, "offset[{offset}]"), AddrOfLocal(local) => write!(f, "&{local:?}"), _AddrOfStatic(static_) => write!(f, "&'static {static_:?}"), diff --git a/pdg/src/info.rs b/pdg/src/info.rs index ad26b23e5f..1a247acfba 100644 --- a/pdg/src/info.rs +++ b/pdg/src/info.rs @@ -1,5 +1,4 @@ use crate::graph::{Graph, Graphs, Node, NodeId, NodeKind}; -use rustc_middle::mir::Field; use serde::{Deserialize, Serialize}; use std::cmp::{max, min}; use std::collections::{HashMap, HashSet}; @@ -8,6 +7,9 @@ use std::fmt::{self, Debug, Display, Formatter}; /// Force an import of [`Node`] just for docs. const _: Option = None; +/// The identity of a field of a structure is its offset. +type Field = usize; + /// Information generated from the PDG proper that is queried by static analysis. /// /// Includes information about what kinds of [`Node`]s the [`Node`] flows to, @@ -111,7 +113,7 @@ fn collect_children(g: &Graph) -> HashMap)>> { .rev() .filter_map(|(child, child_node)| Some((child_node.source?, child, child_node))) { - if let NodeKind::Field(f) = child_node.kind { + if let NodeKind::Project(f) = child_node.kind { let my_children = children .remove(&child) @@ -224,7 +226,6 @@ mod test { use super::*; use c2rust_analysis_rt::mir_loc::Func; use c2rust_analysis_rt::mir_loc::FuncId; - use rustc_middle::mir::Field; use rustc_middle::mir::Local; fn mk_node(g: &mut Graph, kind: NodeKind, source: Option) -> NodeId { @@ -255,8 +256,8 @@ mod test { mk_node(g, NodeKind::StoreAddr, Some(source)) } - fn mk_field(g: &mut Graph, source: NodeId, field: impl Into) -> NodeId { - mk_node(g, NodeKind::Field(field.into()), Some(source)) + fn mk_project(g: &mut Graph, source: NodeId, field: impl Into) -> NodeId { + mk_node(g, NodeKind::Project(field.into()), Some(source)) } fn mk_offset(g: &mut Graph, source: NodeId, i: isize) -> NodeId { @@ -485,10 +486,10 @@ mod test { // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); // let b = &mut a.x; - let b11 = mk_field(&mut g, a, 0_u32); + let b11 = mk_project(&mut g, a, 0_usize); let b1 = mk_copy(&mut g, b11); // let c = &mut a.y; - let c11 = mk_field(&mut g, a, 1_u32); + let c11 = mk_project(&mut g, a, 1_usize); let c1 = mk_copy(&mut g, c11); // *b = 1; let b2 = mk_store_addr(&mut g, b1); @@ -535,17 +536,17 @@ mod test { // let j = &mut a; let j = mk_copy(&mut g, a); // let b = &mut j.x; - let b11 = mk_field(&mut g, j, 0_u32); + let b11 = mk_project(&mut g, j, 0_usize); let b1 = mk_copy(&mut g, b11); // let c = &mut j.x; - let c11 = mk_field(&mut g, j, 0_u32); + let c11 = mk_project(&mut g, j, 0_usize); let c1 = mk_copy(&mut g, c11); // *b = 1; let b2 = mk_store_addr(&mut g, b1); // *c = 2; let c2 = mk_store_addr(&mut g, c1); // *(a.y) = 3; - let d1 = mk_field(&mut g, a, 1_u32); + let d1 = mk_project(&mut g, a, 1_usize); let d2 = mk_store_addr(&mut g, d1); let pdg = build_pdg(g); @@ -584,7 +585,7 @@ mod test { // let b = &mut a; let b1 = mk_copy(&mut g, a); // let c = &mut a.y; - let c11 = mk_field(&mut g, a, 1_u32); + let c11 = mk_project(&mut g, a, 1_usize); let c1 = mk_copy(&mut g, c11); // *c = 2; let c2 = mk_store_addr(&mut g, c1); @@ -630,10 +631,10 @@ mod test { // let b = &mut a; let b1 = mk_copy(&mut g, a); // let c = &mut b.y; - let c1 = mk_field(&mut g, a, 1_u32); + let c1 = mk_project(&mut g, a, 1_usize); let c2 = mk_copy(&mut g, c1); // let bb = &mut b.y; - let bb = mk_field(&mut g, b1, 1_u32); + let bb = mk_project(&mut g, b1, 1_usize); let bb1 = mk_copy(&mut g, bb); // *c = 2; let c3 = mk_store_addr(&mut g, c2); @@ -669,20 +670,20 @@ mod test { fn lots_of_siblings() { let mut g = Graph::default(); - let (x, y, z) = (0_u32, 1_u32, 2_u32); - let (red, green, _blue) = (0_u32, 1_u32, 2_u32); + let (x, y, z) = (0_usize, 1_usize, 2_usize); + let (red, green, _blue) = (0_usize, 1_usize, 2_usize); // let mut a = ColorPoint { x: 0, y: 0, z: Color { r: 100, g: 100, b: 100 } }; let a = mk_addr_of_local(&mut g, 0_u32); // let b = &mut a.x; - let bb1 = mk_field(&mut g, a, x); + let bb1 = mk_project(&mut g, a, x); let b1 = mk_copy(&mut g, bb1); // let c = &mut a.y; - let cc1 = mk_field(&mut g, a, y); + let cc1 = mk_project(&mut g, a, y); let c1 = mk_copy(&mut g, cc1); // a.z.r = 200; - let x1 = mk_field(&mut g, a, z); - let x2 = mk_field(&mut g, x1, red); + let x1 = mk_project(&mut g, a, z); + let x2 = mk_project(&mut g, x1, red); let x3 = mk_store_addr(&mut g, x2); // *b = 4; let b2 = mk_store_addr(&mut g, b1); @@ -693,19 +694,19 @@ mod test { // *d = ColorPoint { x: 0, y: 0, z: Color { r: 20, g: 200, b: 20 } }; let d2 = mk_store_addr(&mut g, d1); // let e = &mut a.z; - let ee = mk_field(&mut g, a, z); + let ee = mk_project(&mut g, a, z); let e = mk_copy(&mut g, ee); // let f = &mut e.g; - let ff1 = mk_field(&mut g, e, green); + let ff1 = mk_project(&mut g, e, green); let f1 = mk_copy(&mut g, ff1); // let g = &mut e.g; - let ggg = mk_field(&mut g, e, green); + let ggg = mk_project(&mut g, e, green); let gg = mk_copy(&mut g, ggg); // *f = 3; let f2 = mk_store_addr(&mut g, f1); // a.z.r = 100; - let x4 = mk_field(&mut g, a, z); - let x5 = mk_field(&mut g, x4, green); + let x4 = mk_project(&mut g, a, z); + let x5 = mk_project(&mut g, x4, green); let x6 = mk_store_addr(&mut g, x5); let pdg = build_pdg(g); @@ -758,10 +759,10 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0; - let x1 = mk_field(&mut g, a, 0_u32); + let x1 = mk_project(&mut g, a, 0_usize); let x2 = mk_copy(&mut g, x1); // let y = &mut a.1; - let y1 = mk_field(&mut g, a, 1_u32); + let y1 = mk_project(&mut g, a, 1_usize); let y2 = mk_copy(&mut g, y1); // *x = 1; let x3 = mk_store_addr(&mut g, x2); @@ -816,12 +817,12 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.1.0; - let x1 = mk_field(&mut g, a, 1_u32); - let x2 = mk_field(&mut g, x1, 0_u32); + let x1 = mk_project(&mut g, a, 1_usize); + let x2 = mk_project(&mut g, x1, 0_usize); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1.1; - let y1 = mk_field(&mut g, a, 1_u32); - let y2 = mk_field(&mut g, y1, 1_u32); + let y1 = mk_project(&mut g, a, 1_usize); + let y2 = mk_project(&mut g, y1, 1_usize); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); @@ -870,16 +871,16 @@ mod test { //let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); //let mut x = &mut a.1; - let x1 = mk_field(&mut g, a, 1_u32); + let x1 = mk_project(&mut g, a, 1_usize); let x2 = mk_copy(&mut g, x1); //let mut y = &mut a.1; - let y1 = mk_field(&mut g, a, 1_u32); + let y1 = mk_project(&mut g, a, 1_usize); let y2 = mk_copy(&mut g, y1); // *(x.0) = 4; - let x3 = mk_field(&mut g, x2, 0_u32); + let x3 = mk_project(&mut g, x2, 0_usize); let x4 = mk_store_addr(&mut g, x3); // *(y.1) = 2; - let y3 = mk_field(&mut g, y2, 1_u32); + let y3 = mk_project(&mut g, y2, 1_usize); let y4 = mk_store_addr(&mut g, y3); let pdg = build_pdg(g); @@ -924,12 +925,12 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.1.0; - let x1 = mk_field(&mut g, a, 1_u32); - let x2 = mk_field(&mut g, x1, 0_u32); + let x1 = mk_project(&mut g, a, 1_usize); + let x2 = mk_project(&mut g, x1, 0_usize); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1.0; - let y1 = mk_field(&mut g, a, 1_u32); - let y2 = mk_field(&mut g, y1, 0_u32); + let y1 = mk_project(&mut g, a, 1_usize); + let y2 = mk_project(&mut g, y1, 0_usize); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); @@ -986,11 +987,11 @@ mod test { // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0[0]; - let x1 = mk_field(&mut g, a, 1_u32); + let x1 = mk_project(&mut g, a, 1_usize); let x2 = mk_offset(&mut g, x1, 0); let x3 = mk_copy(&mut g, x2); // let y = &mut a.0[1]; - let y1 = mk_field(&mut g, a, 1_u32); + let y1 = mk_project(&mut g, a, 1_usize); let y2 = mk_offset(&mut g, y1, 1); let y3 = mk_copy(&mut g, y2); // *x = 1; @@ -1048,11 +1049,11 @@ mod test { // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0[0]; - let x1 = mk_field(&mut g, a, 0_u32); + let x1 = mk_project(&mut g, a, 0_usize); let x2 = mk_offset(&mut g, x1, 0); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1[0]; - let y1 = mk_field(&mut g, a, 1_u32); + let y1 = mk_project(&mut g, a, 1_usize); let y2 = mk_offset(&mut g, y1, 0); let y3 = mk_copy(&mut g, y2); // *x = 1; @@ -1120,11 +1121,11 @@ mod test { let p = mk_addr_of_local(&mut g, 0_u32); // let x = &mut (*p)[0].0; let x1 = mk_offset(&mut g, p, 0); - let x2 = mk_field(&mut g, x1, 0_u32); + let x2 = mk_project(&mut g, x1, 0_usize); let x3 = mk_copy(&mut g, x2); // let y = &mut (*p)[0].1; let y1 = mk_offset(&mut g, p, 0); - let y2 = mk_field(&mut g, y1, 1_u32); + let y2 = mk_project(&mut g, y1, 1_usize); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); From 9fe12bf0c3778b073ac6c33af1f3ed556f880317 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 23 Jul 2024 23:24:09 -0700 Subject: [PATCH 02/17] Keep track of unique projection combinations in Project Add an index value to Project events to differentiate between different projections with the same pointer offset, e.g., (*p).x and (*p).x.a if a is the first field of the structure. This is implemented as a HashMap> where each element is a unique combination of field projections. The Project key points to an element in this map. The keys are randomly-generated 64-bit keys with very low probability of collision. --- Cargo.lock | 108 ++- analysis/runtime/src/events.rs | 10 +- analysis/runtime/src/handlers.rs | 4 +- analysis/runtime/src/metadata.rs | 19 +- dynamic_instrumentation/Cargo.toml | 1 + dynamic_instrumentation/src/instrument.rs | 44 +- dynamic_instrumentation/src/into_operand.rs | 28 + dynamic_instrumentation/src/point/mod.rs | 7 + pdg/src/builder.rs | 26 +- pdg/src/graph.rs | 6 +- pdg/src/info.rs | 81 +- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 849 +++++++++--------- ...lysis_tests_misc_pdg_snapshot_release.snap | 849 +++++++++--------- 13 files changed, 1109 insertions(+), 923 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7efd0ec8fe..63d149b437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,7 +153,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.16", + "syn 2.0.75", "which", ] @@ -172,6 +172,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "c2rust" version = "0.19.0" @@ -304,6 +310,7 @@ dependencies = [ "itertools", "log", "once_cell", + "rand", "tempfile", "toml_edit", ] @@ -456,7 +463,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.75", ] [[package]] @@ -741,6 +748,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.27.2" @@ -1070,7 +1088,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.75", ] [[package]] @@ -1101,6 +1119,15 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "prettyplease" version = "0.1.25" @@ -1118,7 +1145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617feabb81566b593beb4886fb8c1f38064169dae4dccad0e3220160c3b37203" dependencies = [ "proc-macro2", - "syn 2.0.16", + "syn 2.0.75", ] [[package]] @@ -1156,22 +1183,52 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.57" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.27" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -1282,7 +1339,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.75", ] [[package]] @@ -1372,9 +1429,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1438,7 +1495,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.75", ] [[package]] @@ -1552,6 +1609,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "which" version = "4.4.0" @@ -1758,3 +1821,24 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] diff --git a/analysis/runtime/src/events.rs b/analysis/runtime/src/events.rs index 1dea82d532..a468196e72 100644 --- a/analysis/runtime/src/events.rs +++ b/analysis/runtime/src/events.rs @@ -31,7 +31,11 @@ pub enum EventKind { CopyRef, /// Projection. Used for operations like `_2 = &(*_1).0`. - Project(Pointer, Pointer), + /// The third value is a "projection key" that points to an element + /// of the projections data structure in the metadata. It is used to + /// disambiguate between different projections with the same pointer, + /// e.g., `(*p).x` and `(*p).x.a` where `a` is at offset 0. + Project(Pointer, Pointer, u64), Alloc { size: usize, @@ -88,7 +92,9 @@ impl Debug for EventKind { use EventKind::*; match *self { CopyPtr(ptr) => write!(f, "copy(0x{:x})", ptr), - Project(ptr, new_ptr) => write!(f, "project(0x{:x}, 0x{:x})", ptr, new_ptr), + Project(ptr, new_ptr, idx) => { + write!(f, "project(0x{:x}, 0x{:x}, [{}])", ptr, new_ptr, idx) + } Alloc { size, ptr } => { write!(f, "malloc({}) -> 0x{:x}", size, ptr) } diff --git a/analysis/runtime/src/handlers.rs b/analysis/runtime/src/handlers.rs index 1b121656d2..2724ca5585 100644 --- a/analysis/runtime/src/handlers.rs +++ b/analysis/runtime/src/handlers.rs @@ -110,10 +110,10 @@ pub const HOOK_FUNCTIONS: &[&str] = &[ hook_fn!(offset), ]; -pub fn ptr_project(mir_loc: MirLocId, ptr: usize, new_ptr: usize) { +pub fn ptr_project(mir_loc: MirLocId, ptr: usize, new_ptr: usize, proj_key: u64) { RUNTIME.send_event(Event { mir_loc, - kind: EventKind::Project(ptr, new_ptr), + kind: EventKind::Project(ptr, new_ptr, proj_key), }); } diff --git a/analysis/runtime/src/metadata.rs b/analysis/runtime/src/metadata.rs index 0856bf8d6e..a37d1b2f96 100644 --- a/analysis/runtime/src/metadata.rs +++ b/analysis/runtime/src/metadata.rs @@ -13,6 +13,7 @@ use crate::mir_loc::{Func, FuncId, MirLoc, MirLocId}; pub struct Metadata { pub locs: Vec, pub functions: HashMap, + pub projections: HashMap>, } impl Metadata { @@ -46,11 +47,27 @@ impl FromIterator for Metadata { fn from_iter>(iter: I) -> Self { let mut locs = Vec::new(); let mut functions = HashMap::new(); + let mut projections = HashMap::new(); for metadata in iter { locs.extend(metadata.locs); functions.extend(metadata.functions); + + for (key, proj) in metadata.projections.into_iter() { + projections + .entry(key) + .and_modify(|old_proj| { + panic!( + "Projection key collision at {key:x} between {old_proj:?} and {proj:?}" + ) + }) + .or_insert(proj); + } + } + Self { + locs, + functions, + projections, } - Self { locs, functions } } } diff --git a/dynamic_instrumentation/Cargo.toml b/dynamic_instrumentation/Cargo.toml index fab4a52e2e..8dac511ca0 100644 --- a/dynamic_instrumentation/Cargo.toml +++ b/dynamic_instrumentation/Cargo.toml @@ -27,6 +27,7 @@ toml_edit = "0.19" fs2 = "0.4" env_logger = "0.10" tempfile = "3.3" +rand = "0.8.5" [build-dependencies] c2rust-build-paths = { path = "../c2rust-build-paths", version = "0.19.0" } diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index 7bcde0f143..57d01601cb 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -6,6 +6,7 @@ use fs2::FileExt; use fs_err::OpenOptions; use indexmap::IndexSet; use log::{debug, trace}; +use rand; use rustc_ast::Mutability; use rustc_index::vec::Idx; use rustc_middle::mir::visit::{ @@ -29,6 +30,7 @@ use crate::hooks::Hooks; use crate::into_operand::IntoOperand; use crate::mir_utils::remove_outer_deref; use crate::point::InstrumentationApplier; +use crate::point::ProjectionSet; use crate::point::{cast_ptr_to_usize, InstrumentationPriority}; use crate::point::{ CollectAddressTakenLocals, CollectInstrumentationPoints, RewriteAddressTakenLocals, @@ -39,6 +41,7 @@ use crate::util::Convert; pub struct Instrumenter { mir_locs: Mutex>, functions: Mutex>, + projections: Mutex, u64>>, } impl Instrumenter { @@ -75,7 +78,18 @@ impl Instrumenter { let mut functions = self.functions.lock().unwrap(); let locs = locs.drain(..).collect::>(); let functions = functions.drain().collect::>(); - let metadata = Metadata { locs, functions }; + + let projections = std::mem::take(&mut *self.projections.lock().unwrap()); + let projections = projections + .into_iter() + .map(|(proj_vec, proj_key)| (proj_key, proj_vec)) + .collect(); + + let metadata = Metadata { + locs, + functions, + projections, + }; let bytes = bincode::serialize(&metadata).context("Location serialization failed")?; let mut file = OpenOptions::new() .append(true) @@ -116,6 +130,21 @@ impl Instrumenter { } } +impl ProjectionSet for Instrumenter { + fn add_proj(&self, proj: Vec) -> u64 { + // If this projection isn't already in the map, generate + // a random 64-bit key for it; the probability of collision + // is 1/2^32 (because of the birthday paradox), which should + // be good enough for our use case. + self.projections + .lock() + .unwrap() + .entry(proj) + .or_insert_with(rand::random) + .clone() + } +} + fn is_shared_or_unsafe_ptr(ty: Ty) -> bool { ty.is_unsafe_ptr() || (ty.is_region_ptr() && !ty.is_mutable_ptr()) } @@ -377,7 +406,14 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { while let Some((inner_deref_base, PlaceElem::Deref)) = proj_iter.next() { // Find the next Deref or end of projections + // Meanwhile, collect all `Field`s into a vector that we + // can add to the `projections` IndexSet + let mut fields = vec![]; let (outer_deref_base, have_outer_deref) = loop { + if let Some((_, PlaceElem::Field(idx, _))) = proj_iter.peek() { + fields.push(idx.index()); + } + match proj_iter.peek() { Some((base, PlaceElem::Deref)) => break (base.clone(), true), // Reached the end, we can use the full place @@ -397,6 +433,8 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { let have_other_projections = outer_deref_base.projection.len() - inner_deref_base.projection.len() > 1; if have_other_projections { + let proj_key = self.projections.add_proj(fields); + let dest = || { if have_outer_deref { // Only the last field projection gets a destination @@ -430,6 +468,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { self.loc(location, location, project_fn) .arg_var(inner_deref_base) .arg_addr_of(outer_deref_base.clone()) + .arg_var(proj_key) .source(&inner_deref_op) .dest_from(dest) .add_to(self); @@ -800,7 +839,8 @@ fn instrument_body<'a, 'tcx>( // collect instrumentation points let points = { - let mut collector = CollectInstrumentationPoints::new(tcx, hooks, body, local_to_address); + let mut collector = + CollectInstrumentationPoints::new(tcx, hooks, body, local_to_address, state); collector.visit_body(body); collector.into_instrumentation_points() }; diff --git a/dynamic_instrumentation/src/into_operand.rs b/dynamic_instrumentation/src/into_operand.rs index 49c9527f5e..980221d69c 100644 --- a/dynamic_instrumentation/src/into_operand.rs +++ b/dynamic_instrumentation/src/into_operand.rs @@ -31,6 +31,34 @@ impl<'tcx> IntoOperand<'tcx> for u32 { } } +impl<'tcx> IntoOperand<'tcx> for usize { + fn op(self, tcx: TyCtxt<'tcx>) -> Operand<'tcx> { + Operand::Constant(Box::new(Constant { + span: DUMMY_SP, + user_ty: None, + literal: ConstantKind::Ty(ty::Const::from_bits( + tcx, + self.try_into().unwrap(), + ParamEnv::empty().and(tcx.types.usize), + )), + })) + } +} + +impl<'tcx> IntoOperand<'tcx> for u64 { + fn op(self, tcx: TyCtxt<'tcx>) -> Operand<'tcx> { + Operand::Constant(Box::new(Constant { + span: DUMMY_SP, + user_ty: None, + literal: ConstantKind::Ty(ty::Const::from_bits( + tcx, + self.try_into().unwrap(), + ParamEnv::empty().and(tcx.types.u64), + )), + })) + } +} + impl<'tcx> IntoOperand<'tcx> for Local { fn op(self, tcx: TyCtxt<'tcx>) -> Operand<'tcx> { Place::from(self).op(tcx) diff --git a/dynamic_instrumentation/src/point/mod.rs b/dynamic_instrumentation/src/point/mod.rs index 1b3a069c3f..ec062349cb 100644 --- a/dynamic_instrumentation/src/point/mod.rs +++ b/dynamic_instrumentation/src/point/mod.rs @@ -112,6 +112,10 @@ impl<'tcx> RewriteAddressTakenLocals<'tcx> { } } +pub trait ProjectionSet { + fn add_proj(&self, proj: Vec) -> u64; +} + pub struct CollectInstrumentationPoints<'a, 'tcx: 'a> { tcx: TyCtxt<'tcx>, hooks: Hooks<'tcx>, @@ -119,6 +123,7 @@ pub struct CollectInstrumentationPoints<'a, 'tcx: 'a> { pub instrumentation_points: Vec>, assignment: Option<(Place<'tcx>, Rvalue<'tcx>)>, pub addr_taken_local_addresses: IndexMap, + pub projections: &'a dyn ProjectionSet, } impl<'a, 'tcx: 'a> CollectInstrumentationPoints<'a, 'tcx> { @@ -127,6 +132,7 @@ impl<'a, 'tcx: 'a> CollectInstrumentationPoints<'a, 'tcx> { hooks: Hooks<'tcx>, body: &'a Body<'tcx>, addr_taken_local_addresses: IndexMap, + projections: &'a dyn ProjectionSet, ) -> Self { Self { tcx, @@ -135,6 +141,7 @@ impl<'a, 'tcx: 'a> CollectInstrumentationPoints<'a, 'tcx> { instrumentation_points: Default::default(), assignment: Default::default(), addr_taken_local_addresses, + projections, } } diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index d14ca1334e..05c414b2ac 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -35,7 +35,12 @@ type AddressTaken = IndexSet<(FuncId, Local)>; pub trait EventKindExt { fn ptr(&self, metadata: &EventMetadata) -> Option; - fn to_node_kind(&self, func: FuncId, address_taken: &mut AddressTaken) -> Option; + fn to_node_kind( + &self, + func: FuncId, + metadata: &Metadata, + address_taken: &mut AddressTaken, + ) -> Option; } impl EventKindExt for EventKind { @@ -63,14 +68,25 @@ impl EventKindExt for EventKind { }) } - fn to_node_kind(&self, func: FuncId, address_taken: &mut AddressTaken) -> Option { + fn to_node_kind( + &self, + func: FuncId, + metadata: &Metadata, + address_taken: &mut AddressTaken, + ) -> Option { use EventKind::*; Some(match *self { Alloc { .. } => NodeKind::Alloc(1), Realloc { .. } => NodeKind::Alloc(1), Free { .. } => NodeKind::Free, CopyPtr(..) | CopyRef => NodeKind::Copy, - Project(base_ptr, new_ptr) => NodeKind::Project(new_ptr - base_ptr), + Project(base_ptr, new_ptr, key) => { + let proj = metadata + .projections + .get(&key) + .expect("Invalid projection metadata"); + NodeKind::Project(new_ptr - base_ptr, proj.clone()) + } LoadAddr(..) => NodeKind::LoadAddr, StoreAddr(..) => NodeKind::StoreAddr, StoreAddrTaken(..) => NodeKind::StoreAddr, @@ -149,7 +165,7 @@ pub fn add_node( metadata: event_metadata, } = metadata.get(event.mir_loc); - let node_kind = event.kind.to_node_kind(func.id, address_taken)?; + let node_kind = event.kind.to_node_kind(func.id, metadata, address_taken)?; let this_id = func.id; let (src_fn, dest_fn) = match event_metadata.transfer_kind { TransferKind::None => (this_id, this_id), @@ -214,7 +230,7 @@ pub fn add_node( function, block: basic_block_idx.into(), statement_idx, - kind: node_kind, + kind: node_kind.clone(), source: source .and_then(|p| parent(&node_kind, p)) .map(|(_, nid)| nid), diff --git a/pdg/src/graph.rs b/pdg/src/graph.rs index 01b9fa3ff6..771bb72324 100644 --- a/pdg/src/graph.rs +++ b/pdg/src/graph.rs @@ -14,7 +14,7 @@ use crate::info::NodeInfo; use crate::util::pad_columns; use crate::util::ShortOption; -#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, Serialize, Deserialize)] +#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)] pub enum NodeKind { /// A copy from one [`Local`] to another. /// @@ -25,7 +25,7 @@ pub enum NodeKind { /// [`Field`] projection. /// /// Used for operations like `_2 = &(*_1).0`. - Project(usize), + Project(usize, Vec), /// Pointer arithmetic. /// @@ -119,7 +119,7 @@ impl Display for NodeKind { use NodeKind::*; match self { Copy => write!(f, "copy"), - Project(offset) => write!(f, "project.{offset}"), + Project(offset, proj) => write!(f, "project{proj:?}@{offset}"), Offset(offset) => write!(f, "offset[{offset}]"), AddrOfLocal(local) => write!(f, "&{local:?}"), _AddrOfStatic(static_) => write!(f, "&'static {static_:?}"), diff --git a/pdg/src/info.rs b/pdg/src/info.rs index 1a247acfba..29d6aaf83f 100644 --- a/pdg/src/info.rs +++ b/pdg/src/info.rs @@ -7,8 +7,8 @@ use std::fmt::{self, Debug, Display, Formatter}; /// Force an import of [`Node`] just for docs. const _: Option = None; -/// The identity of a field of a structure is its offset. -type Field = usize; +/// The identity of a field of a structure is its offset and projection index vector. +type Field = Vec; /// Information generated from the PDG proper that is queried by static analysis. /// @@ -59,7 +59,7 @@ fn set_flow_info(g: &mut Graph) { let mut flow_map: HashMap = HashMap::from_iter( g.nodes .iter_enumerated() - .map(|(idx, node)| (idx, FlowInfo::new(idx, node.kind))), + .map(|(idx, node)| (idx, FlowInfo::new(idx, node.kind.clone()))), ); for (n_id, mut node) in g.nodes.iter_enumerated_mut().rev() { let cur_node_flow_info: FlowInfo = flow_map.remove(&n_id).unwrap(); @@ -113,7 +113,7 @@ fn collect_children(g: &Graph) -> HashMap)>> { .rev() .filter_map(|(child, child_node)| Some((child_node.source?, child, child_node))) { - if let NodeKind::Project(f) = child_node.kind { + if let NodeKind::Project(_, f) = &child_node.kind { let my_children = children .remove(&child) @@ -123,7 +123,7 @@ fn collect_children(g: &Graph) -> HashMap)>> { ( gchild, ({ - gchildf.push(f); + gchildf.push(f.clone()); gchildf }), ) @@ -257,7 +257,8 @@ mod test { } fn mk_project(g: &mut Graph, source: NodeId, field: impl Into) -> NodeId { - mk_node(g, NodeKind::Project(field.into()), Some(source)) + let f = field.into(); + mk_node(g, NodeKind::Project(f.iter().sum(), f), Some(source)) } fn mk_offset(g: &mut Graph, source: NodeId, i: isize) -> NodeId { @@ -486,10 +487,10 @@ mod test { // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); // let b = &mut a.x; - let b11 = mk_project(&mut g, a, 0_usize); + let b11 = mk_project(&mut g, a, vec![0_usize]); let b1 = mk_copy(&mut g, b11); // let c = &mut a.y; - let c11 = mk_project(&mut g, a, 1_usize); + let c11 = mk_project(&mut g, a, vec![1_usize]); let c1 = mk_copy(&mut g, c11); // *b = 1; let b2 = mk_store_addr(&mut g, b1); @@ -536,17 +537,17 @@ mod test { // let j = &mut a; let j = mk_copy(&mut g, a); // let b = &mut j.x; - let b11 = mk_project(&mut g, j, 0_usize); + let b11 = mk_project(&mut g, j, vec![0_usize]); let b1 = mk_copy(&mut g, b11); // let c = &mut j.x; - let c11 = mk_project(&mut g, j, 0_usize); + let c11 = mk_project(&mut g, j, vec![0_usize]); let c1 = mk_copy(&mut g, c11); // *b = 1; let b2 = mk_store_addr(&mut g, b1); // *c = 2; let c2 = mk_store_addr(&mut g, c1); // *(a.y) = 3; - let d1 = mk_project(&mut g, a, 1_usize); + let d1 = mk_project(&mut g, a, vec![1_usize]); let d2 = mk_store_addr(&mut g, d1); let pdg = build_pdg(g); @@ -585,7 +586,7 @@ mod test { // let b = &mut a; let b1 = mk_copy(&mut g, a); // let c = &mut a.y; - let c11 = mk_project(&mut g, a, 1_usize); + let c11 = mk_project(&mut g, a, vec![1_usize]); let c1 = mk_copy(&mut g, c11); // *c = 2; let c2 = mk_store_addr(&mut g, c1); @@ -631,10 +632,10 @@ mod test { // let b = &mut a; let b1 = mk_copy(&mut g, a); // let c = &mut b.y; - let c1 = mk_project(&mut g, a, 1_usize); + let c1 = mk_project(&mut g, a, vec![1_usize]); let c2 = mk_copy(&mut g, c1); // let bb = &mut b.y; - let bb = mk_project(&mut g, b1, 1_usize); + let bb = mk_project(&mut g, b1, vec![1_usize]); let bb1 = mk_copy(&mut g, bb); // *c = 2; let c3 = mk_store_addr(&mut g, c2); @@ -670,8 +671,8 @@ mod test { fn lots_of_siblings() { let mut g = Graph::default(); - let (x, y, z) = (0_usize, 1_usize, 2_usize); - let (red, green, _blue) = (0_usize, 1_usize, 2_usize); + let (x, y, z) = (vec![0_usize], vec![1_usize], vec![2_usize]); + let (red, green, _blue) = (vec![0_usize], vec![1_usize], vec![2_usize]); // let mut a = ColorPoint { x: 0, y: 0, z: Color { r: 100, g: 100, b: 100 } }; let a = mk_addr_of_local(&mut g, 0_u32); @@ -682,7 +683,7 @@ mod test { let cc1 = mk_project(&mut g, a, y); let c1 = mk_copy(&mut g, cc1); // a.z.r = 200; - let x1 = mk_project(&mut g, a, z); + let x1 = mk_project(&mut g, a, z.clone()); let x2 = mk_project(&mut g, x1, red); let x3 = mk_store_addr(&mut g, x2); // *b = 4; @@ -694,13 +695,13 @@ mod test { // *d = ColorPoint { x: 0, y: 0, z: Color { r: 20, g: 200, b: 20 } }; let d2 = mk_store_addr(&mut g, d1); // let e = &mut a.z; - let ee = mk_project(&mut g, a, z); + let ee = mk_project(&mut g, a, z.clone()); let e = mk_copy(&mut g, ee); // let f = &mut e.g; - let ff1 = mk_project(&mut g, e, green); + let ff1 = mk_project(&mut g, e, green.clone()); let f1 = mk_copy(&mut g, ff1); // let g = &mut e.g; - let ggg = mk_project(&mut g, e, green); + let ggg = mk_project(&mut g, e, green.clone()); let gg = mk_copy(&mut g, ggg); // *f = 3; let f2 = mk_store_addr(&mut g, f1); @@ -759,10 +760,10 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0; - let x1 = mk_project(&mut g, a, 0_usize); + let x1 = mk_project(&mut g, a, vec![0_usize]); let x2 = mk_copy(&mut g, x1); // let y = &mut a.1; - let y1 = mk_project(&mut g, a, 1_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); let y2 = mk_copy(&mut g, y1); // *x = 1; let x3 = mk_store_addr(&mut g, x2); @@ -817,12 +818,12 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.1.0; - let x1 = mk_project(&mut g, a, 1_usize); - let x2 = mk_project(&mut g, x1, 0_usize); + let x1 = mk_project(&mut g, a, vec![1_usize]); + let x2 = mk_project(&mut g, x1, vec![0_usize]); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1.1; - let y1 = mk_project(&mut g, a, 1_usize); - let y2 = mk_project(&mut g, y1, 1_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); + let y2 = mk_project(&mut g, y1, vec![1_usize]); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); @@ -871,16 +872,16 @@ mod test { //let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); //let mut x = &mut a.1; - let x1 = mk_project(&mut g, a, 1_usize); + let x1 = mk_project(&mut g, a, vec![1_usize]); let x2 = mk_copy(&mut g, x1); //let mut y = &mut a.1; - let y1 = mk_project(&mut g, a, 1_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); let y2 = mk_copy(&mut g, y1); // *(x.0) = 4; - let x3 = mk_project(&mut g, x2, 0_usize); + let x3 = mk_project(&mut g, x2, vec![0_usize]); let x4 = mk_store_addr(&mut g, x3); // *(y.1) = 2; - let y3 = mk_project(&mut g, y2, 1_usize); + let y3 = mk_project(&mut g, y2, vec![1_usize]); let y4 = mk_store_addr(&mut g, y3); let pdg = build_pdg(g); @@ -925,12 +926,12 @@ mod test { // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.1.0; - let x1 = mk_project(&mut g, a, 1_usize); - let x2 = mk_project(&mut g, x1, 0_usize); + let x1 = mk_project(&mut g, a, vec![1_usize]); + let x2 = mk_project(&mut g, x1, vec![0_usize]); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1.0; - let y1 = mk_project(&mut g, a, 1_usize); - let y2 = mk_project(&mut g, y1, 0_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); + let y2 = mk_project(&mut g, y1, vec![0_usize]); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); @@ -987,11 +988,11 @@ mod test { // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0[0]; - let x1 = mk_project(&mut g, a, 1_usize); + let x1 = mk_project(&mut g, a, vec![1_usize]); let x2 = mk_offset(&mut g, x1, 0); let x3 = mk_copy(&mut g, x2); // let y = &mut a.0[1]; - let y1 = mk_project(&mut g, a, 1_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); let y2 = mk_offset(&mut g, y1, 1); let y3 = mk_copy(&mut g, y2); // *x = 1; @@ -1049,11 +1050,11 @@ mod test { // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); // let x = &mut a.0[0]; - let x1 = mk_project(&mut g, a, 0_usize); + let x1 = mk_project(&mut g, a, vec![0_usize]); let x2 = mk_offset(&mut g, x1, 0); let x3 = mk_copy(&mut g, x2); // let y = &mut a.1[0]; - let y1 = mk_project(&mut g, a, 1_usize); + let y1 = mk_project(&mut g, a, vec![1_usize]); let y2 = mk_offset(&mut g, y1, 0); let y3 = mk_copy(&mut g, y2); // *x = 1; @@ -1121,11 +1122,11 @@ mod test { let p = mk_addr_of_local(&mut g, 0_u32); // let x = &mut (*p)[0].0; let x1 = mk_offset(&mut g, p, 0); - let x2 = mk_project(&mut g, x1, 0_usize); + let x2 = mk_project(&mut g, x1, vec![0_usize]); let x3 = mk_copy(&mut g, x2); // let y = &mut (*p)[0].1; let y1 = mk_offset(&mut g, p, 0); - let y2 = mk_project(&mut g, y1, 1_usize); + let y2 = mk_project(&mut g, y1, vec![1_usize]); let y3 = mk_copy(&mut g, y2); // *x = 1; let x4 = mk_store_addr(&mut g, x3); diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index f63a2ed663..7b4cf4d67c 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -1,5 +1,6 @@ --- source: pdg/src/main.rs +assertion_line: 376 expression: pdg --- g { @@ -44,75 +45,69 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; - n[3]: field.0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); - n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; - n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); - n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); + n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; + n[3]: project[0]@0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); + n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; + n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); + n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); } nodes_that_need_write = [] g { - n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); - n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; - n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; - n[4]: field.0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[6]: field.0 n[3] => _12 @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[8]: field.0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[9]: addr.store n[8] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[10]: field.1 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[11]: addr.store n[10] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[12]: field.0 n[3] => _13 @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[13]: addr.load n[12] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[14]: field.1 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[15]: copy n[14] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[16]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); - n[17]: field.2 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[18]: addr.store n[17] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[19]: value.store n[16] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[20]: field.3 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[21]: addr.store n[20] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[22]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); - n[23]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; - n[24]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; - n[25]: copy n[24] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); - n[26]: copy n[25] => _13 @ bb8[3]: fn recur; _13 = _2; - n[27]: copy n[26] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[28]: copy n[27] => _13 @ bb8[3]: fn recur; _13 = _2; - n[29]: copy n[28] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[30]: copy n[29] => _13 @ bb8[3]: fn recur; _13 = _2; - n[31]: copy n[30] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[32]: copy n[31] => _8 @ bb1[2]: fn recur; _8 = _2; - n[33]: copy n[32] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); - n[34]: free n[33] => _0 @ bb1[5]: fn recur; _0 = free(move _7); - n[35]: copy n[31] => _14 @ bb9[4]: fn recur; _14 = _2; - n[36]: copy n[31] => _14 @ bb9[4]: fn recur; _14 = _2; - n[37]: copy n[31] => _14 @ bb9[4]: fn recur; _14 = _2; -} -nodes_that_need_write = [23, 21, 20, 18, 17, 11, 10, 9, 8, 5, 4, 3, 2, 1, 0] - -g { - n[0]: &_1 _ => _ @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); + n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); + n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; + n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; + n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); + n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); + n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); + n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; + n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; + n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); + n[25]: copy n[24] => _13 @ bb8[3]: fn recur; _13 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); + n[27]: copy n[26] => _13 @ bb8[3]: fn recur; _13 = _2; + n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); + n[29]: copy n[28] => _13 @ bb8[3]: fn recur; _13 = _2; + n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); + n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; + n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); + n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); + n[34]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; + n[35]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; + n[36]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; +} +nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); + n[6]: copy n[1] => _13 @ bb3[7]: fn exercise_allocator; _13 = _1; + n[7]: copy n[6] => _12 @ bb3[8]: fn exercise_allocator; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); } -nodes_that_need_write = [] - -g { - n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _10 @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); - n[6]: copy n[1] => _13 @ bb3[7]: fn exercise_allocator; _13 = _1; - n[7]: copy n[6] => _12 @ bb3[8]: fn exercise_allocator; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); -} -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: copy _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; @@ -194,147 +189,147 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); - n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); - n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; - n[3]: offset[0] n[2] => _18 @ bb6[7]: fn exercise_allocator; _18 = offset(move _19, const 0_isize); - n[4]: field.0 n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; - n[6]: copy n[1] => _21 @ bb7[5]: fn exercise_allocator; _21 = _1; - n[7]: offset[1] n[6] => _20 @ bb7[6]: fn exercise_allocator; _20 = offset(move _21, const 1_isize); - n[8]: field.0 n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; - n[10]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; - n[11]: offset[0] n[10] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); - n[12]: field.0 n[11] => _32 @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[13]: addr.load n[12] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[14]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; - n[15]: offset[1] n[14] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); - n[16]: field.0 n[15] => _32 @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[17]: addr.load n[16] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[18]: copy n[1] => _43 @ bb21[6]: fn exercise_allocator; _43 = _1; - n[19]: copy n[18] => _42 @ bb21[7]: fn exercise_allocator; _42 = move _43 as *mut libc::c_void (Misc); - n[20]: copy n[1] => _4 @ bb0[1]: fn reallocarray; _4 = _1; - n[21]: copy n[20] => _1 @ bb1[3]: fn reallocarray; _0 = const pointers::REALLOC(move _4, move _5); - n[22]: free n[19] => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); -} -nodes_that_need_write = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); - n[1]: copy n[0] => _1 @ bb23[3]: fn exercise_allocator; _1 = move _41 as *mut pointers::S (Misc); - n[2]: copy n[1] => _48 @ bb23[7]: fn exercise_allocator; _48 = _1; - n[3]: offset[0] n[2] => _47 @ bb23[8]: fn exercise_allocator; _47 = offset(move _48, const 0_isize); - n[4]: field.0 n[3] => _ @ bb24[1]: fn exercise_allocator; ((*_47).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb24[1]: fn exercise_allocator; ((*_47).0: i32) = const 10_i32; - n[6]: copy n[1] => _50 @ bb24[5]: fn exercise_allocator; _50 = _1; - n[7]: offset[1] n[6] => _49 @ bb24[6]: fn exercise_allocator; _49 = offset(move _50, const 1_isize); - n[8]: field.0 n[7] => _ @ bb25[1]: fn exercise_allocator; ((*_49).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb25[1]: fn exercise_allocator; ((*_49).0: i32) = const 11_i32; - n[10]: copy n[1] => _52 @ bb25[5]: fn exercise_allocator; _52 = _1; - n[11]: offset[2] n[10] => _51 @ bb25[6]: fn exercise_allocator; _51 = offset(move _52, const 2_isize); - n[12]: field.0 n[11] => _ @ bb26[1]: fn exercise_allocator; ((*_51).0: i32) = const 12_i32; - n[13]: addr.store n[12] => _ @ bb26[1]: fn exercise_allocator; ((*_51).0: i32) = const 12_i32; - n[14]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; - n[15]: offset[0] n[14] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); - n[16]: field.0 n[15] => _62 @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[17]: addr.load n[16] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[18]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; - n[19]: offset[1] n[18] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); - n[20]: field.0 n[19] => _62 @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[21]: addr.load n[20] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[22]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; - n[23]: offset[2] n[22] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); - n[24]: field.0 n[23] => _62 @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[25]: addr.load n[24] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); - n[26]: copy n[1] => _73 @ bb39[6]: fn exercise_allocator; _73 = _1; - n[27]: copy n[26] => _72 @ bb39[7]: fn exercise_allocator; _72 = move _73 as *mut libc::c_void (Misc); - n[28]: free n[27] => _71 @ bb39[9]: fn exercise_allocator; _71 = free(move _72); -} -nodes_that_need_write = [13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _74 @ bb41[2]: fn exercise_allocator; _74 = calloc(move _75, move _76); - n[1]: copy n[0] => _1 @ bb42[2]: fn exercise_allocator; _1 = move _74 as *mut pointers::S (Misc); - n[2]: copy n[1] => _79 @ bb42[6]: fn exercise_allocator; _79 = _1; - n[3]: offset[0] n[2] => _78 @ bb42[7]: fn exercise_allocator; _78 = offset(move _79, const 0_isize); - n[4]: field.0 n[3] => _ @ bb43[1]: fn exercise_allocator; ((*_78).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb43[1]: fn exercise_allocator; ((*_78).0: i32) = const 10_i32; - n[6]: copy n[1] => _81 @ bb43[5]: fn exercise_allocator; _81 = _1; - n[7]: offset[1] n[6] => _80 @ bb43[6]: fn exercise_allocator; _80 = offset(move _81, const 1_isize); - n[8]: field.0 n[7] => _ @ bb44[1]: fn exercise_allocator; ((*_80).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb44[1]: fn exercise_allocator; ((*_80).0: i32) = const 11_i32; - n[10]: copy n[1] => _83 @ bb44[5]: fn exercise_allocator; _83 = _1; - n[11]: offset[2] n[10] => _82 @ bb44[6]: fn exercise_allocator; _82 = offset(move _83, const 2_isize); - n[12]: field.0 n[11] => _ @ bb45[1]: fn exercise_allocator; ((*_82).0: i32) = const 12_i32; - n[13]: addr.store n[12] => _ @ bb45[1]: fn exercise_allocator; ((*_82).0: i32) = const 12_i32; - n[14]: copy n[1] => _85 @ bb45[5]: fn exercise_allocator; _85 = _1; - n[15]: offset[3] n[14] => _84 @ bb45[6]: fn exercise_allocator; _84 = offset(move _85, const 3_isize); - n[16]: field.0 n[15] => _ @ bb46[1]: fn exercise_allocator; ((*_84).0: i32) = const 13_i32; - n[17]: addr.store n[16] => _ @ bb46[1]: fn exercise_allocator; ((*_84).0: i32) = const 13_i32; - n[18]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; - n[19]: offset[0] n[18] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); - n[20]: field.0 n[19] => _95 @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[21]: addr.load n[20] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[22]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; - n[23]: offset[1] n[22] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); - n[24]: field.0 n[23] => _95 @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[25]: addr.load n[24] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[26]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; - n[27]: offset[2] n[26] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); - n[28]: field.0 n[27] => _95 @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[29]: addr.load n[28] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[30]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; - n[31]: offset[3] n[30] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); - n[32]: field.0 n[31] => _95 @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[33]: addr.load n[32] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); - n[34]: copy n[1] => _106 @ bb59[6]: fn exercise_allocator; _106 = _1; - n[35]: copy n[34] => _105 @ bb59[7]: fn exercise_allocator; _105 = move _106 as *mut libc::c_void (Misc); - n[36]: free n[35] => _104 @ bb59[9]: fn exercise_allocator; _104 = free(move _105); -} -nodes_that_need_write = [17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _10 @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); - n[6]: copy n[1] => _13 @ bb3[7]: fn simple_analysis; _13 = _1; - n[7]: copy n[6] => _12 @ bb3[8]: fn simple_analysis; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb3[10]: fn simple_analysis; _11 = free(move _12); + n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); + n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); + n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; + n[3]: offset[0] n[2] => _18 @ bb6[7]: fn exercise_allocator; _18 = offset(move _19, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; + n[6]: copy n[1] => _21 @ bb7[5]: fn exercise_allocator; _21 = _1; + n[7]: offset[1] n[6] => _20 @ bb7[6]: fn exercise_allocator; _20 = offset(move _21, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; + n[10]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; + n[11]: offset[0] n[10] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); + n[12]: project[0]@0 n[11] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[13]: addr.load n[11] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[14]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; + n[15]: offset[1] n[14] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); + n[16]: project[0]@0 n[15] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[17]: addr.load n[15] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[18]: copy n[1] => _43 @ bb21[6]: fn exercise_allocator; _43 = _1; + n[19]: copy n[18] => _42 @ bb21[7]: fn exercise_allocator; _42 = move _43 as *mut libc::c_void (Misc); + n[20]: copy n[1] => _4 @ bb0[1]: fn reallocarray; _4 = _1; + n[21]: copy n[20] => _1 @ bb1[3]: fn reallocarray; _0 = const pointers::REALLOC(move _4, move _5); + n[22]: free n[19] => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); +} +nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); + n[1]: copy n[0] => _1 @ bb23[3]: fn exercise_allocator; _1 = move _41 as *mut pointers::S (Misc); + n[2]: copy n[1] => _48 @ bb23[7]: fn exercise_allocator; _48 = _1; + n[3]: offset[0] n[2] => _47 @ bb23[8]: fn exercise_allocator; _47 = offset(move _48, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb24[1]: fn exercise_allocator; ((*_47).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb24[1]: fn exercise_allocator; ((*_47).0: i32) = const 10_i32; + n[6]: copy n[1] => _50 @ bb24[5]: fn exercise_allocator; _50 = _1; + n[7]: offset[1] n[6] => _49 @ bb24[6]: fn exercise_allocator; _49 = offset(move _50, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb25[1]: fn exercise_allocator; ((*_49).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb25[1]: fn exercise_allocator; ((*_49).0: i32) = const 11_i32; + n[10]: copy n[1] => _52 @ bb25[5]: fn exercise_allocator; _52 = _1; + n[11]: offset[2] n[10] => _51 @ bb25[6]: fn exercise_allocator; _51 = offset(move _52, const 2_isize); + n[12]: project[0]@0 n[11] => _ @ bb26[1]: fn exercise_allocator; ((*_51).0: i32) = const 12_i32; + n[13]: addr.store n[11] => _ @ bb26[1]: fn exercise_allocator; ((*_51).0: i32) = const 12_i32; + n[14]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; + n[15]: offset[0] n[14] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); + n[16]: project[0]@0 n[15] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[17]: addr.load n[15] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[18]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; + n[19]: offset[1] n[18] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); + n[20]: project[0]@0 n[19] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[21]: addr.load n[19] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[22]: copy n[1] => _64 @ bb29[14]: fn exercise_allocator; _64 = _1; + n[23]: offset[2] n[22] => _63 @ bb29[20]: fn exercise_allocator; _63 = offset(move _64, move _65); + n[24]: project[0]@0 n[23] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[25]: addr.load n[23] => _ @ bb31[2]: fn exercise_allocator; _62 = ((*_63).0: i32); + n[26]: copy n[1] => _73 @ bb39[6]: fn exercise_allocator; _73 = _1; + n[27]: copy n[26] => _72 @ bb39[7]: fn exercise_allocator; _72 = move _73 as *mut libc::c_void (Misc); + n[28]: free n[27] => _71 @ bb39[9]: fn exercise_allocator; _71 = free(move _72); +} +nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _74 @ bb41[2]: fn exercise_allocator; _74 = calloc(move _75, move _76); + n[1]: copy n[0] => _1 @ bb42[2]: fn exercise_allocator; _1 = move _74 as *mut pointers::S (Misc); + n[2]: copy n[1] => _79 @ bb42[6]: fn exercise_allocator; _79 = _1; + n[3]: offset[0] n[2] => _78 @ bb42[7]: fn exercise_allocator; _78 = offset(move _79, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb43[1]: fn exercise_allocator; ((*_78).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb43[1]: fn exercise_allocator; ((*_78).0: i32) = const 10_i32; + n[6]: copy n[1] => _81 @ bb43[5]: fn exercise_allocator; _81 = _1; + n[7]: offset[1] n[6] => _80 @ bb43[6]: fn exercise_allocator; _80 = offset(move _81, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb44[1]: fn exercise_allocator; ((*_80).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb44[1]: fn exercise_allocator; ((*_80).0: i32) = const 11_i32; + n[10]: copy n[1] => _83 @ bb44[5]: fn exercise_allocator; _83 = _1; + n[11]: offset[2] n[10] => _82 @ bb44[6]: fn exercise_allocator; _82 = offset(move _83, const 2_isize); + n[12]: project[0]@0 n[11] => _ @ bb45[1]: fn exercise_allocator; ((*_82).0: i32) = const 12_i32; + n[13]: addr.store n[11] => _ @ bb45[1]: fn exercise_allocator; ((*_82).0: i32) = const 12_i32; + n[14]: copy n[1] => _85 @ bb45[5]: fn exercise_allocator; _85 = _1; + n[15]: offset[3] n[14] => _84 @ bb45[6]: fn exercise_allocator; _84 = offset(move _85, const 3_isize); + n[16]: project[0]@0 n[15] => _ @ bb46[1]: fn exercise_allocator; ((*_84).0: i32) = const 13_i32; + n[17]: addr.store n[15] => _ @ bb46[1]: fn exercise_allocator; ((*_84).0: i32) = const 13_i32; + n[18]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; + n[19]: offset[0] n[18] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); + n[20]: project[0]@0 n[19] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[21]: addr.load n[19] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[22]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; + n[23]: offset[1] n[22] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); + n[24]: project[0]@0 n[23] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[25]: addr.load n[23] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[26]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; + n[27]: offset[2] n[26] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); + n[28]: project[0]@0 n[27] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[29]: addr.load n[27] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[30]: copy n[1] => _97 @ bb49[14]: fn exercise_allocator; _97 = _1; + n[31]: offset[3] n[30] => _96 @ bb49[20]: fn exercise_allocator; _96 = offset(move _97, move _98); + n[32]: project[0]@0 n[31] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[33]: addr.load n[31] => _ @ bb51[2]: fn exercise_allocator; _95 = ((*_96).0: i32); + n[34]: copy n[1] => _106 @ bb59[6]: fn exercise_allocator; _106 = _1; + n[35]: copy n[34] => _105 @ bb59[7]: fn exercise_allocator; _105 = move _106 as *mut libc::c_void (Misc); + n[36]: free n[35] => _104 @ bb59[9]: fn exercise_allocator; _104 = free(move _105); +} +nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); + n[6]: copy n[1] => _13 @ bb3[7]: fn simple_analysis; _13 = _1; + n[7]: copy n[6] => _12 @ bb3[8]: fn simple_analysis; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb3[10]: fn simple_analysis; _11 = free(move _12); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _6 @ bb2[8]: fn analysis2; _6 = _1; - n[5]: copy n[4] => _1 @ bb0[0]: fn analysis2_helper; _5 = analysis2_helper(move _6); - n[6]: field.0 n[5] => _7 @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); - n[8]: copy n[5] => _9 @ bb3[5]: fn analysis2; _9 = _1; - n[9]: copy n[8] => _8 @ bb3[6]: fn analysis2; _8 = move _9 as *mut libc::c_void (Misc); - n[10]: free n[9] => _7 @ bb3[8]: fn analysis2; _7 = free(move _8); + n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _6 @ bb2[8]: fn analysis2; _6 = _1; + n[5]: copy n[4] => _1 @ bb0[0]: fn analysis2_helper; _5 = analysis2_helper(move _6); + n[6]: project[0]@0 n[5] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); + n[7]: addr.load n[5] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); + n[8]: copy n[5] => _9 @ bb3[5]: fn analysis2; _9 = _1; + n[9]: copy n[8] => _8 @ bb3[6]: fn analysis2; _8 = move _9 as *mut libc::c_void (Misc); + n[10]: free n[9] => _7 @ bb3[8]: fn analysis2; _7 = free(move _8); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); - n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); - n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); - n[3]: field.0 n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; - n[4]: addr.store n[3] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; - n[5]: field.0 n[2] => _10 @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); - n[6]: addr.load n[5] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); - n[7]: copy n[2] => _13 @ bb3[7]: fn inter_function_analysis; _13 = _1; - n[8]: copy n[7] => _12 @ bb3[8]: fn inter_function_analysis; _12 = move _13 as *mut libc::c_void (Misc); - n[9]: free n[8] => _11 @ bb3[10]: fn inter_function_analysis; _11 = free(move _12); + n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); + n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); + n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); + n[3]: project[0]@0 n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; + n[4]: addr.store n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; + n[5]: project[0]@0 n[2] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); + n[6]: addr.load n[2] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); + n[7]: copy n[2] => _13 @ bb3[7]: fn inter_function_analysis; _13 = _1; + n[8]: copy n[7] => _12 @ bb3[8]: fn inter_function_analysis; _12 = move _13 as *mut libc::c_void (Misc); + n[9]: free n[8] => _11 @ bb3[10]: fn inter_function_analysis; _11 = free(move _12); } -nodes_that_need_write = [4, 3, 2, 1, 0] +nodes_that_need_write = [4, 2, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -346,23 +341,24 @@ g { nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: field.0 n[10] => _18 @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: addr.load n[11] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[13]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[14]: addr.store n[13] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; + n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; + n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; + n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; + n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[12]: project[0]@0 n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[13]: addr.load n[12] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[14]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; + n[15]: addr.store n[14] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [14, 13, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [15, 14, 9, 8, 5, 4, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -374,19 +370,20 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _5 @ bb2[7]: fn invalid; _5 = _1; - n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; - n[6]: field.0 n[1] => _12 @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; - n[9]: copy n[8] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); - n[10]: free n[9] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); + n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _5 @ bb2[7]: fn invalid; _5 = _1; + n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; + n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); + n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); + n[8]: value.load _ => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; + n[10]: copy n[9] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); + n[11]: free n[10] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; @@ -419,19 +416,19 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; - n[3]: field.0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[4]: addr.store n[3] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; - n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); - n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; - n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); - n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); + n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); + n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; + n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; + n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; + n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; + n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); + n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); } -nodes_that_need_write = [4, 3, 2, 1, 0] +nodes_that_need_write = [4, 2, 1, 0] g { n[0]: &_13 _ => _ @ bb4[14]: fn simple1; _22 = &raw mut _13; @@ -464,116 +461,116 @@ g { nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4] g { - n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); - n[2]: field.0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[3]: addr.store n[2] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[7]: field.0 n[6] => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[8]: addr.load n[7] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); - n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; - n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); - n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); - n[15]: field.0 n[14] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[16]: addr.load n[15] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[17]: field.0 n[14] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[18]: addr.load n[17] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[19]: copy n[15] => _23 @ bb7[5]: fn lighttpd_test; _23 = _5; - n[20]: copy n[19] => _22 @ bb7[6]: fn lighttpd_test; _22 = move _23 as *mut libc::c_void (Misc); - n[21]: free n[20] => _21 @ bb7[8]: fn lighttpd_test; _21 = free(move _22); + n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; + n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; + n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; + n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); + n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; + n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); + n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); + n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[17]: project[0]@0 n[14] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[18]: addr.load n[14] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[19]: copy n[1] => _23 @ bb7[5]: fn lighttpd_test; _23 = _5; + n[20]: copy n[19] => _22 @ bb7[6]: fn lighttpd_test; _22 = move _23 as *mut libc::c_void (Misc); + n[21]: free n[20] => _21 @ bb7[8]: fn lighttpd_test; _21 = free(move _22); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; - n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; - n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); - n[3]: copy n[2] => _14 @ bb4[18]: fn lighttpd_test; _14 = &raw mut (*_10); - n[4]: copy n[3] => _1 @ bb0[0]: fn connection_accepted; _13 = connection_accepted(move _14, const 0_i32); - n[5]: field.0 n[4] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[6]: addr.load n[5] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[7]: copy n[5] => _16 @ bb5[4]: fn lighttpd_test; _16 = &raw mut (*_10); - n[8]: copy n[7] => _1 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); - n[9]: field.0 n[8] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[10]: addr.load n[9] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[11]: field.0 n[8] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); - n[12]: addr.load n[11] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; + n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; + n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); + n[3]: copy n[2] => _14 @ bb4[18]: fn lighttpd_test; _14 = &raw mut (*_10); + n[4]: copy n[3] => _1 @ bb0[0]: fn connection_accepted; _13 = connection_accepted(move _14, const 0_i32); + n[5]: project[0]@0 n[4] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[6]: addr.load n[4] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[7]: copy n[2] => _16 @ bb5[4]: fn lighttpd_test; _16 = &raw mut (*_10); + n[8]: copy n[7] => _1 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); + n[9]: project[0]@0 n[8] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[10]: addr.load n[8] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[11]: project[0]@0 n[8] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[12]: addr.load n[8] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); } nodes_that_need_write = [1, 0] g { - n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); - n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); - n[2]: field.0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; - n[3]: addr.store n[2] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; - n[4]: field.0 n[1] => _11 @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); - n[5]: addr.load n[4] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); - n[6]: copy n[1] => _15 @ bb2[20]: fn connection_accepted; _15 = _4; - n[7]: copy n[6] => _14 @ bb2[21]: fn connection_accepted; _14 = move _15 as *mut libc::c_void (Misc); - n[8]: copy n[7] => _4 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; - n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[11]: field.1 n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[12]: addr.store n[11] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; - n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); - n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; - n[16]: copy n[15] => _2 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); - n[17]: field.1 n[16] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[18]: addr.load n[17] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[19]: field.0 n[16] => _8 @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); - n[20]: addr.load n[19] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); - n[21]: copy n[16] => _11 @ bb2[6]: fn connection_close; _11 = _2; - n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); - n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); -} -nodes_that_need_write = [12, 11, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); - n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); - n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; - n[3]: copy n[2] => _1 @ bb0[0]: fn is_null; _9 = is_null(move _10); - n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; - n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); - n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; - n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[8]: field.0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; - n[9]: addr.store n[8] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; - n[10]: field.2 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; - n[11]: addr.store n[10] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; - n[12]: field.1 n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[13]: addr.store n[12] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[14]: field.3 n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; - n[15]: addr.store n[14] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; - n[16]: field.4 n[7] => _ @ bb3[0]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); - n[17]: addr.store n[16] => _ @ bb3[0]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); - n[18]: copy n[7] => _0 @ bb3[2]: fn fdevent_register; _0 = _12; - n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); - n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; - n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); - n[25]: copy n[22] => _8 @ bb2[4]: fn fdevent_fdnode_event_del; _8 = _2; - n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[27]: field.4 n[26] => _8 @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); - n[28]: addr.load n[27] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); - n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; - n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); - n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; - n[33]: copy n[32] => _1 @ bb0[0]: fn fdnode_free; _22 = fdnode_free(move _23); - n[34]: copy n[33] => _4 @ bb0[3]: fn fdnode_free; _4 = _1; - n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); - n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); -} -nodes_that_need_write = [17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7] + n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); + n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; + n[3]: addr.store n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; + n[4]: project[0]@0 n[1] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); + n[5]: addr.load n[1] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); + n[6]: copy n[1] => _15 @ bb2[20]: fn connection_accepted; _15 = _4; + n[7]: copy n[6] => _14 @ bb2[21]: fn connection_accepted; _14 = move _15 as *mut libc::c_void (Misc); + n[8]: copy n[7] => _4 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; + n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[11]: project[1]@8 n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[12]: addr.store n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; + n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); + n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; + n[16]: copy n[15] => _2 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); + n[17]: project[1]@8 n[16] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[18]: addr.load n[16] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[19]: project[0]@0 n[16] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); + n[20]: addr.load n[16] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); + n[21]: copy n[16] => _11 @ bb2[6]: fn connection_close; _11 = _2; + n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); + n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); +} +nodes_that_need_write = [12, 3, 1, 0] + +g { + n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); + n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); + n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; + n[3]: copy n[2] => _1 @ bb0[0]: fn is_null; _9 = is_null(move _10); + n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; + n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); + n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; + n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); + n[8]: project[0]@0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; + n[9]: addr.store n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; + n[10]: project[2]@16 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; + n[11]: addr.store n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; + n[12]: project[1]@8 n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[13]: addr.store n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[14]: project[3]@20 n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; + n[15]: addr.store n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; + n[16]: project[4]@24 n[7] => _ @ bb3[0]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); + n[17]: addr.store n[7] => _ @ bb3[0]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); + n[18]: copy n[7] => _0 @ bb3[2]: fn fdevent_register; _0 = _12; + n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); + n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; + n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); + n[25]: copy n[22] => _8 @ bb2[4]: fn fdevent_fdnode_event_del; _8 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); + n[27]: project[4]@24 n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); + n[28]: addr.load n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); + n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; + n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); + n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; + n[33]: copy n[32] => _1 @ bb0[0]: fn fdnode_free; _22 = fdnode_free(move _23); + n[34]: copy n[33] => _4 @ bb0[3]: fn fdnode_free; _4 = _1; + n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); + n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); +} +nodes_that_need_write = [17, 15, 13, 11, 9, 7] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); @@ -717,67 +714,65 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _7 @ bb2[8]: fn test_store_addr; _7 = _1; - n[5]: copy n[4] => _6 @ bb2[9]: fn test_store_addr; _6 = move _7 as *mut libc::c_void (Misc); - n[6]: free n[5] => _5 @ bb2[11]: fn test_store_addr; _5 = free(move _6); + n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _7 @ bb2[8]: fn test_store_addr; _7 = _1; + n[5]: copy n[4] => _6 @ bb2[9]: fn test_store_addr; _6 = move _7 as *mut libc::c_void (Misc); + n[6]: free n[5] => _5 @ bb2[11]: fn test_store_addr; _5 = free(move _6); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _9 @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); - n[6]: copy n[1] => _12 @ bb4[12]: fn test_load_other_store_self; _12 = _1; - n[7]: copy n[6] => _11 @ bb4[13]: fn test_load_other_store_self; _11 = move _12 as *mut libc::c_void (Misc); - n[8]: free n[7] => _10 @ bb4[15]: fn test_load_other_store_self; _10 = free(move _11); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); + n[6]: copy n[1] => _12 @ bb4[12]: fn test_load_other_store_self; _12 = _1; + n[7]: copy n[6] => _11 @ bb4[13]: fn test_load_other_store_self; _11 = move _12 as *mut libc::c_void (Misc); + n[8]: free n[7] => _10 @ bb4[15]: fn test_load_other_store_self; _10 = free(move _11); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; - n[3]: addr.store n[2] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; - n[4]: copy n[1] => _15 @ bb5[5]: fn test_load_other_store_self; _15 = _5; - n[5]: copy n[4] => _14 @ bb5[6]: fn test_load_other_store_self; _14 = move _15 as *mut libc::c_void (Misc); - n[6]: free n[5] => _13 @ bb5[8]: fn test_load_other_store_self; _13 = free(move _14); + n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; + n[3]: addr.store n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; + n[4]: copy n[1] => _15 @ bb5[5]: fn test_load_other_store_self; _15 = _5; + n[5]: copy n[4] => _14 @ bb5[6]: fn test_load_other_store_self; _14 = move _15 as *mut libc::c_void (Misc); + n[6]: free n[5] => _13 @ bb5[8]: fn test_load_other_store_self; _13 = free(move _14); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); - n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.3 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[3]: field.3 n[2] => _6 @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[4]: addr.load n[3] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[5]: field.3 n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[6]: field.3 n[5] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[7]: addr.store n[6] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[8]: copy n[1] => _9 @ bb2[12]: fn test_load_self_store_self; _9 = _1; - n[9]: copy n[8] => _8 @ bb2[13]: fn test_load_self_store_self; _8 = move _9 as *mut libc::c_void (Misc); - n[10]: free n[9] => _7 @ bb2[15]: fn test_load_self_store_self; _7 = free(move _8); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); + n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[3, 3]@48 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); + n[3]: addr.load n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); + n[4]: project[3, 3]@48 n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; + n[5]: addr.store n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; + n[6]: copy n[1] => _9 @ bb2[12]: fn test_load_self_store_self; _9 = _1; + n[7]: copy n[6] => _8 @ bb2[13]: fn test_load_self_store_self; _8 = move _9 as *mut libc::c_void (Misc); + n[8]: free n[7] => _7 @ bb2[15]: fn test_load_self_store_self; _7 = free(move _8); } -nodes_that_need_write = [7, 6, 5, 1, 0] +nodes_that_need_write = [5, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); - n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _6 @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); - n[3]: addr.load n[2] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); - n[4]: field.0 n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; - n[5]: addr.store n[4] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; - n[6]: copy n[1] => _10 @ bb2[15]: fn test_load_self_store_self_inter; _10 = _1; - n[7]: copy n[6] => _9 @ bb2[16]: fn test_load_self_store_self_inter; _9 = move _10 as *mut libc::c_void (Misc); - n[8]: free n[7] => _8 @ bb2[18]: fn test_load_self_store_self_inter; _8 = free(move _9); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); + n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); + n[3]: addr.load n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); + n[4]: project[0]@0 n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; + n[5]: addr.store n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; + n[6]: copy n[1] => _10 @ bb2[15]: fn test_load_self_store_self_inter; _10 = _1; + n[7]: copy n[6] => _9 @ bb2[16]: fn test_load_self_store_self_inter; _9 = move _10 as *mut libc::c_void (Misc); + n[8]: free n[7] => _8 @ bb2[18]: fn test_load_self_store_self_inter; _8 = free(move _9); } -nodes_that_need_write = [5, 4, 1, 0] +nodes_that_need_write = [5, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); @@ -823,32 +818,32 @@ g { nodes_that_need_write = [3, 2, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; - n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[5]: field.2 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[6]: addr.store n[5] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[8]: copy n[1] => _16 @ bb5[5]: fn test_store_value_field; _16 = _1; - n[9]: copy n[8] => _15 @ bb5[6]: fn test_store_value_field; _15 = move _16 as *mut libc::c_void (Misc); - n[10]: free n[9] => _14 @ bb5[8]: fn test_store_value_field; _14 = free(move _15); + n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; + n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[5]: project[2]@16 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[6]: addr.store n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[8]: copy n[1] => _16 @ bb5[5]: fn test_store_value_field; _16 = _1; + n[9]: copy n[8] => _15 @ bb5[6]: fn test_store_value_field; _15 = move _16 as *mut libc::c_void (Misc); + n[10]: free n[9] => _14 @ bb5[8]: fn test_store_value_field; _14 = free(move _15); } -nodes_that_need_write = [6, 5, 1, 0] +nodes_that_need_write = [6, 1, 0] g { - n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); - n[2]: field.2 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[3]: addr.store n[2] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: field.2 n[1] => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[5]: addr.load n[4] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[6]: copy n[1] => _13 @ bb4[15]: fn test_store_value_field; _13 = _5; - n[7]: copy n[6] => _12 @ bb4[16]: fn test_store_value_field; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb4[18]: fn test_store_value_field; _11 = free(move _12); + n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); + n[2]: project[2]@16 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[3]: addr.store n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[4]: project[2]@16 n[1] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[5]: addr.load n[1] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[6]: copy n[1] => _13 @ bb4[15]: fn test_store_value_field; _13 = _5; + n[7]: copy n[6] => _12 @ bb4[16]: fn test_store_value_field; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb4[18]: fn test_store_value_field; _11 = free(move _12); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); @@ -951,17 +946,15 @@ g { nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] g { - n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; - n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; - n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); - n[3]: field.3 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: field.3 n[3] => _7 @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[5]: addr.load n[4] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[6]: field.3 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[7]: field.3 n[6] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[8]: addr.store n[7] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; + n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; + n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); + n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); + n[4]: addr.load n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); + n[5]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[6]: addr.store n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [8, 7, 6, 2, 1, 0] +nodes_that_need_write = [6, 2, 1, 0] g { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _10 = &raw mut _1; @@ -973,12 +966,12 @@ g { nodes_that_need_write = [1, 0] g { - n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; - n[1]: field.2 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[2]: addr.store n[1] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: copy n[0] => _2 @ bb0[3]: fn test_addr_taken_arg; _2 = &(*_3); + n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; + n[1]: project[2]@16 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[2]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: copy n[0] => _2 @ bb0[3]: fn test_addr_taken_arg; _2 = &(*_3); } -nodes_that_need_write = [2, 1, 0] +nodes_that_need_write = [2, 0] g { n[0]: &_3 _ => _ @ bb2[2]: fn test_addr_taken_loop; _20 = &raw mut _3; @@ -1029,6 +1022,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 67 -num_nodes = 759 +num_graphs = 66 +num_nodes = 755 diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index 9fb1a5cf68..20839642f5 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -1,5 +1,6 @@ --- source: pdg/src/main.rs +assertion_line: 384 expression: pdg --- g { @@ -44,75 +45,69 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; - n[3]: field.0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); - n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; - n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); - n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); + n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; + n[3]: project[0]@0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); + n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; + n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); + n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); } nodes_that_need_write = [] g { - n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); - n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; - n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; - n[4]: field.0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[6]: field.0 n[3] => _12 @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[8]: field.0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[9]: addr.store n[8] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[10]: field.1 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[11]: addr.store n[10] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[12]: field.0 n[3] => _13 @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[13]: addr.load n[12] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[14]: field.1 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[15]: copy n[14] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[16]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); - n[17]: field.2 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[18]: addr.store n[17] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[19]: value.store n[16] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[20]: field.3 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[21]: addr.store n[20] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[22]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); - n[23]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; - n[24]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; - n[25]: copy n[24] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); - n[26]: copy n[25] => _12 @ bb7[9]: fn recur; _12 = _2; - n[27]: copy n[26] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[28]: copy n[27] => _12 @ bb7[9]: fn recur; _12 = _2; - n[29]: copy n[28] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[30]: copy n[29] => _12 @ bb7[9]: fn recur; _12 = _2; - n[31]: copy n[30] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[32]: copy n[31] => _8 @ bb1[2]: fn recur; _8 = _2; - n[33]: copy n[32] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); - n[34]: free n[33] => _0 @ bb1[5]: fn recur; _0 = free(move _7); - n[35]: copy n[31] => _13 @ bb8[4]: fn recur; _13 = _2; - n[36]: copy n[31] => _13 @ bb8[4]: fn recur; _13 = _2; - n[37]: copy n[31] => _13 @ bb8[4]: fn recur; _13 = _2; -} -nodes_that_need_write = [23, 21, 20, 18, 17, 11, 10, 9, 8, 5, 4, 3, 2, 1, 0] - -g { - n[0]: &_1 _ => _ @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); + n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); + n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; + n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; + n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); + n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); + n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); + n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; + n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; + n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); + n[25]: copy n[24] => _12 @ bb7[9]: fn recur; _12 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); + n[27]: copy n[26] => _12 @ bb7[9]: fn recur; _12 = _2; + n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); + n[29]: copy n[28] => _12 @ bb7[9]: fn recur; _12 = _2; + n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); + n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; + n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); + n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); + n[34]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; + n[35]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; + n[36]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; +} +nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); + n[6]: copy n[1] => _13 @ bb3[7]: fn exercise_allocator; _13 = _1; + n[7]: copy n[6] => _12 @ bb3[8]: fn exercise_allocator; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); } -nodes_that_need_write = [] - -g { - n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _10 @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb2[18]: fn exercise_allocator; _10 = ((*_1).0: i32); - n[6]: copy n[1] => _13 @ bb3[7]: fn exercise_allocator; _13 = _1; - n[7]: copy n[6] => _12 @ bb3[8]: fn exercise_allocator; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); -} -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: copy _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; @@ -194,147 +189,147 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); - n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); - n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; - n[3]: offset[0] n[2] => _18 @ bb6[7]: fn exercise_allocator; _18 = offset(move _19, const 0_isize); - n[4]: field.0 n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; - n[6]: copy n[1] => _21 @ bb7[5]: fn exercise_allocator; _21 = _1; - n[7]: offset[1] n[6] => _20 @ bb7[6]: fn exercise_allocator; _20 = offset(move _21, const 1_isize); - n[8]: field.0 n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; - n[10]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; - n[11]: offset[0] n[10] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); - n[12]: field.0 n[11] => _32 @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[13]: addr.load n[12] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[14]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; - n[15]: offset[1] n[14] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); - n[16]: field.0 n[15] => _32 @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[17]: addr.load n[16] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); - n[18]: copy n[1] => _42 @ bb20[6]: fn exercise_allocator; _42 = _1; - n[19]: copy n[18] => _41 @ bb20[7]: fn exercise_allocator; _41 = move _42 as *mut libc::c_void (Misc); - n[20]: copy n[1] => _4 @ bb0[1]: fn reallocarray; _4 = _1; - n[21]: copy n[20] => _1 @ bb0[10]: fn reallocarray; _0 = const pointers::REALLOC(move _4, move _5); - n[22]: free n[19] => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); -} -nodes_that_need_write = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); - n[1]: copy n[0] => _1 @ bb22[3]: fn exercise_allocator; _1 = move _40 as *mut pointers::S (Misc); - n[2]: copy n[1] => _47 @ bb22[7]: fn exercise_allocator; _47 = _1; - n[3]: offset[0] n[2] => _46 @ bb22[8]: fn exercise_allocator; _46 = offset(move _47, const 0_isize); - n[4]: field.0 n[3] => _ @ bb23[1]: fn exercise_allocator; ((*_46).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb23[1]: fn exercise_allocator; ((*_46).0: i32) = const 10_i32; - n[6]: copy n[1] => _49 @ bb23[5]: fn exercise_allocator; _49 = _1; - n[7]: offset[1] n[6] => _48 @ bb23[6]: fn exercise_allocator; _48 = offset(move _49, const 1_isize); - n[8]: field.0 n[7] => _ @ bb24[1]: fn exercise_allocator; ((*_48).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb24[1]: fn exercise_allocator; ((*_48).0: i32) = const 11_i32; - n[10]: copy n[1] => _51 @ bb24[5]: fn exercise_allocator; _51 = _1; - n[11]: offset[2] n[10] => _50 @ bb24[6]: fn exercise_allocator; _50 = offset(move _51, const 2_isize); - n[12]: field.0 n[11] => _ @ bb25[1]: fn exercise_allocator; ((*_50).0: i32) = const 12_i32; - n[13]: addr.store n[12] => _ @ bb25[1]: fn exercise_allocator; ((*_50).0: i32) = const 12_i32; - n[14]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; - n[15]: offset[0] n[14] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); - n[16]: field.0 n[15] => _61 @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[17]: addr.load n[16] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[18]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; - n[19]: offset[1] n[18] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); - n[20]: field.0 n[19] => _61 @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[21]: addr.load n[20] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[22]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; - n[23]: offset[2] n[22] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); - n[24]: field.0 n[23] => _61 @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[25]: addr.load n[24] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); - n[26]: copy n[1] => _71 @ bb37[6]: fn exercise_allocator; _71 = _1; - n[27]: copy n[26] => _70 @ bb37[7]: fn exercise_allocator; _70 = move _71 as *mut libc::c_void (Misc); - n[28]: free n[27] => _69 @ bb37[9]: fn exercise_allocator; _69 = free(move _70); -} -nodes_that_need_write = [13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _72 @ bb39[2]: fn exercise_allocator; _72 = calloc(move _73, move _74); - n[1]: copy n[0] => _1 @ bb40[2]: fn exercise_allocator; _1 = move _72 as *mut pointers::S (Misc); - n[2]: copy n[1] => _77 @ bb40[6]: fn exercise_allocator; _77 = _1; - n[3]: offset[0] n[2] => _76 @ bb40[7]: fn exercise_allocator; _76 = offset(move _77, const 0_isize); - n[4]: field.0 n[3] => _ @ bb41[1]: fn exercise_allocator; ((*_76).0: i32) = const 10_i32; - n[5]: addr.store n[4] => _ @ bb41[1]: fn exercise_allocator; ((*_76).0: i32) = const 10_i32; - n[6]: copy n[1] => _79 @ bb41[5]: fn exercise_allocator; _79 = _1; - n[7]: offset[1] n[6] => _78 @ bb41[6]: fn exercise_allocator; _78 = offset(move _79, const 1_isize); - n[8]: field.0 n[7] => _ @ bb42[1]: fn exercise_allocator; ((*_78).0: i32) = const 11_i32; - n[9]: addr.store n[8] => _ @ bb42[1]: fn exercise_allocator; ((*_78).0: i32) = const 11_i32; - n[10]: copy n[1] => _81 @ bb42[5]: fn exercise_allocator; _81 = _1; - n[11]: offset[2] n[10] => _80 @ bb42[6]: fn exercise_allocator; _80 = offset(move _81, const 2_isize); - n[12]: field.0 n[11] => _ @ bb43[1]: fn exercise_allocator; ((*_80).0: i32) = const 12_i32; - n[13]: addr.store n[12] => _ @ bb43[1]: fn exercise_allocator; ((*_80).0: i32) = const 12_i32; - n[14]: copy n[1] => _83 @ bb43[5]: fn exercise_allocator; _83 = _1; - n[15]: offset[3] n[14] => _82 @ bb43[6]: fn exercise_allocator; _82 = offset(move _83, const 3_isize); - n[16]: field.0 n[15] => _ @ bb44[1]: fn exercise_allocator; ((*_82).0: i32) = const 13_i32; - n[17]: addr.store n[16] => _ @ bb44[1]: fn exercise_allocator; ((*_82).0: i32) = const 13_i32; - n[18]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; - n[19]: offset[0] n[18] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); - n[20]: field.0 n[19] => _93 @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[21]: addr.load n[20] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[22]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; - n[23]: offset[1] n[22] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); - n[24]: field.0 n[23] => _93 @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[25]: addr.load n[24] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[26]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; - n[27]: offset[2] n[26] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); - n[28]: field.0 n[27] => _93 @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[29]: addr.load n[28] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[30]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; - n[31]: offset[3] n[30] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); - n[32]: field.0 n[31] => _93 @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[33]: addr.load n[32] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); - n[34]: copy n[1] => _103 @ bb56[6]: fn exercise_allocator; _103 = _1; - n[35]: copy n[34] => _102 @ bb56[7]: fn exercise_allocator; _102 = move _103 as *mut libc::c_void (Misc); - n[36]: free n[35] => _101 @ bb56[9]: fn exercise_allocator; _101 = free(move _102); -} -nodes_that_need_write = [17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _10 @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); - n[6]: copy n[1] => _13 @ bb3[7]: fn simple_analysis; _13 = _1; - n[7]: copy n[6] => _12 @ bb3[8]: fn simple_analysis; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb3[10]: fn simple_analysis; _11 = free(move _12); + n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); + n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); + n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; + n[3]: offset[0] n[2] => _18 @ bb6[7]: fn exercise_allocator; _18 = offset(move _19, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb7[1]: fn exercise_allocator; ((*_18).0: i32) = const 10_i32; + n[6]: copy n[1] => _21 @ bb7[5]: fn exercise_allocator; _21 = _1; + n[7]: offset[1] n[6] => _20 @ bb7[6]: fn exercise_allocator; _20 = offset(move _21, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb8[1]: fn exercise_allocator; ((*_20).0: i32) = const 11_i32; + n[10]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; + n[11]: offset[0] n[10] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); + n[12]: project[0]@0 n[11] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[13]: addr.load n[11] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[14]: copy n[1] => _34 @ bb11[14]: fn exercise_allocator; _34 = _1; + n[15]: offset[1] n[14] => _33 @ bb11[20]: fn exercise_allocator; _33 = offset(move _34, move _35); + n[16]: project[0]@0 n[15] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[17]: addr.load n[15] => _ @ bb13[2]: fn exercise_allocator; _32 = ((*_33).0: i32); + n[18]: copy n[1] => _42 @ bb20[6]: fn exercise_allocator; _42 = _1; + n[19]: copy n[18] => _41 @ bb20[7]: fn exercise_allocator; _41 = move _42 as *mut libc::c_void (Misc); + n[20]: copy n[1] => _4 @ bb0[1]: fn reallocarray; _4 = _1; + n[21]: copy n[20] => _1 @ bb0[10]: fn reallocarray; _0 = const pointers::REALLOC(move _4, move _5); + n[22]: free n[19] => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); +} +nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); + n[1]: copy n[0] => _1 @ bb22[3]: fn exercise_allocator; _1 = move _40 as *mut pointers::S (Misc); + n[2]: copy n[1] => _47 @ bb22[7]: fn exercise_allocator; _47 = _1; + n[3]: offset[0] n[2] => _46 @ bb22[8]: fn exercise_allocator; _46 = offset(move _47, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb23[1]: fn exercise_allocator; ((*_46).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb23[1]: fn exercise_allocator; ((*_46).0: i32) = const 10_i32; + n[6]: copy n[1] => _49 @ bb23[5]: fn exercise_allocator; _49 = _1; + n[7]: offset[1] n[6] => _48 @ bb23[6]: fn exercise_allocator; _48 = offset(move _49, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb24[1]: fn exercise_allocator; ((*_48).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb24[1]: fn exercise_allocator; ((*_48).0: i32) = const 11_i32; + n[10]: copy n[1] => _51 @ bb24[5]: fn exercise_allocator; _51 = _1; + n[11]: offset[2] n[10] => _50 @ bb24[6]: fn exercise_allocator; _50 = offset(move _51, const 2_isize); + n[12]: project[0]@0 n[11] => _ @ bb25[1]: fn exercise_allocator; ((*_50).0: i32) = const 12_i32; + n[13]: addr.store n[11] => _ @ bb25[1]: fn exercise_allocator; ((*_50).0: i32) = const 12_i32; + n[14]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; + n[15]: offset[0] n[14] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); + n[16]: project[0]@0 n[15] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[17]: addr.load n[15] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[18]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; + n[19]: offset[1] n[18] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); + n[20]: project[0]@0 n[19] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[21]: addr.load n[19] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[22]: copy n[1] => _63 @ bb28[14]: fn exercise_allocator; _63 = _1; + n[23]: offset[2] n[22] => _62 @ bb28[20]: fn exercise_allocator; _62 = offset(move _63, move _64); + n[24]: project[0]@0 n[23] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[25]: addr.load n[23] => _ @ bb30[2]: fn exercise_allocator; _61 = ((*_62).0: i32); + n[26]: copy n[1] => _71 @ bb37[6]: fn exercise_allocator; _71 = _1; + n[27]: copy n[26] => _70 @ bb37[7]: fn exercise_allocator; _70 = move _71 as *mut libc::c_void (Misc); + n[28]: free n[27] => _69 @ bb37[9]: fn exercise_allocator; _69 = free(move _70); +} +nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _72 @ bb39[2]: fn exercise_allocator; _72 = calloc(move _73, move _74); + n[1]: copy n[0] => _1 @ bb40[2]: fn exercise_allocator; _1 = move _72 as *mut pointers::S (Misc); + n[2]: copy n[1] => _77 @ bb40[6]: fn exercise_allocator; _77 = _1; + n[3]: offset[0] n[2] => _76 @ bb40[7]: fn exercise_allocator; _76 = offset(move _77, const 0_isize); + n[4]: project[0]@0 n[3] => _ @ bb41[1]: fn exercise_allocator; ((*_76).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb41[1]: fn exercise_allocator; ((*_76).0: i32) = const 10_i32; + n[6]: copy n[1] => _79 @ bb41[5]: fn exercise_allocator; _79 = _1; + n[7]: offset[1] n[6] => _78 @ bb41[6]: fn exercise_allocator; _78 = offset(move _79, const 1_isize); + n[8]: project[0]@0 n[7] => _ @ bb42[1]: fn exercise_allocator; ((*_78).0: i32) = const 11_i32; + n[9]: addr.store n[7] => _ @ bb42[1]: fn exercise_allocator; ((*_78).0: i32) = const 11_i32; + n[10]: copy n[1] => _81 @ bb42[5]: fn exercise_allocator; _81 = _1; + n[11]: offset[2] n[10] => _80 @ bb42[6]: fn exercise_allocator; _80 = offset(move _81, const 2_isize); + n[12]: project[0]@0 n[11] => _ @ bb43[1]: fn exercise_allocator; ((*_80).0: i32) = const 12_i32; + n[13]: addr.store n[11] => _ @ bb43[1]: fn exercise_allocator; ((*_80).0: i32) = const 12_i32; + n[14]: copy n[1] => _83 @ bb43[5]: fn exercise_allocator; _83 = _1; + n[15]: offset[3] n[14] => _82 @ bb43[6]: fn exercise_allocator; _82 = offset(move _83, const 3_isize); + n[16]: project[0]@0 n[15] => _ @ bb44[1]: fn exercise_allocator; ((*_82).0: i32) = const 13_i32; + n[17]: addr.store n[15] => _ @ bb44[1]: fn exercise_allocator; ((*_82).0: i32) = const 13_i32; + n[18]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; + n[19]: offset[0] n[18] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); + n[20]: project[0]@0 n[19] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[21]: addr.load n[19] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[22]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; + n[23]: offset[1] n[22] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); + n[24]: project[0]@0 n[23] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[25]: addr.load n[23] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[26]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; + n[27]: offset[2] n[26] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); + n[28]: project[0]@0 n[27] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[29]: addr.load n[27] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[30]: copy n[1] => _95 @ bb47[14]: fn exercise_allocator; _95 = _1; + n[31]: offset[3] n[30] => _94 @ bb47[20]: fn exercise_allocator; _94 = offset(move _95, move _96); + n[32]: project[0]@0 n[31] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[33]: addr.load n[31] => _ @ bb49[2]: fn exercise_allocator; _93 = ((*_94).0: i32); + n[34]: copy n[1] => _103 @ bb56[6]: fn exercise_allocator; _103 = _1; + n[35]: copy n[34] => _102 @ bb56[7]: fn exercise_allocator; _102 = move _103 as *mut libc::c_void (Misc); + n[36]: free n[35] => _101 @ bb56[9]: fn exercise_allocator; _101 = free(move _102); +} +nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] + +g { + n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb2[18]: fn simple_analysis; _10 = ((*_1).0: i32); + n[6]: copy n[1] => _13 @ bb3[7]: fn simple_analysis; _13 = _1; + n[7]: copy n[6] => _12 @ bb3[8]: fn simple_analysis; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb3[10]: fn simple_analysis; _11 = free(move _12); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _6 @ bb2[8]: fn analysis2; _6 = _1; - n[5]: copy n[4] => _1 @ bb0[0]: fn analysis2_helper; _5 = analysis2_helper(move _6); - n[6]: field.0 n[5] => _7 @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); - n[8]: copy n[5] => _9 @ bb3[5]: fn analysis2; _9 = _1; - n[9]: copy n[8] => _8 @ bb3[6]: fn analysis2; _8 = move _9 as *mut libc::c_void (Misc); - n[10]: free n[9] => _7 @ bb3[8]: fn analysis2; _7 = free(move _8); + n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _6 @ bb2[8]: fn analysis2; _6 = _1; + n[5]: copy n[4] => _1 @ bb0[0]: fn analysis2_helper; _5 = analysis2_helper(move _6); + n[6]: project[0]@0 n[5] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); + n[7]: addr.load n[5] => _ @ bb0[12]: fn analysis2_helper; _7 = ((*_1).0: i32); + n[8]: copy n[5] => _9 @ bb3[5]: fn analysis2; _9 = _1; + n[9]: copy n[8] => _8 @ bb3[6]: fn analysis2; _8 = move _9 as *mut libc::c_void (Misc); + n[10]: free n[9] => _7 @ bb3[8]: fn analysis2; _7 = free(move _8); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); - n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); - n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); - n[3]: field.0 n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; - n[4]: addr.store n[3] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; - n[5]: field.0 n[2] => _10 @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); - n[6]: addr.load n[5] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); - n[7]: copy n[2] => _13 @ bb3[7]: fn inter_function_analysis; _13 = _1; - n[8]: copy n[7] => _12 @ bb3[8]: fn inter_function_analysis; _12 = move _13 as *mut libc::c_void (Misc); - n[9]: free n[8] => _11 @ bb3[10]: fn inter_function_analysis; _11 = free(move _12); + n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); + n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); + n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); + n[3]: project[0]@0 n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; + n[4]: addr.store n[2] => _ @ bb2[5]: fn inter_function_analysis; ((*_1).0: i32) = const 11_i32; + n[5]: project[0]@0 n[2] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); + n[6]: addr.load n[2] => _ @ bb2[18]: fn inter_function_analysis; _10 = ((*_1).0: i32); + n[7]: copy n[2] => _13 @ bb3[7]: fn inter_function_analysis; _13 = _1; + n[8]: copy n[7] => _12 @ bb3[8]: fn inter_function_analysis; _12 = move _13 as *mut libc::c_void (Misc); + n[9]: free n[8] => _11 @ bb3[10]: fn inter_function_analysis; _11 = free(move _12); } -nodes_that_need_write = [4, 3, 2, 1, 0] +nodes_that_need_write = [4, 2, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -346,23 +341,24 @@ g { nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: field.0 n[10] => _18 @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: addr.load n[11] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[13]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[14]: addr.store n[13] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; + n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; + n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; + n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; + n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[12]: project[0]@0 n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[13]: addr.load n[12] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[14]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; + n[15]: addr.store n[14] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [14, 13, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [15, 14, 9, 8, 5, 4, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -374,19 +370,20 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _5 @ bb2[7]: fn invalid; _5 = _1; - n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; - n[6]: field.0 n[1] => _12 @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[7]: addr.load n[6] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; - n[9]: copy n[8] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); - n[10]: free n[9] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); + n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _5 @ bb2[7]: fn invalid; _5 = _1; + n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; + n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); + n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); + n[8]: value.load _ => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; + n[10]: copy n[9] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); + n[11]: free n[10] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; @@ -419,19 +416,19 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; - n[3]: field.0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[4]: addr.store n[3] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; - n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); - n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; - n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); - n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); + n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); + n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; + n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; + n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; + n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; + n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); + n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); } -nodes_that_need_write = [4, 3, 2, 1, 0] +nodes_that_need_write = [4, 2, 1, 0] g { n[0]: &_13 _ => _ @ bb4[14]: fn simple1; _22 = &raw mut _13; @@ -464,116 +461,116 @@ g { nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4] g { - n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); - n[2]: field.0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[3]: addr.store n[2] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[7]: field.0 n[6] => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[8]: addr.load n[7] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); - n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; - n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); - n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); - n[15]: field.0 n[14] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[16]: addr.load n[15] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[17]: field.0 n[14] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[18]: addr.load n[17] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[19]: copy n[15] => _23 @ bb7[5]: fn lighttpd_test; _23 = _5; - n[20]: copy n[19] => _22 @ bb7[6]: fn lighttpd_test; _22 = move _23 as *mut libc::c_void (Misc); - n[21]: free n[20] => _21 @ bb7[8]: fn lighttpd_test; _21 = free(move _22); + n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; + n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; + n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; + n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); + n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; + n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); + n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); + n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[17]: project[0]@0 n[14] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[18]: addr.load n[14] => _ @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[19]: copy n[1] => _23 @ bb7[5]: fn lighttpd_test; _23 = _5; + n[20]: copy n[19] => _22 @ bb7[6]: fn lighttpd_test; _22 = move _23 as *mut libc::c_void (Misc); + n[21]: free n[20] => _21 @ bb7[8]: fn lighttpd_test; _21 = free(move _22); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; - n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; - n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); - n[3]: copy n[2] => _14 @ bb4[18]: fn lighttpd_test; _14 = &raw mut (*_10); - n[4]: copy n[3] => _1 @ bb0[0]: fn connection_accepted; _13 = connection_accepted(move _14, const 0_i32); - n[5]: field.0 n[4] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[6]: addr.load n[5] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); - n[7]: copy n[5] => _16 @ bb5[4]: fn lighttpd_test; _16 = &raw mut (*_10); - n[8]: copy n[7] => _1 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); - n[9]: field.0 n[8] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[10]: addr.load n[9] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); - n[11]: field.0 n[8] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); - n[12]: addr.load n[11] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; + n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; + n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); + n[3]: copy n[2] => _14 @ bb4[18]: fn lighttpd_test; _14 = &raw mut (*_10); + n[4]: copy n[3] => _1 @ bb0[0]: fn connection_accepted; _13 = connection_accepted(move _14, const 0_i32); + n[5]: project[0]@0 n[4] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[6]: addr.load n[4] => _ @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[7]: copy n[2] => _16 @ bb5[4]: fn lighttpd_test; _16 = &raw mut (*_10); + n[8]: copy n[7] => _1 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); + n[9]: project[0]@0 n[8] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[10]: addr.load n[8] => _ @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[11]: project[0]@0 n[8] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[12]: addr.load n[8] => _ @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); } nodes_that_need_write = [1, 0] g { - n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); - n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); - n[2]: field.0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; - n[3]: addr.store n[2] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; - n[4]: field.0 n[1] => _11 @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); - n[5]: addr.load n[4] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); - n[6]: copy n[1] => _15 @ bb2[20]: fn connection_accepted; _15 = _4; - n[7]: copy n[6] => _14 @ bb2[21]: fn connection_accepted; _14 = move _15 as *mut libc::c_void (Misc); - n[8]: copy n[7] => _4 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; - n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[11]: field.1 n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[12]: addr.store n[11] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; - n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); - n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; - n[16]: copy n[15] => _2 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); - n[17]: field.1 n[16] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[18]: addr.load n[17] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[19]: field.0 n[16] => _8 @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); - n[20]: addr.load n[19] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); - n[21]: copy n[16] => _11 @ bb2[6]: fn connection_close; _11 = _2; - n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); - n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); -} -nodes_that_need_write = [12, 11, 3, 2, 1, 0] - -g { - n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); - n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); - n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; - n[3]: copy n[2] => _1 @ bb0[0]: fn is_null; _9 = is_null(move _10); - n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; - n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); - n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; - n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[8]: field.0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; - n[9]: addr.store n[8] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; - n[10]: field.2 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; - n[11]: addr.store n[10] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; - n[12]: field.1 n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[13]: addr.store n[12] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; - n[14]: field.3 n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; - n[15]: addr.store n[14] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; - n[16]: field.4 n[7] => _ @ bb2[24]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); - n[17]: addr.store n[16] => _ @ bb2[24]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); - n[18]: copy n[7] => _0 @ bb2[26]: fn fdevent_register; _0 = _12; - n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); - n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); - n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); - n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; - n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); - n[25]: copy n[22] => _8 @ bb2[4]: fn fdevent_fdnode_event_del; _8 = _2; - n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[27]: field.4 n[26] => _7 @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); - n[28]: addr.load n[27] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); - n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; - n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); - n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; - n[33]: copy n[32] => _1 @ bb0[0]: fn fdnode_free; _22 = fdnode_free(move _23); - n[34]: copy n[33] => _4 @ bb0[3]: fn fdnode_free; _4 = _1; - n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); - n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); -} -nodes_that_need_write = [17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7] + n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); + n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; + n[3]: addr.store n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; + n[4]: project[0]@0 n[1] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); + n[5]: addr.load n[1] => _ @ bb2[12]: fn connection_accepted; _11 = ((*_4).0: i32); + n[6]: copy n[1] => _15 @ bb2[20]: fn connection_accepted; _15 = _4; + n[7]: copy n[6] => _14 @ bb2[21]: fn connection_accepted; _14 = move _15 as *mut libc::c_void (Misc); + n[8]: copy n[7] => _4 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; + n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[11]: project[1]@8 n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[12]: addr.store n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; + n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); + n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; + n[16]: copy n[15] => _2 @ bb0[0]: fn connection_close; _15 = connection_close(move _16, move _17); + n[17]: project[1]@8 n[16] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[18]: addr.load n[16] => _ @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[19]: project[0]@0 n[16] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); + n[20]: addr.load n[16] => _ @ bb1[7]: fn connection_close; _8 = ((*_2).0: i32); + n[21]: copy n[16] => _11 @ bb2[6]: fn connection_close; _11 = _2; + n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); + n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); +} +nodes_that_need_write = [12, 3, 1, 0] + +g { + n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); + n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); + n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; + n[3]: copy n[2] => _1 @ bb0[0]: fn is_null; _9 = is_null(move _10); + n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; + n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); + n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; + n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); + n[8]: project[0]@0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; + n[9]: addr.store n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; + n[10]: project[2]@16 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; + n[11]: addr.store n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; + n[12]: project[1]@8 n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[13]: addr.store n[7] => _ @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; + n[14]: project[3]@20 n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; + n[15]: addr.store n[7] => _ @ bb2[20]: fn fdevent_register; ((*_12).3: i32) = move _16; + n[16]: project[4]@24 n[7] => _ @ bb2[24]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); + n[17]: addr.store n[7] => _ @ bb2[24]: fn fdevent_register; ((*_12).4: i32) = Neg(move _17); + n[18]: copy n[7] => _0 @ bb2[26]: fn fdevent_register; _0 = _12; + n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); + n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); + n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; + n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); + n[25]: copy n[22] => _8 @ bb2[4]: fn fdevent_fdnode_event_del; _8 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); + n[27]: project[4]@24 n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); + n[28]: addr.load n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); + n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; + n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); + n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; + n[33]: copy n[32] => _1 @ bb0[0]: fn fdnode_free; _22 = fdnode_free(move _23); + n[34]: copy n[33] => _4 @ bb0[3]: fn fdnode_free; _4 = _1; + n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); + n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); +} +nodes_that_need_write = [17, 15, 13, 11, 9, 7] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); @@ -717,67 +714,65 @@ g { nodes_that_need_write = [] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; - n[4]: copy n[1] => _7 @ bb2[8]: fn test_store_addr; _7 = _1; - n[5]: copy n[4] => _6 @ bb2[9]: fn test_store_addr; _6 = move _7 as *mut libc::c_void (Misc); - n[6]: free n[5] => _5 @ bb2[11]: fn test_store_addr; _5 = free(move _6); + n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; + n[4]: copy n[1] => _7 @ bb2[8]: fn test_store_addr; _7 = _1; + n[5]: copy n[4] => _6 @ bb2[9]: fn test_store_addr; _6 = move _7 as *mut libc::c_void (Misc); + n[6]: free n[5] => _5 @ bb2[11]: fn test_store_addr; _5 = free(move _6); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; - n[3]: addr.store n[2] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; - n[4]: field.0 n[1] => _9 @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); - n[5]: addr.load n[4] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); - n[6]: copy n[1] => _12 @ bb4[12]: fn test_load_other_store_self; _12 = _1; - n[7]: copy n[6] => _11 @ bb4[13]: fn test_load_other_store_self; _11 = move _12 as *mut libc::c_void (Misc); - n[8]: free n[7] => _10 @ bb4[15]: fn test_load_other_store_self; _10 = free(move _11); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; + n[3]: addr.store n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; + n[4]: project[0]@0 n[1] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); + n[5]: addr.load n[1] => _ @ bb4[6]: fn test_load_other_store_self; _9 = ((*_1).0: i32); + n[6]: copy n[1] => _12 @ bb4[12]: fn test_load_other_store_self; _12 = _1; + n[7]: copy n[6] => _11 @ bb4[13]: fn test_load_other_store_self; _11 = move _12 as *mut libc::c_void (Misc); + n[8]: free n[7] => _10 @ bb4[15]: fn test_load_other_store_self; _10 = free(move _11); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; - n[3]: addr.store n[2] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; - n[4]: copy n[1] => _15 @ bb5[5]: fn test_load_other_store_self; _15 = _5; - n[5]: copy n[4] => _14 @ bb5[6]: fn test_load_other_store_self; _14 = move _15 as *mut libc::c_void (Misc); - n[6]: free n[5] => _13 @ bb5[8]: fn test_load_other_store_self; _13 = free(move _14); + n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; + n[3]: addr.store n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; + n[4]: copy n[1] => _15 @ bb5[5]: fn test_load_other_store_self; _15 = _5; + n[5]: copy n[4] => _14 @ bb5[6]: fn test_load_other_store_self; _14 = move _15 as *mut libc::c_void (Misc); + n[6]: free n[5] => _13 @ bb5[8]: fn test_load_other_store_self; _13 = free(move _14); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); - n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.3 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[3]: field.3 n[2] => _6 @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[4]: addr.load n[3] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); - n[5]: field.3 n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[6]: field.3 n[5] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[7]: addr.store n[6] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; - n[8]: copy n[1] => _9 @ bb2[12]: fn test_load_self_store_self; _9 = _1; - n[9]: copy n[8] => _8 @ bb2[13]: fn test_load_self_store_self; _8 = move _9 as *mut libc::c_void (Misc); - n[10]: free n[9] => _7 @ bb2[15]: fn test_load_self_store_self; _7 = free(move _8); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); + n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[3, 3]@48 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); + n[3]: addr.load n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); + n[4]: project[3, 3]@48 n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; + n[5]: addr.store n[1] => _ @ bb2[7]: fn test_load_self_store_self; (((*_1).3: pointers::T).3: i32) = move _6; + n[6]: copy n[1] => _9 @ bb2[12]: fn test_load_self_store_self; _9 = _1; + n[7]: copy n[6] => _8 @ bb2[13]: fn test_load_self_store_self; _8 = move _9 as *mut libc::c_void (Misc); + n[8]: free n[7] => _7 @ bb2[15]: fn test_load_self_store_self; _7 = free(move _8); } -nodes_that_need_write = [7, 6, 5, 1, 0] +nodes_that_need_write = [5, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); - n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); - n[2]: field.0 n[1] => _6 @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); - n[3]: addr.load n[2] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); - n[4]: field.0 n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; - n[5]: addr.store n[4] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; - n[6]: copy n[1] => _10 @ bb2[15]: fn test_load_self_store_self_inter; _10 = _1; - n[7]: copy n[6] => _9 @ bb2[16]: fn test_load_self_store_self_inter; _9 = move _10 as *mut libc::c_void (Misc); - n[8]: free n[7] => _8 @ bb2[18]: fn test_load_self_store_self_inter; _8 = free(move _9); + n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); + n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); + n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); + n[3]: addr.load n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); + n[4]: project[0]@0 n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; + n[5]: addr.store n[1] => _ @ bb2[10]: fn test_load_self_store_self_inter; ((*_1).0: i32) = move _7; + n[6]: copy n[1] => _10 @ bb2[15]: fn test_load_self_store_self_inter; _10 = _1; + n[7]: copy n[6] => _9 @ bb2[16]: fn test_load_self_store_self_inter; _9 = move _10 as *mut libc::c_void (Misc); + n[8]: free n[7] => _8 @ bb2[18]: fn test_load_self_store_self_inter; _8 = free(move _9); } -nodes_that_need_write = [5, 4, 1, 0] +nodes_that_need_write = [5, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); @@ -823,32 +818,32 @@ g { nodes_that_need_write = [3, 2, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; - n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[5]: field.2 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[6]: addr.store n[5] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; - n[8]: copy n[1] => _16 @ bb5[5]: fn test_store_value_field; _16 = _1; - n[9]: copy n[8] => _15 @ bb5[6]: fn test_store_value_field; _15 = move _16 as *mut libc::c_void (Misc); - n[10]: free n[9] => _14 @ bb5[8]: fn test_store_value_field; _14 = free(move _15); + n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; + n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[5]: project[2]@16 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[6]: addr.store n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; + n[8]: copy n[1] => _16 @ bb5[5]: fn test_store_value_field; _16 = _1; + n[9]: copy n[8] => _15 @ bb5[6]: fn test_store_value_field; _15 = move _16 as *mut libc::c_void (Misc); + n[10]: free n[9] => _14 @ bb5[8]: fn test_store_value_field; _14 = free(move _15); } -nodes_that_need_write = [6, 5, 1, 0] +nodes_that_need_write = [6, 1, 0] g { - n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); - n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); - n[2]: field.2 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[3]: addr.store n[2] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: field.2 n[1] => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[5]: addr.load n[4] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); - n[6]: copy n[1] => _13 @ bb4[15]: fn test_store_value_field; _13 = _5; - n[7]: copy n[6] => _12 @ bb4[16]: fn test_store_value_field; _12 = move _13 as *mut libc::c_void (Misc); - n[8]: free n[7] => _11 @ bb4[18]: fn test_store_value_field; _11 = free(move _12); + n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); + n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); + n[2]: project[2]@16 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[3]: addr.store n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); + n[4]: project[2]@16 n[1] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[5]: addr.load n[1] => _ @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[6]: copy n[1] => _13 @ bb4[15]: fn test_store_value_field; _13 = _5; + n[7]: copy n[6] => _12 @ bb4[16]: fn test_store_value_field; _12 = move _13 as *mut libc::c_void (Misc); + n[8]: free n[7] => _11 @ bb4[18]: fn test_store_value_field; _11 = free(move _12); } -nodes_that_need_write = [3, 2, 1, 0] +nodes_that_need_write = [3, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); @@ -951,17 +946,15 @@ g { nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] g { - n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; - n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; - n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); - n[3]: field.3 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: field.3 n[3] => _7 @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[5]: addr.load n[4] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[6]: field.3 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[7]: field.3 n[6] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[8]: addr.store n[7] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; + n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; + n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); + n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); + n[4]: addr.load n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); + n[5]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[6]: addr.store n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [8, 7, 6, 2, 1, 0] +nodes_that_need_write = [6, 2, 1, 0] g { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _8 = &raw mut _1; @@ -973,12 +966,12 @@ g { nodes_that_need_write = [1, 0] g { - n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; - n[1]: field.2 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[2]: addr.store n[1] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: copy n[0] => _2 @ bb0[3]: fn test_addr_taken_arg; _2 = &(*_3); + n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; + n[1]: project[2]@16 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[2]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: copy n[0] => _2 @ bb0[3]: fn test_addr_taken_arg; _2 = &(*_3); } -nodes_that_need_write = [2, 1, 0] +nodes_that_need_write = [2, 0] g { n[0]: &_3 _ => _ @ bb2[2]: fn test_addr_taken_loop; _19 = &raw mut _3; @@ -1029,6 +1022,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 67 -num_nodes = 759 +num_graphs = 66 +num_nodes = 755 From 72fe7e407e7d44c33589298eca41ecf2d064fba0 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Thu, 13 Jun 2024 00:41:07 -0700 Subject: [PATCH 03/17] Build PDG without tracking assignments The event assignment-based PDG construction steps were giving incorrect results for indirect accesses, so remove them completely. --- pdg/src/builder.rs | 61 ++----- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 164 +++++++++--------- ...lysis_tests_misc_pdg_snapshot_release.snap | 164 +++++++++--------- 3 files changed, 176 insertions(+), 213 deletions(-) diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index 05c414b2ac..63baafc81a 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -138,7 +138,7 @@ fn update_provenance( Realloc { new_ptr, .. } => { provenances.insert(new_ptr, mapping); } - Offset(_, _, new_ptr) => { + Offset(_, _, new_ptr) | Project(_, new_ptr, _) => { provenances.insert(new_ptr, mapping); } CopyRef => { @@ -167,7 +167,7 @@ pub fn add_node( let node_kind = event.kind.to_node_kind(func.id, metadata, address_taken)?; let this_id = func.id; - let (src_fn, dest_fn) = match event_metadata.transfer_kind { + let (_src_fn, dest_fn) = match event_metadata.transfer_kind { TransferKind::None => (this_id, this_id), TransferKind::Arg(id) => (this_id, id), TransferKind::Ret(id) => (id, this_id), @@ -189,37 +189,22 @@ pub fn add_node( .iter() .rposition(|n| { if let (Some(d), Some(s)) = (&n.dest, &event_metadata.source) { - d == s + // TODO: Ignore direct assignments with projections for now, + // e.g., `_1.0 = _2;`. We should later add support for + // assignments to sub-fields, e.g. + // ``` + // _1 = _2; + // _1.0 = _3; + // _1 = _4; + // ``` + d == s && s.projection.is_empty() } else { false } }) .map(|nid| (gid, NodeId::from(nid))) }); - - let source = direct_source.or_else(|| { - event_metadata.source.as_ref().and_then(|src| { - let latest_assignment = graphs.latest_assignment.get(&(src_fn, src.local)).cloned(); - if !src.projection.is_empty() { - if let Some((gid, _)) = latest_assignment { - if let Some((nid, n)) = graphs.graphs[gid].nodes.iter_enumerated().rev().next() - { - if let NodeKind::Project(..) = n.kind { - return Some((gid, nid)); - } - } - } - } - - if !matches!(event.kind, EventKind::AddrOfLocal(..)) && src.projection.is_empty() { - latest_assignment - } else if let EventKind::Project(..) = event.kind { - latest_assignment - } else { - provenance - } - }) - }); + let source = direct_source.or(provenance); let function = Func { id: dest_fn, @@ -240,8 +225,6 @@ pub fn add_node( }; let graph_id = source - .or(direct_source) - .or(provenance) .and_then(|p| parent(&node_kind, p)) .map(|(gid, _)| gid) .unwrap_or_else(|| graphs.graphs.push(Graph::new())); @@ -254,26 +237,6 @@ pub fn add_node( (graph_id, node_id), ); - if let Some(dest) = &event_metadata.destination { - let unique_place = (dest_fn, dest.local); - let last_setting = (graph_id, node_id); - - if let Some(last @ (last_gid, last_nid)) = - graphs.latest_assignment.insert(unique_place, last_setting) - { - if !dest.projection.is_empty() - && graphs.graphs[last_gid].nodes[last_nid] - .dest - .as_ref() - .unwrap() - .projection - .is_empty() - { - graphs.latest_assignment.insert(unique_place, last); - } - } - } - Some(node_id) } diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index 7b4cf4d67c..f49ad7f3be 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -20,13 +20,13 @@ nodes_that_need_write = [] g { n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); - n[2]: int_to_ptr _ => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: value.store _ => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); - n[4]: value.store _ => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[5]: int_to_ptr _ => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[6]: int_to_ptr _ => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[7]: int_to_ptr _ => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[8]: value.store _ => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[4]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); + n[5]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[6]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[7]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[8]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -115,72 +115,72 @@ g { n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[5]: copy _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; + n[5]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; n[6]: copy n[5] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); n[7]: copy n[6] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); n[8]: copy n[7] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); n[9]: copy n[8] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[10]: copy _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; + n[10]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; n[11]: copy n[10] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); n[12]: copy n[11] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); n[13]: copy n[12] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); n[14]: copy n[13] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[15]: copy _ => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; + n[15]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; n[16]: copy n[15] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); n[17]: copy n[16] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); n[18]: copy n[17] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); n[19]: copy n[18] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[20]: copy _ => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; + n[20]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; n[21]: copy n[20] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); n[22]: copy n[21] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); n[23]: copy n[22] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[25]: copy _ => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; + n[25]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; n[26]: copy n[25] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); n[27]: copy n[26] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); n[28]: copy n[27] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); n[29]: copy n[28] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[30]: copy _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; + n[30]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; n[31]: copy n[30] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); n[32]: copy n[31] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); n[33]: copy n[32] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); n[34]: copy n[33] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[35]: copy _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; + n[35]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; n[36]: copy n[35] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); n[37]: copy n[36] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); n[38]: copy n[37] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); n[39]: copy n[38] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[40]: copy _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; + n[40]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; n[41]: copy n[40] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); n[42]: copy n[41] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); n[43]: copy n[42] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[45]: copy _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; + n[45]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; n[46]: copy n[45] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); n[47]: copy n[46] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); n[48]: copy n[47] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); n[49]: copy n[48] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[50]: copy _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; + n[50]: copy n[0] => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; n[51]: copy n[50] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); n[52]: copy n[51] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[53]: copy n[52] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); n[54]: copy n[53] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[55]: copy _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; + n[55]: copy n[0] => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; n[56]: copy n[55] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); n[57]: copy n[56] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); n[58]: copy n[57] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); n[59]: copy n[58] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); - n[60]: copy _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; + n[60]: copy n[0] => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; n[61]: copy n[60] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); n[62]: copy n[61] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[63]: copy n[62] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); n[64]: copy n[63] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[65]: copy _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; + n[65]: copy n[0] => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; n[66]: copy n[65] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); n[67]: copy n[66] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); n[68]: copy n[67] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); n[69]: copy n[68] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); - n[70]: copy _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; + n[70]: copy n[0] => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; n[71]: copy n[70] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); n[72]: copy n[71] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); n[73]: copy n[72] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); @@ -334,36 +334,34 @@ nodes_that_need_write = [4, 2, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: value.load _ => _12 @ bb6[6]: fn main_0; _12 = (*_13); + n[2]: value.load n[0] => _12 @ bb6[6]: fn main_0; _12 = (*_13); n[3]: copy n[2] => _11 @ bb6[7]: fn main_0; _11 = move _12 as *mut libc::c_void (Misc); n[4]: free n[3] => _10 @ bb6[9]: fn main_0; _10 = free(move _11); } nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: project[0]@0 n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[13]: addr.load n[12] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[14]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[15]: addr.store n[14] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: copy n[0] => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; + n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[4]: copy n[0] => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[6]: copy n[0] => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; + n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[8]: copy n[0] => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; + n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[10]: copy n[0] => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; + n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[12]: copy n[0] => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; + n[13]: addr.store n[12] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [15, 14, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [13, 12, 9, 8, 5, 4, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: value.load _ => _11 @ bb3[5]: fn no_owner; _11 = (*_12); + n[2]: value.load n[0] => _11 @ bb3[5]: fn no_owner; _11 = (*_12); n[3]: copy n[2] => _10 @ bb3[6]: fn no_owner; _10 = move _11 as *mut libc::c_void (Misc); n[4]: free n[3] => _9 @ bb3[8]: fn no_owner; _9 = free(move _10); } @@ -378,10 +376,12 @@ g { n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: value.load _ => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[9]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; - n[10]: copy n[9] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); - n[11]: free n[10] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); + n[8]: value.load n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: project[0]@0 n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[10]: addr.load n[9] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[11]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; + n[12]: copy n[11] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); + n[13]: free n[12] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); } nodes_that_need_write = [3, 1, 0] @@ -405,28 +405,28 @@ g { nodes_that_need_write = [3, 2, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; - n[3]: copy n[2] => _7 @ bb2[9]: fn simple1; _7 = move _8 as *mut libc::c_void (Misc); - n[4]: free n[3] => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[5]: copy n[1] => _16 @ bb4[21]: fn simple1; _16 = _1; - n[6]: ptr_to_int n[5] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); + n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; + n[3]: copy n[2] => _7 @ bb2[9]: fn simple1; _7 = move _8 as *mut libc::c_void (Misc); + n[4]: free n[3] => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); } nodes_that_need_write = [] g { - n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; - n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; - n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); - n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; - n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); - n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); + n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); + n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; + n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; + n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; + n[7]: copy n[3] => _16 @ bb4[21]: fn simple1; _16 = _1; + n[8]: ptr_to_int n[7] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); + n[9]: int_to_ptr n[3] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[10]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; + n[11]: copy n[10] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); + n[12]: free n[11] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); } nodes_that_need_write = [4, 2, 1, 0] @@ -442,15 +442,15 @@ g { n[1]: copy n[0] => _1 @ bb2[1]: fn lighttpd_test; _1 = move _2 as *mut *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn lighttpd_test; _9 = _1; n[3]: value.store n[2] => _5.*.0 @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[4]: value.load _ => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[4]: value.load n[0] => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[5]: offset[0] n[4] => _7 @ bb0[8]: fn fdevent_register; _7 = offset(move _8, move _9); n[6]: copy n[5] => _6 @ bb1[3]: fn fdevent_register; _6 = &mut (*_7); n[7]: addr.store n[6] => _ @ bb2[0]: fn fdevent_register; (*_6) = move _11; n[8]: addr.load n[6] => _ @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[9]: value.load _ => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load n[5] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[10]: offset[0] n[9] => _4 @ bb0[9]: fn fdevent_unregister; _4 = offset(move _5, move _6); n[11]: addr.load n[10] => _ @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[12]: value.load _ => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[12]: value.load n[10] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); n[13]: offset[0] n[12] => _18 @ bb7[10]: fn fdevent_unregister; _18 = offset(move _19, move _20); n[14]: copy n[13] => _17 @ bb8[3]: fn fdevent_unregister; _17 = &mut (*_18); n[15]: addr.store n[14] => _ @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); @@ -458,7 +458,7 @@ g { n[17]: copy n[16] => _19 @ bb6[7]: fn lighttpd_test; _19 = move _20 as *mut libc::c_void (Misc); n[18]: free n[17] => _18 @ bb6[9]: fn lighttpd_test; _18 = free(move _19); } -nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4] +nodes_that_need_write = [15, 14, 13, 12, 10, 9, 7, 6, 5, 4, 0] g { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); @@ -466,15 +466,15 @@ g { n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[5]: value.load n[2] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[9]: value.load n[7] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[13]: value.load n[7] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); @@ -516,7 +516,7 @@ g { n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; n[11]: project[1]@8 n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[12]: addr.store n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[12]: addr.store n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; @@ -529,7 +529,7 @@ g { n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); } -nodes_that_need_write = [12, 3, 1, 0] +nodes_that_need_write = [12, 8, 7, 6, 3, 1, 0] g { n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); @@ -539,7 +539,7 @@ g { n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; - n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); + n[7]: value.load n[0] => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); n[8]: project[0]@0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; n[9]: addr.store n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; n[10]: project[2]@16 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; @@ -553,7 +553,7 @@ g { n[18]: copy n[7] => _0 @ bb3[2]: fn fdevent_register; _0 = _12; n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[21]: value.load n[8] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); @@ -561,7 +561,7 @@ g { n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); n[27]: project[4]@24 n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); n[28]: addr.load n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); - n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[29]: value.load n[8] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; @@ -570,7 +570,7 @@ g { n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); } -nodes_that_need_write = [17, 15, 13, 11, 9, 7] +nodes_that_need_write = [17, 15, 13, 11, 9, 7, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); @@ -778,7 +778,7 @@ g { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_ptr_int_ptr; _5 = _1; n[2]: ptr_to_int n[1] => _ @ bb2[5]: fn test_ptr_int_ptr; _4 = move _5 as usize (PointerExposeAddress); - n[3]: int_to_ptr _ => _1 @ bb2[10]: fn test_ptr_int_ptr; _1 = move _6 as *mut libc::c_void (PointerFromExposedAddress); + n[3]: int_to_ptr n[0] => _1 @ bb2[10]: fn test_ptr_int_ptr; _1 = move _6 as *mut libc::c_void (PointerFromExposedAddress); n[4]: copy n[3] => _8 @ bb2[14]: fn test_ptr_int_ptr; _8 = _1; n[5]: free n[4] => _7 @ bb2[15]: fn test_ptr_int_ptr; _7 = free(move _8); } @@ -786,7 +786,7 @@ nodes_that_need_write = [] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value; _1 = malloc(move _2); - n[1]: value.load _ => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); + n[1]: value.load n[0] => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); n[2]: free n[1] => _5 @ bb2[9]: fn test_load_value; _5 = free(move _6); } nodes_that_need_write = [] @@ -800,10 +800,10 @@ nodes_that_need_write = [] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_store_value; _1 = malloc(move _2); - n[1]: value.load _ => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); + n[1]: value.load n[0] => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[1] => _6 @ bb2[10]: fn test_store_value; _6 = _4; n[3]: value.store n[2] => _5.* @ bb2[11]: fn test_store_value; (*_5) = move _6; - n[4]: value.load _ => _8 @ bb2[15]: fn test_store_value; _8 = (*_9); + n[4]: value.load n[0] => _8 @ bb2[15]: fn test_store_value; _8 = (*_9); n[5]: free n[4] => _7 @ bb2[16]: fn test_store_value; _7 = free(move _8); } nodes_that_need_write = [] @@ -822,7 +822,7 @@ g { n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[4]: value.load n[0] => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); n[5]: project[2]@16 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; n[6]: addr.store n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; @@ -847,9 +847,9 @@ nodes_that_need_write = [3, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); - n[1]: value.load _ => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); + n[1]: value.load n[0] => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[2]: value.store n[1] => _4.* @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; - n[3]: value.load _ => _7 @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); + n[3]: value.load n[0] => _7 @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); n[4]: free n[3] => _6 @ bb2[13]: fn test_load_value_store_value; _6 = free(move _7); } nodes_that_need_write = [] diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index 20839642f5..186572a2cc 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -20,13 +20,13 @@ nodes_that_need_write = [] g { n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); - n[2]: int_to_ptr _ => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: value.store _ => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); - n[4]: value.store _ => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[5]: int_to_ptr _ => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[6]: int_to_ptr _ => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[7]: int_to_ptr _ => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[8]: value.store _ => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[4]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); + n[5]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[6]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[7]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[8]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -115,72 +115,72 @@ g { n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[5]: copy _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; + n[5]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; n[6]: copy n[5] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); n[7]: copy n[6] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); n[8]: copy n[7] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); n[9]: copy n[8] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[10]: copy _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; + n[10]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; n[11]: copy n[10] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); n[12]: copy n[11] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); n[13]: copy n[12] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); n[14]: copy n[13] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[15]: copy _ => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; + n[15]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; n[16]: copy n[15] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); n[17]: copy n[16] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); n[18]: copy n[17] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); n[19]: copy n[18] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[20]: copy _ => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; + n[20]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; n[21]: copy n[20] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); n[22]: copy n[21] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); n[23]: copy n[22] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[25]: copy _ => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; + n[25]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; n[26]: copy n[25] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); n[27]: copy n[26] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); n[28]: copy n[27] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); n[29]: copy n[28] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[30]: copy _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; + n[30]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; n[31]: copy n[30] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); n[32]: copy n[31] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); n[33]: copy n[32] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); n[34]: copy n[33] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[35]: copy _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; + n[35]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; n[36]: copy n[35] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); n[37]: copy n[36] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); n[38]: copy n[37] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); n[39]: copy n[38] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[40]: copy _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; + n[40]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; n[41]: copy n[40] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); n[42]: copy n[41] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); n[43]: copy n[42] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[45]: copy _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; + n[45]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; n[46]: copy n[45] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); n[47]: copy n[46] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); n[48]: copy n[47] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); n[49]: copy n[48] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[50]: copy _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; + n[50]: copy n[0] => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; n[51]: copy n[50] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); n[52]: copy n[51] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[53]: copy n[52] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); n[54]: copy n[53] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[55]: copy _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; + n[55]: copy n[0] => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; n[56]: copy n[55] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); n[57]: copy n[56] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); n[58]: copy n[57] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); n[59]: copy n[58] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); - n[60]: copy _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; + n[60]: copy n[0] => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; n[61]: copy n[60] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); n[62]: copy n[61] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); n[63]: copy n[62] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); n[64]: copy n[63] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[65]: copy _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; + n[65]: copy n[0] => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; n[66]: copy n[65] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); n[67]: copy n[66] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); n[68]: copy n[67] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); n[69]: copy n[68] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); - n[70]: copy _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; + n[70]: copy n[0] => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; n[71]: copy n[70] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); n[72]: copy n[71] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); n[73]: copy n[72] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); @@ -334,36 +334,34 @@ nodes_that_need_write = [4, 2, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: value.load _ => _12 @ bb6[6]: fn main_0; _12 = (*_13); + n[2]: value.load n[0] => _12 @ bb6[6]: fn main_0; _12 = (*_13); n[3]: copy n[2] => _11 @ bb6[7]: fn main_0; _11 = move _12 as *mut libc::c_void (Misc); n[4]: free n[3] => _10 @ bb6[9]: fn main_0; _10 = free(move _11); } nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: project[0]@0 n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[13]: addr.load n[12] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[14]: copy _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[15]: addr.store n[14] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: copy n[0] => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; + n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[4]: copy n[0] => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[6]: copy n[0] => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; + n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[8]: copy n[0] => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; + n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[10]: copy n[0] => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; + n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[12]: copy n[0] => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; + n[13]: addr.store n[12] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [15, 14, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [13, 12, 9, 8, 5, 4, 1, 0] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: value.load _ => _11 @ bb3[5]: fn no_owner; _11 = (*_12); + n[2]: value.load n[0] => _11 @ bb3[5]: fn no_owner; _11 = (*_12); n[3]: copy n[2] => _10 @ bb3[6]: fn no_owner; _10 = move _11 as *mut libc::c_void (Misc); n[4]: free n[3] => _9 @ bb3[8]: fn no_owner; _9 = free(move _10); } @@ -378,10 +376,12 @@ g { n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: value.load _ => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[9]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; - n[10]: copy n[9] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); - n[11]: free n[10] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); + n[8]: value.load n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: project[0]@0 n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[10]: addr.load n[9] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[11]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; + n[12]: copy n[11] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); + n[13]: free n[12] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); } nodes_that_need_write = [3, 1, 0] @@ -405,28 +405,28 @@ g { nodes_that_need_write = [3, 2, 1, 0] g { - n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); - n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); - n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; - n[3]: copy n[2] => _7 @ bb2[9]: fn simple1; _7 = move _8 as *mut libc::c_void (Misc); - n[4]: free n[3] => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[5]: copy n[1] => _16 @ bb4[21]: fn simple1; _16 = _1; - n[6]: ptr_to_int n[5] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); + n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); + n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); + n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; + n[3]: copy n[2] => _7 @ bb2[9]: fn simple1; _7 = move _8 as *mut libc::c_void (Misc); + n[4]: free n[3] => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); } nodes_that_need_write = [] g { - n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); - n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; - n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; - n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; - n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: int_to_ptr _ => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); - n[8]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; - n[9]: copy n[8] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); - n[10]: free n[9] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); + n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); + n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; + n[3]: project[0]@0 n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; + n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; + n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; + n[7]: copy n[3] => _16 @ bb4[21]: fn simple1; _16 = _1; + n[8]: ptr_to_int n[7] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); + n[9]: int_to_ptr n[3] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[10]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; + n[11]: copy n[10] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); + n[12]: free n[11] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); } nodes_that_need_write = [4, 2, 1, 0] @@ -442,15 +442,15 @@ g { n[1]: copy n[0] => _1 @ bb2[1]: fn lighttpd_test; _1 = move _2 as *mut *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn lighttpd_test; _9 = _1; n[3]: value.store n[2] => _5.*.0 @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; - n[4]: value.load _ => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[4]: value.load n[0] => _8 @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[5]: offset[0] n[4] => _7 @ bb0[8]: fn fdevent_register; _7 = offset(move _8, move _9); n[6]: copy n[5] => _6 @ bb1[3]: fn fdevent_register; _6 = &mut (*_7); n[7]: addr.store n[6] => _ @ bb2[0]: fn fdevent_register; (*_6) = move _11; n[8]: addr.load n[6] => _ @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[9]: value.load _ => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load n[5] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[10]: offset[0] n[9] => _4 @ bb0[9]: fn fdevent_unregister; _4 = offset(move _5, move _6); n[11]: addr.load n[10] => _ @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[12]: value.load _ => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[12]: value.load n[10] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); n[13]: offset[0] n[12] => _18 @ bb7[10]: fn fdevent_unregister; _18 = offset(move _19, move _20); n[14]: copy n[13] => _17 @ bb8[3]: fn fdevent_unregister; _17 = &mut (*_18); n[15]: addr.store n[14] => _ @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); @@ -458,7 +458,7 @@ g { n[17]: copy n[16] => _19 @ bb6[7]: fn lighttpd_test; _19 = move _20 as *mut libc::c_void (Misc); n[18]: free n[17] => _18 @ bb6[9]: fn lighttpd_test; _18 = free(move _19); } -nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4] +nodes_that_need_write = [15, 14, 13, 12, 10, 9, 7, 6, 5, 4, 0] g { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); @@ -466,15 +466,15 @@ g { n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load _ => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[5]: value.load n[2] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load _ => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[9]: value.load n[7] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load _ => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[13]: value.load n[7] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); @@ -516,7 +516,7 @@ g { n[9]: copy n[8] => _15 @ bb2[15]: fn fdevent_register; _15 = _4; n[10]: value.store n[9] => _12.*.1 @ bb2[16]: fn fdevent_register; ((*_12).1: *mut libc::c_void) = move _15; n[11]: project[1]@8 n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[12]: addr.store n[1] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; + n[12]: addr.store n[8] => _ @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; n[13]: copy n[8] => _0 @ bb3[6]: fn connection_accepted; _0 = _4; n[14]: copy n[13] => _13 @ bb4[19]: fn lighttpd_test; _13 = connection_accepted(move _14, const 0_i32); n[15]: copy n[14] => _17 @ bb5[6]: fn lighttpd_test; _17 = _13; @@ -529,7 +529,7 @@ g { n[22]: copy n[21] => _10 @ bb2[7]: fn connection_close; _10 = move _11 as *mut libc::c_void (Misc); n[23]: free n[22] => _9 @ bb2[9]: fn connection_close; _9 = free(move _10); } -nodes_that_need_write = [12, 3, 1, 0] +nodes_that_need_write = [12, 8, 7, 6, 3, 1, 0] g { n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); @@ -539,7 +539,7 @@ g { n[4]: copy n[1] => _0 @ bb9[2]: fn fdnode_init; _0 = _2; n[5]: copy n[4] => _11 @ bb1[5]: fn fdevent_register; _11 = fdnode_init(); n[6]: value.store n[5] => _6.* @ bb2[0]: fn fdevent_register; (*_6) = move _11; - n[7]: value.load _ => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); + n[7]: value.load n[0] => _12 @ bb2[3]: fn fdevent_register; _12 = (*_6); n[8]: project[0]@0 n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; n[9]: addr.store n[7] => _ @ bb2[8]: fn fdevent_register; ((*_12).0: std::option::Option u32>) = move _13; n[10]: project[2]@16 n[7] => _ @ bb2[12]: fn fdevent_register; ((*_12).2: i32) = move _14; @@ -553,7 +553,7 @@ g { n[18]: copy n[7] => _0 @ bb2[26]: fn fdevent_register; _0 = _12; n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load _ => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[21]: value.load n[8] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); @@ -561,7 +561,7 @@ g { n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); n[27]: project[4]@24 n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); n[28]: addr.load n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); - n[29]: value.load _ => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[29]: value.load n[8] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; @@ -570,7 +570,7 @@ g { n[35]: copy n[34] => _3 @ bb0[4]: fn fdnode_free; _3 = move _4 as *mut libc::c_void (Misc); n[36]: free n[35] => _2 @ bb0[6]: fn fdnode_free; _2 = free(move _3); } -nodes_that_need_write = [17, 15, 13, 11, 9, 7] +nodes_that_need_write = [17, 15, 13, 11, 9, 7, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); @@ -778,7 +778,7 @@ g { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_ptr_int_ptr; _5 = _1; n[2]: ptr_to_int n[1] => _ @ bb2[5]: fn test_ptr_int_ptr; _4 = move _5 as usize (PointerExposeAddress); - n[3]: int_to_ptr _ => _1 @ bb2[10]: fn test_ptr_int_ptr; _1 = move _6 as *mut libc::c_void (PointerFromExposedAddress); + n[3]: int_to_ptr n[0] => _1 @ bb2[10]: fn test_ptr_int_ptr; _1 = move _6 as *mut libc::c_void (PointerFromExposedAddress); n[4]: copy n[3] => _8 @ bb2[14]: fn test_ptr_int_ptr; _8 = _1; n[5]: free n[4] => _7 @ bb2[15]: fn test_ptr_int_ptr; _7 = free(move _8); } @@ -786,7 +786,7 @@ nodes_that_need_write = [] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value; _1 = malloc(move _2); - n[1]: value.load _ => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); + n[1]: value.load n[0] => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); n[2]: free n[1] => _5 @ bb2[9]: fn test_load_value; _5 = free(move _6); } nodes_that_need_write = [] @@ -800,10 +800,10 @@ nodes_that_need_write = [] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_store_value; _1 = malloc(move _2); - n[1]: value.load _ => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); + n[1]: value.load n[0] => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[1] => _6 @ bb2[10]: fn test_store_value; _6 = _4; n[3]: value.store n[2] => _5.* @ bb2[11]: fn test_store_value; (*_5) = move _6; - n[4]: value.load _ => _8 @ bb2[15]: fn test_store_value; _8 = (*_9); + n[4]: value.load n[0] => _8 @ bb2[15]: fn test_store_value; _8 = (*_9); n[5]: free n[4] => _7 @ bb2[16]: fn test_store_value; _7 = free(move _8); } nodes_that_need_write = [] @@ -822,7 +822,7 @@ g { n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; n[3]: value.store n[2] => _5.*.2 @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); - n[4]: value.load _ => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); + n[4]: value.load n[0] => _10 @ bb4[9]: fn test_store_value_field; _10 = ((*_5).2: *const pointers::S); n[5]: project[2]@16 n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; n[6]: addr.store n[1] => _ @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; n[7]: value.store n[4] => _1.*.2 @ bb4[10]: fn test_store_value_field; ((*_1).2: *const pointers::S) = move _10; @@ -847,9 +847,9 @@ nodes_that_need_write = [3, 1, 0] g { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); - n[1]: value.load _ => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); + n[1]: value.load n[0] => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[2]: value.store n[1] => _4.* @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; - n[3]: value.load _ => _7 @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); + n[3]: value.load n[0] => _7 @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); n[4]: free n[3] => _6 @ bb2[13]: fn test_load_value_store_value; _6 = free(move _7); } nodes_that_need_write = [] From 886aa3ae7f63cd6f1f4629f6417014005fe67f63 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Sun, 18 Aug 2024 17:04:41 -0700 Subject: [PATCH 04/17] Remove unused CopyRef NodeKind --- analysis/runtime/src/events.rs | 3 --- pdg/src/builder.rs | 8 +------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/analysis/runtime/src/events.rs b/analysis/runtime/src/events.rs index a468196e72..8e6091a2da 100644 --- a/analysis/runtime/src/events.rs +++ b/analysis/runtime/src/events.rs @@ -28,8 +28,6 @@ pub enum EventKind { /// the pointer. CopyPtr(Pointer), - CopyRef, - /// Projection. Used for operations like `_2 = &(*_1).0`. /// The third value is a "projection key" that points to an element /// of the projections data structure in the metadata. It is used to @@ -110,7 +108,6 @@ impl Debug for EventKind { LoadAddr(ptr) => write!(f, "load(0x{:x})", ptr), StoreAddr(ptr) => write!(f, "store(0x{:x})", ptr), StoreAddrTaken(ptr) => write!(f, "store(0x{:x})", ptr), - CopyRef => write!(f, "copy_ref"), AddrOfLocal(ptr, _) => write!(f, "addr_of_local = 0x{:x}", ptr), ToInt(ptr) => write!(f, "to_int(0x{:x})", ptr), FromInt(ptr) => write!(f, "from_int(0x{:x})", ptr), diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index 63baafc81a..afe90df3e0 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -57,7 +57,6 @@ impl EventKindExt for EventKind { StoreAddrTaken(ptr) => ptr, LoadValue(ptr) => ptr, StoreValue(ptr) => ptr, - CopyRef => return None, // FIXME ToInt(ptr) => ptr, Realloc { old_ptr, .. } => old_ptr, FromInt(lhs) => lhs, @@ -79,7 +78,7 @@ impl EventKindExt for EventKind { Alloc { .. } => NodeKind::Alloc(1), Realloc { .. } => NodeKind::Alloc(1), Free { .. } => NodeKind::Free, - CopyPtr(..) | CopyRef => NodeKind::Copy, + CopyPtr(..) => NodeKind::Copy, Project(base_ptr, new_ptr, key) => { let proj = metadata .projections @@ -121,7 +120,6 @@ impl EventKindExt for EventKind { fn update_provenance( provenances: &mut HashMap, event_kind: &EventKind, - metadata: &EventMetadata, mapping: (GraphId, NodeId), ) { use EventKind::*; @@ -141,9 +139,6 @@ fn update_provenance( Offset(_, _, new_ptr) | Project(_, new_ptr, _) => { provenances.insert(new_ptr, mapping); } - CopyRef => { - provenances.insert(metadata.destination.clone().unwrap().local.into(), mapping); - } AddrOfLocal(ptr, _) => { provenances.insert(ptr, mapping); } @@ -233,7 +228,6 @@ pub fn add_node( update_provenance( provenances, &event.kind, - event_metadata, (graph_id, node_id), ); From c508513f0aba4b52bd07e30e68905bcb49938d2a Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 14 Jun 2024 00:04:00 -0700 Subject: [PATCH 05/17] Pointer provenance improvements Track the provenance of pointers with finer granularity by storing the size of every allocation, local, and constant inside the corresponding events. With this information, we can keep track of the boundaries of every object and track whether a projected pointer falls inside the original allocation. --- pdg/src/builder.rs | 152 ++++++++++++++---- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 38 +++-- ...lysis_tests_misc_pdg_snapshot_release.snap | 48 +++--- 3 files changed, 172 insertions(+), 66 deletions(-) diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index afe90df3e0..22d4976c10 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -6,7 +6,7 @@ use color_eyre::eyre; use fs_err::File; use indexmap::IndexSet; use itertools::Itertools; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::io::{self, BufReader}; use std::iter; use std::path::Path; @@ -23,7 +23,7 @@ pub fn read_metadata(path: &Path) -> eyre::Result { Ok(Metadata::read(&bytes)?) } -fn parent(e: &NodeKind, obj: (GraphId, NodeId)) -> Option<(GraphId, NodeId)> { +fn parent<'a, 'b>(e: &'a NodeKind, obj: &'b ProvenanceInfo) -> Option<&'b ProvenanceInfo> { use NodeKind::*; match e { Alloc(..) | AddrOfLocal(..) => None, @@ -117,29 +117,103 @@ impl EventKindExt for EventKind { } } +#[derive(Debug, Clone)] +pub struct ProvenanceInfo { + /// Size of this allocation or local object. + size: Option, + + /// Graph containing all the nodes for this object. + gid: GraphId, + + /// One node that created this object. + nid: NodeId, +} + +impl ProvenanceInfo { + fn new(gid: GraphId, nid: NodeId) -> Self { + Self { + size: None, + gid, + nid, + } + } + + /// Return a copy of the current object with a different node. + fn with_node(&self, nid: NodeId) -> Self { + Self { + nid, + ..self.clone() + } + } +} + fn update_provenance( - provenances: &mut HashMap, + provenances: &mut BTreeMap, event_kind: &EventKind, - mapping: (GraphId, NodeId), + mut mapping: ProvenanceInfo, ) { use EventKind::*; match *event_kind { - Alloc { ptr, .. } => { + Alloc { ptr, size, .. } => { + // TODO: check for overlap with existing allocations + mapping.size = Some(size); provenances.insert(ptr, mapping); } - CopyPtr(ptr) => { - // only insert if not already there - if let Err(..) = provenances.try_insert(ptr, mapping) { - log::warn!("0x{:x} already has a source", ptr); - } - } - Realloc { new_ptr, .. } => { + Realloc { new_ptr, size, .. } => { + mapping.size = Some(size); provenances.insert(new_ptr, mapping); } - Offset(_, _, new_ptr) | Project(_, new_ptr, _) => { - provenances.insert(new_ptr, mapping); + Free { ptr } if ptr != 0 => { + // TODO: handle the case where `ptr` falls inside an allocation + let old_prov = provenances.remove(&ptr); + if old_prov.is_none() { + log::warn!("Tried to free invalid pointer 0x{:x}", ptr); + } + } + CopyPtr(ptr) | Offset(_, _, ptr) | Project(_, ptr, _) => { + // Check that the pointer falls inside an existing allocation + let need_insert = provenances + .range(0..=ptr) + .next_back() + .map(|(start, pi)| { + // If the existing pointer has a size, check it + // Otherwise, insert ours if it's different + let size = match pi.size { + Some(size) => size, + None => return ptr != *start, + }; + + let end = start.saturating_add(size); + if (*start..=end).contains(&ptr) { + return false; + } + + if matches!(*event_kind, CopyPtr(_)) { + // A new pointer that we don't know where it came from + // Insert it for now, we should decide later what to do + // + // Assume an unknown pointer points to a word-sized object + log::warn!("Pointer of unknown origin 0x{:x}", ptr); + return true; + } + + log::warn!( + "0x{:x} outside of object bounds 0x{:x}-0x{:x}", + ptr, + start, + end + ); + + false + }) + .unwrap_or(true); + + if need_insert { + provenances.insert(ptr, mapping); + } } AddrOfLocal(ptr, _) => { + // TODO: is this a local from another function? provenances.insert(ptr, mapping); } _ => {} @@ -148,7 +222,7 @@ fn update_provenance( pub fn add_node( graphs: &mut Graphs, - provenances: &mut HashMap, + provenances: &mut BTreeMap, address_taken: &mut AddressTaken, event: &Event, metadata: &Metadata, @@ -174,12 +248,34 @@ pub fn add_node( statement_idx = 0; } - let provenance = event - .kind - .ptr(event_metadata) - .and_then(|ptr| provenances.get(&ptr).cloned()); - let direct_source = provenance.and_then(|(gid, _last_nid_ref)| { - graphs.graphs[gid] + let ptr = event.kind.ptr(event_metadata); + let provenance = ptr.and_then(|ptr| { + provenances + .range(0..=ptr) + .next_back() + .and_then(|(start, pi)| { + let size = match pi.size { + Some(size) => size, + None if ptr == *start => return Some(pi), + None => return None, + }; + + // If the current pointer falls outside the + // original object, make a new graph for it + let end = start.saturating_add(size); + + // This is intentionally greater-than because + // one past the end is still a valid pointer + if ptr > end { + None + } else { + Some(pi) + } + }) + }); + + let direct_source = provenance.and_then(|pi| { + graphs.graphs[pi.gid] .nodes .iter() .rposition(|n| { @@ -197,9 +293,9 @@ pub fn add_node( false } }) - .map(|nid| (gid, NodeId::from(nid))) + .map(|nid| pi.with_node(NodeId::from(nid))) }); - let source = direct_source.or(provenance); + let source = direct_source.or(provenance.cloned()); let function = Func { id: dest_fn, @@ -212,23 +308,25 @@ pub fn add_node( statement_idx, kind: node_kind.clone(), source: source + .as_ref() .and_then(|p| parent(&node_kind, p)) - .map(|(_, nid)| nid), + .map(|pi| pi.nid), dest: event_metadata.destination.clone(), debug_info: event_metadata.debug_info.clone(), info: None, }; let graph_id = source + .as_ref() .and_then(|p| parent(&node_kind, p)) - .map(|(gid, _)| gid) + .map(|pi| pi.gid) .unwrap_or_else(|| graphs.graphs.push(Graph::new())); let node_id = graphs.graphs[graph_id].nodes.push(node); update_provenance( provenances, &event.kind, - (graph_id, node_id), + ProvenanceInfo::new(graph_id, node_id), ); Some(node_id) @@ -236,7 +334,7 @@ pub fn add_node( pub fn construct_pdg(events: &[Event], metadata: &Metadata) -> Graphs { let mut graphs = Graphs::new(); - let mut provenances = HashMap::new(); + let mut provenances = BTreeMap::new(); let mut address_taken = AddressTaken::new(); for event in events { add_node( diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index f49ad7f3be..7fcd2dd20a 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -90,12 +90,16 @@ g { n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); - n[34]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; - n[35]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; - n[36]: copy n[30] => _14 @ bb9[4]: fn recur; _14 = _2; } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] +g { + n[0]: copy _ => _14 @ bb9[4]: fn recur; _14 = _2; + n[1]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; + n[2]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); @@ -376,9 +380,9 @@ g { n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: value.load n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[9]: project[0]@0 n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[10]: addr.load n[9] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[8]: value.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: project[0]@0 n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[10]: addr.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); n[11]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; n[12]: copy n[11] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); n[13]: free n[12] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); @@ -421,9 +425,9 @@ g { n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: copy n[3] => _16 @ bb4[21]: fn simple1; _16 = _1; + n[7]: copy n[0] => _16 @ bb4[21]: fn simple1; _16 = _1; n[8]: ptr_to_int n[7] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); - n[9]: int_to_ptr n[3] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[9]: int_to_ptr n[0] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); n[10]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; n[11]: copy n[10] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); n[12]: free n[11] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); @@ -447,10 +451,10 @@ g { n[6]: copy n[5] => _6 @ bb1[3]: fn fdevent_register; _6 = &mut (*_7); n[7]: addr.store n[6] => _ @ bb2[0]: fn fdevent_register; (*_6) = move _11; n[8]: addr.load n[6] => _ @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[9]: value.load n[5] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load n[0] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[10]: offset[0] n[9] => _4 @ bb0[9]: fn fdevent_unregister; _4 = offset(move _5, move _6); n[11]: addr.load n[10] => _ @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[12]: value.load n[10] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[12]: value.load n[0] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); n[13]: offset[0] n[12] => _18 @ bb7[10]: fn fdevent_unregister; _18 = offset(move _19, move _20); n[14]: copy n[13] => _17 @ bb8[3]: fn fdevent_unregister; _17 = &mut (*_18); n[15]: addr.store n[14] => _ @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); @@ -458,7 +462,7 @@ g { n[17]: copy n[16] => _19 @ bb6[7]: fn lighttpd_test; _19 = move _20 as *mut libc::c_void (Misc); n[18]: free n[17] => _18 @ bb6[9]: fn lighttpd_test; _18 = free(move _19); } -nodes_that_need_write = [15, 14, 13, 12, 10, 9, 7, 6, 5, 4, 0] +nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4, 0] g { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); @@ -466,15 +470,15 @@ g { n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load n[2] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[5]: value.load n[0] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load n[7] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[9]: value.load n[0] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load n[7] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[13]: value.load n[0] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); @@ -553,7 +557,7 @@ g { n[18]: copy n[7] => _0 @ bb3[2]: fn fdevent_register; _0 = _12; n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load n[8] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[21]: value.load n[0] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); @@ -561,7 +565,7 @@ g { n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); n[27]: project[4]@24 n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); n[28]: addr.load n[26] => _ @ bb1[3]: fn fdevent_fdnode_event_unsetter; _8 = ((*_2).4: i32); - n[29]: value.load n[8] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[29]: value.load n[0] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; @@ -1022,6 +1026,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 66 +num_graphs = 67 num_nodes = 755 diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index 186572a2cc..d0e7315fbd 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -90,12 +90,16 @@ g { n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); - n[34]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; - n[35]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; - n[36]: copy n[30] => _13 @ bb8[4]: fn recur; _13 = _2; } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] +g { + n[0]: copy _ => _13 @ bb8[4]: fn recur; _13 = _2; + n[1]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; + n[2]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); @@ -376,9 +380,9 @@ g { n[5]: value.store n[4] => _6.* @ bb2[10]: fn invalid; (*_6) = move _5; n[6]: project[0]@0 n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); n[7]: addr.load n[1] => _ @ bb2[25]: fn invalid; _12 = ((*_1).0: i32); - n[8]: value.load n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[9]: project[0]@0 n[6] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[10]: addr.load n[9] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[8]: value.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[9]: project[0]@0 n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[10]: addr.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); n[11]: copy n[1] => _23 @ bb4[12]: fn invalid; _23 = _1; n[12]: copy n[11] => _22 @ bb4[13]: fn invalid; _22 = move _23 as *mut libc::c_void (Misc); n[13]: free n[12] => _21 @ bb4[15]: fn invalid; _21 = free(move _22); @@ -421,9 +425,9 @@ g { n[4]: addr.store n[2] => _ @ bb4[8]: fn simple1; ((*_11).0: i32) = const 10_i32; n[5]: copy n[1] => _12 @ bb4[10]: fn simple1; _12 = _5; n[6]: copy n[2] => _13 @ bb4[13]: fn simple1; _13 = _11; - n[7]: copy n[3] => _16 @ bb4[21]: fn simple1; _16 = _1; + n[7]: copy n[0] => _16 @ bb4[21]: fn simple1; _16 = _1; n[8]: ptr_to_int n[7] => _ @ bb4[22]: fn simple1; _15 = move _16 as usize (PointerExposeAddress); - n[9]: int_to_ptr n[3] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); + n[9]: int_to_ptr n[0] => _17 @ bb4[28]: fn simple1; _17 = move _18 as *const libc::c_void (PointerFromExposedAddress); n[10]: copy n[1] => _21 @ bb4[34]: fn simple1; _21 = _5; n[11]: copy n[10] => _20 @ bb4[35]: fn simple1; _20 = move _21 as *mut libc::c_void (Misc); n[12]: free n[11] => _19 @ bb4[37]: fn simple1; _19 = free(move _20); @@ -447,10 +451,10 @@ g { n[6]: copy n[5] => _6 @ bb1[3]: fn fdevent_register; _6 = &mut (*_7); n[7]: addr.store n[6] => _ @ bb2[0]: fn fdevent_register; (*_6) = move _11; n[8]: addr.load n[6] => _ @ bb2[3]: fn fdevent_register; _12 = (*_6); - n[9]: value.load n[5] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[9]: value.load n[0] => _5 @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[10]: offset[0] n[9] => _4 @ bb0[9]: fn fdevent_unregister; _4 = offset(move _5, move _6); n[11]: addr.load n[10] => _ @ bb1[2]: fn fdevent_unregister; _3 = (*_4); - n[12]: value.load n[10] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); + n[12]: value.load n[0] => _19 @ bb7[4]: fn fdevent_unregister; _19 = ((*_1).0: *mut *mut pointers::fdnode_st); n[13]: offset[0] n[12] => _18 @ bb7[10]: fn fdevent_unregister; _18 = offset(move _19, move _20); n[14]: copy n[13] => _17 @ bb8[3]: fn fdevent_unregister; _17 = &mut (*_18); n[15]: addr.store n[14] => _ @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); @@ -458,7 +462,7 @@ g { n[17]: copy n[16] => _19 @ bb6[7]: fn lighttpd_test; _19 = move _20 as *mut libc::c_void (Misc); n[18]: free n[17] => _18 @ bb6[9]: fn lighttpd_test; _18 = free(move _19); } -nodes_that_need_write = [15, 14, 13, 12, 10, 9, 7, 6, 5, 4, 0] +nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4, 0] g { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); @@ -466,15 +470,15 @@ g { n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[3]: addr.store n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; n[4]: copy n[1] => _12 @ bb4[10]: fn lighttpd_test; _12 = _5; - n[5]: value.load n[2] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); + n[5]: value.load n[0] => _10 @ bb2[10]: fn connection_accepted; _10 = ((*_1).0: *mut pointers::fdevents); n[6]: copy n[5] => _1 @ bb0[0]: fn fdevent_register; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[7]: project[0]@0 n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); n[8]: addr.load n[6] => _ @ bb0[2]: fn fdevent_register; _8 = ((*_1).0: *mut *mut pointers::fdnode_st); - n[9]: value.load n[7] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); + n[9]: value.load n[0] => _4 @ bb0[2]: fn connection_close; _4 = ((*_1).0: *mut pointers::fdevents); n[10]: copy n[9] => _1 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[11]: copy n[10] => _7 @ bb2[2]: fn fdevent_fdnode_event_del; _7 = _1; n[12]: copy n[11] => _1 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); - n[13]: value.load n[7] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); + n[13]: value.load n[0] => _7 @ bb1[5]: fn connection_close; _7 = ((*_1).0: *mut pointers::fdevents); n[14]: copy n[13] => _1 @ bb0[0]: fn fdevent_unregister; _6 = fdevent_unregister(move _7, move _8); n[15]: project[0]@0 n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); n[16]: addr.load n[14] => _ @ bb0[3]: fn fdevent_unregister; _5 = ((*_1).0: *mut *mut pointers::fdnode_st); @@ -553,7 +557,7 @@ g { n[18]: copy n[7] => _0 @ bb2[26]: fn fdevent_register; _0 = _12; n[19]: copy n[18] => _9 @ bb2[23]: fn connection_accepted; _9 = fdevent_register(move _10, move _11, move _12, move _14); n[20]: value.store n[19] => _4.*.1 @ bb3[4]: fn connection_accepted; ((*_4).1: *mut pointers::fdnode_st) = move _9; - n[21]: value.load n[8] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); + n[21]: value.load n[0] => _5 @ bb0[4]: fn connection_close; _5 = ((*_2).1: *mut pointers::fdnode_st); n[22]: copy n[21] => _2 @ bb0[0]: fn fdevent_fdnode_event_del; _3 = fdevent_fdnode_event_del(move _4, move _5); n[23]: copy n[22] => _5 @ bb0[3]: fn fdevent_fdnode_event_del; _5 = _2; n[24]: copy n[23] => _1 @ bb0[0]: fn is_null; _4 = is_null(move _5); @@ -561,7 +565,7 @@ g { n[26]: copy n[25] => _2 @ bb0[0]: fn fdevent_fdnode_event_unsetter; _6 = fdevent_fdnode_event_unsetter(move _7, move _8); n[27]: project[4]@24 n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); n[28]: addr.load n[26] => _ @ bb0[8]: fn fdevent_fdnode_event_unsetter; _7 = ((*_2).4: i32); - n[29]: value.load n[8] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); + n[29]: value.load n[0] => _3 @ bb1[2]: fn fdevent_unregister; _3 = (*_4); n[30]: copy n[29] => _12 @ bb1[11]: fn fdevent_unregister; _12 = _3; n[31]: ptr_to_int n[30] => _ @ bb1[12]: fn fdevent_unregister; _11 = move _12 as usize (PointerExposeAddress); n[32]: copy n[29] => _23 @ bb8[7]: fn fdevent_unregister; _23 = _3; @@ -860,8 +864,10 @@ g { n[2]: addr.load n[1] => _ @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[3]: addr.store n[1] => _ @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; n[4]: addr.load n[1] => _ @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); + n[5]: addr.load n[0] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); + n[6]: addr.store n[0] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [3, 1, 0] +nodes_that_need_write = [6, 3, 1, 0] g { n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _59 = &raw mut _40; @@ -950,11 +956,9 @@ g { n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: addr.load n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[5]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[6]: addr.store n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[4]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [6, 2, 1, 0] +nodes_that_need_write = [1, 0] g { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _8 = &raw mut _1; @@ -1022,6 +1026,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 66 +num_graphs = 67 num_nodes = 755 From cc1d67620e8f312157ed7d8d1a473e876dab8980 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 14 Jun 2024 19:38:44 -0700 Subject: [PATCH 06/17] Add size of locals to AddrOfLocal events Keep track of the size of every local for the new provenance algorithm. --- analysis/runtime/src/events.rs | 13 +++- analysis/runtime/src/handlers.rs | 8 ++- dynamic_instrumentation/src/instrument.rs | 67 +++++++++++-------- pdg/src/builder.rs | 7 +- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 18 +++-- 5 files changed, 72 insertions(+), 41 deletions(-) diff --git a/analysis/runtime/src/events.rs b/analysis/runtime/src/events.rs index 8e6091a2da..be86d4ee3a 100644 --- a/analysis/runtime/src/events.rs +++ b/analysis/runtime/src/events.rs @@ -61,8 +61,13 @@ pub enum EventKind { /// are necessary for its underlying address. StoreAddrTaken(Pointer), - /// The pointer that appears as the address result of addr_of(Local) - AddrOfLocal(Pointer, Local), + /// The pointer that appears as the address result of addr_of(Local). + /// The fields encode the pointer of the local, its MIR index, and its size. + AddrOfLocal { + ptr: Pointer, + local: Local, + size: u32, + }, /// Casting the pointer to an int ToInt(Pointer), @@ -108,7 +113,9 @@ impl Debug for EventKind { LoadAddr(ptr) => write!(f, "load(0x{:x})", ptr), StoreAddr(ptr) => write!(f, "store(0x{:x})", ptr), StoreAddrTaken(ptr) => write!(f, "store(0x{:x})", ptr), - AddrOfLocal(ptr, _) => write!(f, "addr_of_local = 0x{:x}", ptr), + AddrOfLocal { ptr, local, size } => { + write!(f, "addr_of_local({:?}, {}) = 0x{:x}", local, size, ptr) + } ToInt(ptr) => write!(f, "to_int(0x{:x})", ptr), FromInt(ptr) => write!(f, "from_int(0x{:x})", ptr), LoadValue(ptr) => write!(f, "load_value(0x{:x})", ptr), diff --git a/analysis/runtime/src/handlers.rs b/analysis/runtime/src/handlers.rs index 2724ca5585..898424767f 100644 --- a/analysis/runtime/src/handlers.rs +++ b/analysis/runtime/src/handlers.rs @@ -138,10 +138,14 @@ pub fn ptr_to_int(mir_loc: MirLocId, ptr: usize) { }); } -pub fn addr_of_local(mir_loc: MirLocId, ptr: usize, local: u32) { +pub fn addr_of_local(mir_loc: MirLocId, ptr: usize, local: u32, size: u32) { RUNTIME.send_event(Event { mir_loc, - kind: EventKind::AddrOfLocal(ptr, local.into()), + kind: EventKind::AddrOfLocal { + ptr, + local: local.into(), + size, + }, }); } diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index 57d01601cb..b236affcf2 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -13,8 +13,8 @@ use rustc_middle::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc_middle::mir::{ - BasicBlock, BasicBlockData, Body, BorrowKind, ClearCrossCrate, HasLocalDecls, Local, LocalDecl, - Location, Operand, Place, PlaceElem, ProjectionElem, Rvalue, Safety, SourceInfo, SourceScope, + BasicBlock, BasicBlockData, Body, ClearCrossCrate, HasLocalDecls, Local, LocalDecl, Location, + Operand, Place, PlaceElem, ProjectionElem, Rvalue, Safety, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -562,6 +562,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { let ptr_contrive_fn = self.hooks().find("ptr_contrive"); let ptr_to_int_fn = self.hooks().find("ptr_to_int"); let load_value_fn = self.hooks().find("load_value"); + let project_fn = self.hooks().find("ptr_project"); let store_value_fn = self.hooks().find("store_value"); let store_addr_taken_fn = self.hooks().find("ptr_store_addr_taken"); @@ -575,6 +576,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { let op_ty = |op: &Operand<'tcx>| op.ty(&locals, ctx); let place_ty = |p: &Place<'tcx>| p.ty(&locals, ctx).ty; + let local_ty = |p: &Place| place_ty(&p.local.into()); let value_ty = value.ty(self, self.tcx()); self.visit_place( @@ -631,16 +633,6 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { } } _ if !is_region_or_unsafe_ptr(value_ty) => {} - Rvalue::AddressOf(_, p) if !p.is_indirect() => { - // Instrument which local's address is taken - self.loc(location, location.successor_within_block(), addr_local_fn) - .arg_var(dest) - .arg_index_of(p.local) - .source(p) - .dest(&dest) - .instrumentation_priority(InstrumentationPriority::Early) - .add_to(self); - } Rvalue::Use(Operand::Copy(p) | Operand::Move(p)) if p.is_indirect() => { // We're dereferencing something, the result of which is a reference or pointer self.loc(location, location.successor_within_block(), load_value_fn) @@ -677,27 +669,46 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { .dest(&dest) .add_to(self); } - Rvalue::Ref(_, bkind, p) if !p.is_indirect() => { + Rvalue::AddressOf(_, p) | Rvalue::Ref(_, _, p) if !p.is_indirect() => { let source = remove_outer_deref(*p, self.tcx()); - if let BorrowKind::Mut { .. } = bkind { - // Instrument which local's address is taken - self.loc(location, location, addr_local_fn) + let layout = ctx + .layout_of(ty::ParamEnv::reveal_all().and(local_ty(p))) + .expect("Failed to compute layout of local"); + let size = + u32::try_from(layout.size.bytes()).expect("Failed to convert local size"); + + let mut b = self + .loc(location, location, addr_local_fn) + .arg_addr_of(p.local) + .arg_index_of(p.local) + .arg_var(size) + .source(&source) + .instrumentation_priority(InstrumentationPriority::Early); + if p.projection.is_empty() { + // No projections, store directly to the destination + b = b.dest(&dest); + } + b.add_to(self); + + if !p.projection.is_empty() { + let fields = p + .projection + .iter() + .filter_map(|elem| match elem { + PlaceElem::Field(idx, _) => Some(idx.index()), + _ => None, + }) + .collect::>(); + let proj_idx = self.projections.add_proj(fields); + + self.loc(location, location, project_fn) + .arg_addr_of(p.local) .arg_addr_of(*p) - .arg_index_of(p.local) - .source(&source) - .dest(&dest) - .instrumentation_priority(InstrumentationPriority::Early) - .add_to(self); - } else { - // Instrument immutable borrows by tracing the reference itself - self.loc(location, location.successor_within_block(), addr_local_fn) - .arg_var(dest) - .arg_index_of(p.local) - .source(&source) + .arg_var(proj_idx) .dest(&dest) .instrumentation_priority(InstrumentationPriority::Early) .add_to(self); - }; + } } _ => (), } diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index 22d4976c10..69895a347f 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -61,7 +61,7 @@ impl EventKindExt for EventKind { Realloc { old_ptr, .. } => old_ptr, FromInt(lhs) => lhs, Alloc { ptr, .. } => ptr, - AddrOfLocal(lhs, _) => lhs, + AddrOfLocal { ptr, .. } => ptr, Offset(ptr, _, _) => ptr, Done | BeginFuncBody => return None, }) @@ -91,7 +91,7 @@ impl EventKindExt for EventKind { StoreAddrTaken(..) => NodeKind::StoreAddr, LoadValue(..) => NodeKind::LoadValue, StoreValue(..) => NodeKind::StoreValue, - AddrOfLocal(_, local) => { + AddrOfLocal { local, .. } => { // All but the first instance of AddrOfLocal in a given // function body are considered copies of that local's address let (_, inserted) = address_taken.insert_full((func, local)); @@ -212,8 +212,9 @@ fn update_provenance( provenances.insert(ptr, mapping); } } - AddrOfLocal(ptr, _) => { + AddrOfLocal { ptr, size, .. } => { // TODO: is this a local from another function? + mapping.size = size.try_into().ok(); provenances.insert(ptr, mapping); } _ => {} diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index 7fcd2dd20a..625a99146c 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -954,11 +954,19 @@ g { n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: addr.load n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[5]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; - n[6]: addr.store n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; + n[4]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [6, 2, 1, 0] +nodes_that_need_write = [1, 0] + +g { + n[0]: addr.load _ => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); +} +nodes_that_need_write = [] + +g { + n[0]: addr.store _ => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; +} +nodes_that_need_write = [0] g { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _10 = &raw mut _1; @@ -1026,6 +1034,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 67 +num_graphs = 69 num_nodes = 755 From 07ee28918557e317dfa5c34bf00e7f431ac255c8 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 26 Jul 2024 21:37:31 -0700 Subject: [PATCH 07/17] Support passing pointers to event handlers Add a new arg_ptr() method that allows passing a pointer directly to an event handler. The handler needs to be generic on the pointee type: fn foo_handler(ptr: *const T) { ... } This change allows us to get more information about the pointees from the event handler body, e.g., call std::mem::size_of_val(). --- dynamic_instrumentation/src/arg.rs | 3 +- dynamic_instrumentation/src/instrument.rs | 6 ++- dynamic_instrumentation/src/point/apply.rs | 7 ++- dynamic_instrumentation/src/point/build.rs | 7 +++ dynamic_instrumentation/src/point/cast.rs | 53 ++++++++++++++++++++-- 5 files changed, 69 insertions(+), 7 deletions(-) diff --git a/dynamic_instrumentation/src/arg.rs b/dynamic_instrumentation/src/arg.rs index 94f85415fa..d85ae847d0 100644 --- a/dynamic_instrumentation/src/arg.rs +++ b/dynamic_instrumentation/src/arg.rs @@ -35,6 +35,7 @@ impl<'tcx> ArgKind<'tcx> { #[derive(Clone, Debug)] pub enum InstrumentationArg<'tcx> { AddrOf(Operand<'tcx>), + Pointer(Operand<'tcx>), Op(ArgKind<'tcx>), } @@ -42,7 +43,7 @@ impl<'tcx> InstrumentationArg<'tcx> { pub fn inner(&self) -> &Operand<'tcx> { use InstrumentationArg::*; match self { - AddrOf(x) => x, + AddrOf(x) | Pointer(x) => x, Op(x) => x.inner(), } } diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index b236affcf2..8de6141217 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -925,12 +925,14 @@ pub fn insert_call<'tcx>( is_cleanup: blocks[block].is_cleanup, }); + let mut ty_substs: Vec = vec![]; for arg in &mut args { - if let Some((cast_stmts, cast_local)) = cast_ptr_to_usize(tcx, locals, arg) { + if let Some((cast_stmts, cast_local, ty_subst)) = cast_ptr_to_usize(tcx, locals, arg) { *arg = InstrumentationArg::Op(ArgKind::AddressUsize(cast_local)); blocks[block] .statements .splice(statement_index..statement_index, cast_stmts); + ty_substs.extend(ty_subst.into_iter().map(ty::GenericArg::from)); } } @@ -938,7 +940,7 @@ pub fn insert_call<'tcx>( let fn_sig = tcx.liberate_late_bound_regions(func, fn_sig); let ret_local = locals.push(LocalDecl::new(fn_sig.output(), DUMMY_SP)); - let func = Operand::function_handle(tcx, func, ty::List::empty(), DUMMY_SP); + let func = Operand::function_handle(tcx, func, tcx.mk_substs(ty_substs.into_iter()), DUMMY_SP); let call = Terminator { kind: TerminatorKind::Call { diff --git a/dynamic_instrumentation/src/point/apply.rs b/dynamic_instrumentation/src/point/apply.rs index 52e8f6830c..823d909278 100644 --- a/dynamic_instrumentation/src/point/apply.rs +++ b/dynamic_instrumentation/src/point/apply.rs @@ -111,7 +111,12 @@ impl<'tcx, 'a> InstrumentationApplier<'tcx, 'a> { }; // push return value to argument list - if let Some((casts, cast_local)) = cast_ptr_to_usize(tcx, locals, &ret_value) { + if let Some((casts, cast_local, ty)) = cast_ptr_to_usize(tcx, locals, &ret_value) { + assert!( + ty.is_none(), + "Got a type substitution for call result: {:?}", + call + ); extra_statements = Some(casts); args.push(InstrumentationArg::Op(ArgKind::AddressUsize(cast_local))); } else { diff --git a/dynamic_instrumentation/src/point/build.rs b/dynamic_instrumentation/src/point/build.rs index bc5d9c24e5..b580622d10 100644 --- a/dynamic_instrumentation/src/point/build.rs +++ b/dynamic_instrumentation/src/point/build.rs @@ -136,6 +136,13 @@ impl<'tcx> InstrumentationBuilder<'_, 'tcx> { self } + /// Add an argument to this [`InstrumentationPoint`] that copies the pointer as is. + pub fn arg_ptr(mut self, arg: impl IntoOperand<'tcx>) -> Self { + let op = arg.op(self.tcx); + self.point.args.push(InstrumentationArg::Pointer(op)); + self + } + pub fn after_call(mut self) -> Self { self.point.after_call = true; self diff --git a/dynamic_instrumentation/src/point/cast.rs b/dynamic_instrumentation/src/point/cast.rs index 6ab29aeff8..4228ae84fa 100644 --- a/dynamic_instrumentation/src/point/cast.rs +++ b/dynamic_instrumentation/src/point/cast.rs @@ -4,7 +4,7 @@ use rustc_middle::{ CastKind, Local, LocalDecl, Mutability, Operand, ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, }, - ty::{self, TyCtxt, TypeAndMut}, + ty::{self, adjustment::PointerCast, Ty, TyCtxt, TypeAndMut}, }; use rustc_span::DUMMY_SP; @@ -21,7 +21,7 @@ pub fn cast_ptr_to_usize<'tcx>( tcx: TyCtxt<'tcx>, locals: &mut IndexVec>, arg: &InstrumentationArg<'tcx>, -) -> Option<(Vec>, Operand<'tcx>)> { +) -> Option<(Vec>, Operand<'tcx>, Option>)> { let mut new_stmts = vec![]; let arg_ty = arg.inner().ty(locals, tcx); @@ -93,6 +93,53 @@ pub fn cast_ptr_to_usize<'tcx>( new_stmts.push(addr_of_stmt); Operand::Move(raw_ptr_local.into()) } + // We want to preserve the operand as a pointer, e.g., for `AddrOfConst`. + // The argument might be a reference, so we need to do a double cast, e.g. + // `&x` => `&x as *const T` and `&mut x` => `&mut x as *mut T as *const T` + InstrumentationArg::Pointer(arg) => { + let inner_ty = arg_ty + .builtin_deref(true) + .expect("Expected pointer or reference"); + + let mut new_arg = arg.clone(); + if !arg_ty.is_unsafe_ptr() { + // First cast: from non-pointer to pointer + let arg_place = arg.place().expect("Can't get the address of a constant"); + let arg_deref = tcx.mk_place_deref(arg_place); + let raw_ptr_ty = tcx.mk_ptr(inner_ty); + let raw_ptr_local = locals.push(LocalDecl::new(raw_ptr_ty, DUMMY_SP)); + let cast_stmt = Statement { + source_info: SourceInfo::outermost(DUMMY_SP), + kind: StatementKind::Assign(Box::new(( + raw_ptr_local.into(), + Rvalue::AddressOf(inner_ty.mutbl, arg_deref), + ))), + }; + new_stmts.push(cast_stmt); + new_arg = Operand::Move(raw_ptr_local.into()); + } + + if arg_ty.is_mutable_ptr() { + // Second cast: cast away the mutability + let raw_ptr_ty = tcx.mk_imm_ptr(inner_ty.ty); + let raw_ptr_local = locals.push(LocalDecl::new(raw_ptr_ty, DUMMY_SP)); + let cast_stmt = Statement { + source_info: SourceInfo::outermost(DUMMY_SP), + kind: StatementKind::Assign(Box::new(( + raw_ptr_local.into(), + Rvalue::Cast( + CastKind::Pointer(PointerCast::MutToConstPointer), + new_arg, + raw_ptr_ty, + ), + ))), + }; + new_stmts.push(cast_stmt); + new_arg = Operand::Move(raw_ptr_local.into()); + } + + return Some((new_stmts, new_arg, Some(inner_ty.ty))); + } }; let ptr = { @@ -126,5 +173,5 @@ pub fn cast_ptr_to_usize<'tcx>( ))), }; new_stmts.push(cast_stmt); - Some((new_stmts, casted_arg)) + Some((new_stmts, casted_arg, None)) } From 51402d4c2e7d31b6ac0e78a98d1198cffb51de60 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 14 Jun 2024 19:39:51 -0700 Subject: [PATCH 08/17] Add constant size information to events Add a new AddrOfSized event and use it to keep track of the sizes of all constant operands for the new provenance algorithm. --- analysis/runtime/src/events.rs | 7 + analysis/runtime/src/handlers.rs | 11 + dynamic_instrumentation/src/instrument.rs | 6 +- dynamic_instrumentation/src/point/cast.rs | 2 +- pdg/src/builder.rs | 8 +- pdg/src/graph.rs | 4 + ...nalysis_tests_misc_pdg_snapshot_debug.snap | 234 +++++++++++------- ...lysis_tests_misc_pdg_snapshot_release.snap | 234 +++++++++++------- 8 files changed, 317 insertions(+), 189 deletions(-) diff --git a/analysis/runtime/src/events.rs b/analysis/runtime/src/events.rs index be86d4ee3a..12d168e409 100644 --- a/analysis/runtime/src/events.rs +++ b/analysis/runtime/src/events.rs @@ -69,6 +69,12 @@ pub enum EventKind { size: u32, }, + /// The address and size of a sized pointee of a pointer. + AddrOfSized { + ptr: Pointer, + size: usize, + }, + /// Casting the pointer to an int ToInt(Pointer), @@ -116,6 +122,7 @@ impl Debug for EventKind { AddrOfLocal { ptr, local, size } => { write!(f, "addr_of_local({:?}, {}) = 0x{:x}", local, size, ptr) } + AddrOfSized { ptr, size } => write!(f, "addr_of_sized({}) = 0x{:x}", size, ptr), ToInt(ptr) => write!(f, "to_int(0x{:x})", ptr), FromInt(ptr) => write!(f, "from_int(0x{:x})", ptr), LoadValue(ptr) => write!(f, "load_value(0x{:x})", ptr), diff --git a/analysis/runtime/src/handlers.rs b/analysis/runtime/src/handlers.rs index 898424767f..f2063d9ea0 100644 --- a/analysis/runtime/src/handlers.rs +++ b/analysis/runtime/src/handlers.rs @@ -149,6 +149,17 @@ pub fn addr_of_local(mir_loc: MirLocId, ptr: usize, local: u32, size: u32) { }); } +pub fn addr_of_sized(mir_loc: MirLocId, ptr: *const T) { + let size = unsafe { core::mem::size_of_val(&*ptr) }; + RUNTIME.send_event(Event { + mir_loc, + kind: EventKind::AddrOfSized { + ptr: ptr as *const u8 as usize, + size, + }, + }); +} + pub fn load_value(mir_loc: MirLocId, ptr: usize) { RUNTIME.send_event(Event { mir_loc, diff --git a/dynamic_instrumentation/src/instrument.rs b/dynamic_instrumentation/src/instrument.rs index 8de6141217..f1b2036a41 100644 --- a/dynamic_instrumentation/src/instrument.rs +++ b/dynamic_instrumentation/src/instrument.rs @@ -559,6 +559,7 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { fn visit_assign(&mut self, dest: &Place<'tcx>, value: &Rvalue<'tcx>, location: Location) { let copy_fn = self.hooks().find("ptr_copy"); let addr_local_fn = self.hooks().find("addr_of_local"); + let addr_sized_fn = self.hooks().find("addr_of_sized"); let ptr_contrive_fn = self.hooks().find("ptr_contrive"); let ptr_to_int_fn = self.hooks().find("ptr_to_int"); let load_value_fn = self.hooks().find("load_value"); @@ -643,9 +644,8 @@ impl<'tcx> Visitor<'tcx> for CollectInstrumentationPoints<'_, 'tcx> { Rvalue::Use(Operand::Constant(..)) => { // Track (as copies) assignments that give local names to constants so that code // taking references to said constants can refer to these assignments as sources. - // TODO: should be replaced by AddrOfStatic when support for that is added - self.loc(location, location.successor_within_block(), copy_fn) - .arg_var(dest) + self.loc(location, location.successor_within_block(), addr_sized_fn) + .arg_ptr(dest) .dest(&dest) .debug_mir() .add_to(self); diff --git a/dynamic_instrumentation/src/point/cast.rs b/dynamic_instrumentation/src/point/cast.rs index 4228ae84fa..53d92c5be8 100644 --- a/dynamic_instrumentation/src/point/cast.rs +++ b/dynamic_instrumentation/src/point/cast.rs @@ -93,7 +93,7 @@ pub fn cast_ptr_to_usize<'tcx>( new_stmts.push(addr_of_stmt); Operand::Move(raw_ptr_local.into()) } - // We want to preserve the operand as a pointer, e.g., for `AddrOfConst`. + // We want to preserve the operand as a pointer, e.g., for `AddrOfSized`. // The argument might be a reference, so we need to do a double cast, e.g. // `&x` => `&x as *const T` and `&mut x` => `&mut x as *mut T as *const T` InstrumentationArg::Pointer(arg) => { diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index 69895a347f..885dfaaf5f 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -26,7 +26,7 @@ pub fn read_metadata(path: &Path) -> eyre::Result { fn parent<'a, 'b>(e: &'a NodeKind, obj: &'b ProvenanceInfo) -> Option<&'b ProvenanceInfo> { use NodeKind::*; match e { - Alloc(..) | AddrOfLocal(..) => None, + Alloc(..) | AddrOfLocal(..) | AddrOfSized(..) => None, _ => Some(obj), } } @@ -62,6 +62,7 @@ impl EventKindExt for EventKind { FromInt(lhs) => lhs, Alloc { ptr, .. } => ptr, AddrOfLocal { ptr, .. } => ptr, + AddrOfSized { ptr, .. } => ptr, Offset(ptr, _, _) => ptr, Done | BeginFuncBody => return None, }) @@ -101,6 +102,7 @@ impl EventKindExt for EventKind { NodeKind::Copy } } + AddrOfSized { size, .. } => NodeKind::AddrOfSized(size), BeginFuncBody => { // Reset the collection of address-taken locals, in order to // properly consider the first instance of each address-taking @@ -217,6 +219,10 @@ fn update_provenance( mapping.size = size.try_into().ok(); provenances.insert(ptr, mapping); } + AddrOfSized { ptr, size } => { + mapping.size = Some(size); + let _ = provenances.try_insert(ptr, mapping); + } _ => {} } } diff --git a/pdg/src/graph.rs b/pdg/src/graph.rs index 771bb72324..59052d85b2 100644 --- a/pdg/src/graph.rs +++ b/pdg/src/graph.rs @@ -57,6 +57,9 @@ pub enum NodeKind { /// Can't have a [`Node::source`]. _AddrOfStatic(DefPathHash), + /// Get the address of a sized value. + AddrOfSized(usize), + /// Heap allocation. /// /// The [`usize`] is the number of array elements allocated @@ -123,6 +126,7 @@ impl Display for NodeKind { Offset(offset) => write!(f, "offset[{offset}]"), AddrOfLocal(local) => write!(f, "&{local:?}"), _AddrOfStatic(static_) => write!(f, "&'static {static_:?}"), + AddrOfSized(size) => write!(f, "sized({size})"), Alloc(n) => { // Right now we only create `Alloc(1)`, so special case it, // as the increased readability helps. diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index 625a99146c..6dc27c4621 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -114,81 +114,67 @@ g { nodes_that_need_write = [3, 1, 0] g { - n[0]: copy _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; - n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); - n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); - n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[5]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; - n[6]: copy n[5] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); - n[7]: copy n[6] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); - n[8]: copy n[7] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); - n[9]: copy n[8] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[10]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; - n[11]: copy n[10] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); - n[12]: copy n[11] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); - n[13]: copy n[12] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); - n[14]: copy n[13] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[15]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; - n[16]: copy n[15] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); - n[17]: copy n[16] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); - n[18]: copy n[17] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); - n[19]: copy n[18] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[20]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; - n[21]: copy n[20] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); - n[22]: copy n[21] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); - n[23]: copy n[22] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); - n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[25]: copy n[0] => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; - n[26]: copy n[25] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); - n[27]: copy n[26] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); - n[28]: copy n[27] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); - n[29]: copy n[28] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); - n[30]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; - n[31]: copy n[30] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); - n[32]: copy n[31] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); - n[33]: copy n[32] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); - n[34]: copy n[33] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[35]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; - n[36]: copy n[35] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); - n[37]: copy n[36] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); - n[38]: copy n[37] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); - n[39]: copy n[38] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[40]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; - n[41]: copy n[40] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); - n[42]: copy n[41] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); - n[43]: copy n[42] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); - n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[45]: copy n[0] => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; - n[46]: copy n[45] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); - n[47]: copy n[46] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); - n[48]: copy n[47] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); - n[49]: copy n[48] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); - n[50]: copy n[0] => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; - n[51]: copy n[50] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); - n[52]: copy n[51] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[53]: copy n[52] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); - n[54]: copy n[53] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[55]: copy n[0] => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; - n[56]: copy n[55] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); - n[57]: copy n[56] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); - n[58]: copy n[57] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); - n[59]: copy n[58] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); - n[60]: copy n[0] => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; - n[61]: copy n[60] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); - n[62]: copy n[61] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[63]: copy n[62] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); - n[64]: copy n[63] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[65]: copy n[0] => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; - n[66]: copy n[65] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); - n[67]: copy n[66] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); - n[68]: copy n[67] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); - n[69]: copy n[68] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); - n[70]: copy n[0] => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; - n[71]: copy n[70] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); - n[72]: copy n[71] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); - n[73]: copy n[72] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); - n[74]: copy n[73] => _1 @ bb0[0]: fn printf; _13 = printf(move _14, move _18); + n[0]: sized(4) _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; + n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); + n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); + n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[5]: copy n[0] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); + n[6]: copy n[5] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); + n[7]: copy n[6] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); + n[8]: copy n[7] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); + n[9]: copy n[0] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); + n[10]: copy n[9] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); + n[11]: copy n[10] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); + n[12]: copy n[11] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); + n[13]: copy n[0] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); + n[14]: copy n[13] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); + n[15]: copy n[14] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); + n[16]: copy n[15] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); + n[17]: copy n[0] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); + n[18]: copy n[17] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); + n[19]: copy n[18] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); + n[20]: copy n[19] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); + n[21]: copy n[0] => _60 @ bb29[6]: fn exercise_allocator; _60 = &raw const (*_61); + n[22]: copy n[21] => _59 @ bb29[7]: fn exercise_allocator; _59 = move _60 as *const u8 (Pointer(ArrayToPointer)); + n[23]: copy n[22] => _58 @ bb29[9]: fn exercise_allocator; _58 = move _59 as *const i8 (Misc); + n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _57 = printf(move _58, move _62); + n[25]: copy n[0] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); + n[26]: copy n[25] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); + n[27]: copy n[26] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); + n[28]: copy n[27] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); + n[29]: copy n[0] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); + n[30]: copy n[29] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); + n[31]: copy n[30] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); + n[32]: copy n[31] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); + n[33]: copy n[0] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); + n[34]: copy n[33] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); + n[35]: copy n[34] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); + n[36]: copy n[35] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); + n[37]: copy n[0] => _93 @ bb49[6]: fn exercise_allocator; _93 = &raw const (*_94); + n[38]: copy n[37] => _92 @ bb49[7]: fn exercise_allocator; _92 = move _93 as *const u8 (Pointer(ArrayToPointer)); + n[39]: copy n[38] => _91 @ bb49[9]: fn exercise_allocator; _91 = move _92 as *const i8 (Misc); + n[40]: copy n[39] => _1 @ bb0[0]: fn printf; _90 = printf(move _91, move _95); + n[41]: copy n[0] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); + n[42]: copy n[41] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[43]: copy n[42] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); + n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[45]: copy n[43] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); + n[46]: copy n[45] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); + n[47]: copy n[46] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); + n[48]: copy n[47] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); + n[49]: copy n[0] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); + n[50]: copy n[49] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[51]: copy n[50] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); + n[52]: copy n[51] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[53]: copy n[0] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); + n[54]: copy n[53] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); + n[55]: copy n[54] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); + n[56]: copy n[55] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); + n[57]: copy n[0] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); + n[58]: copy n[57] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); + n[59]: copy n[58] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); + n[60]: copy n[59] => _1 @ bb0[0]: fn printf; _13 = printf(move _14, move _18); } nodes_that_need_write = [] @@ -219,6 +205,11 @@ g { } nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); n[1]: copy n[0] => _1 @ bb23[3]: fn exercise_allocator; _1 = move _41 as *mut pointers::S (Misc); @@ -252,6 +243,11 @@ g { } nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _74 @ bb41[2]: fn exercise_allocator; _74 = calloc(move _75, move _76); n[1]: copy n[0] => _1 @ bb42[2]: fn exercise_allocator; _1 = move _74 as *mut pointers::S (Misc); @@ -293,6 +289,11 @@ g { } nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); @@ -306,6 +307,11 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(4) _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); @@ -321,6 +327,11 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(4) _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); @@ -335,6 +346,11 @@ g { } nodes_that_need_write = [4, 2, 1, 0] +g { + n[0]: sized(4) _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); @@ -345,22 +361,21 @@ g { nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy n[0] => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy n[0] => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy n[0] => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy n[0] => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy n[0] => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: copy n[0] => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[13]: addr.store n[12] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: addr.load n[0] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[3]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[4]: addr.load n[0] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[5]: addr.store n[0] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[6]: addr.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[7]: addr.store n[0] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [13, 12, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [7, 5, 3, 1, 0] + +g { + n[0]: sized(8) _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -371,6 +386,16 @@ g { } nodes_that_need_write = [] +g { + n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); @@ -389,6 +414,31 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(8) _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(4) _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + +g { + n[0]: sized(4) _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + g { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn testing; _1 = const 10_i32; @@ -1034,6 +1084,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 69 -num_nodes = 755 +num_graphs = 83 +num_nodes = 749 diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index d0e7315fbd..ff88678909 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -114,81 +114,67 @@ g { nodes_that_need_write = [3, 1, 0] g { - n[0]: copy _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; - n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); - n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); - n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[5]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; - n[6]: copy n[5] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); - n[7]: copy n[6] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); - n[8]: copy n[7] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); - n[9]: copy n[8] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[10]: copy n[0] => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; - n[11]: copy n[10] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); - n[12]: copy n[11] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); - n[13]: copy n[12] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); - n[14]: copy n[13] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); - n[15]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; - n[16]: copy n[15] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); - n[17]: copy n[16] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); - n[18]: copy n[17] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); - n[19]: copy n[18] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[20]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; - n[21]: copy n[20] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); - n[22]: copy n[21] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); - n[23]: copy n[22] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); - n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[25]: copy n[0] => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; - n[26]: copy n[25] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); - n[27]: copy n[26] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); - n[28]: copy n[27] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); - n[29]: copy n[28] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); - n[30]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; - n[31]: copy n[30] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); - n[32]: copy n[31] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); - n[33]: copy n[32] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); - n[34]: copy n[33] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[35]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; - n[36]: copy n[35] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); - n[37]: copy n[36] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); - n[38]: copy n[37] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); - n[39]: copy n[38] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[40]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; - n[41]: copy n[40] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); - n[42]: copy n[41] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); - n[43]: copy n[42] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); - n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[45]: copy n[0] => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; - n[46]: copy n[45] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); - n[47]: copy n[46] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); - n[48]: copy n[47] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); - n[49]: copy n[48] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); - n[50]: copy n[0] => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; - n[51]: copy n[50] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); - n[52]: copy n[51] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[53]: copy n[52] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); - n[54]: copy n[53] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[55]: copy n[0] => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; - n[56]: copy n[55] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); - n[57]: copy n[56] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); - n[58]: copy n[57] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); - n[59]: copy n[58] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); - n[60]: copy n[0] => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; - n[61]: copy n[60] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); - n[62]: copy n[61] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); - n[63]: copy n[62] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); - n[64]: copy n[63] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); - n[65]: copy n[0] => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; - n[66]: copy n[65] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); - n[67]: copy n[66] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); - n[68]: copy n[67] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); - n[69]: copy n[68] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); - n[70]: copy n[0] => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; - n[71]: copy n[70] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); - n[72]: copy n[71] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); - n[73]: copy n[72] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); - n[74]: copy n[73] => _1 @ bb0[0]: fn printf; _13 = printf(move _14, move _18); + n[0]: sized(4) _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; + n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); + n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[3]: copy n[2] => _6 @ bb2[15]: fn exercise_allocator; _6 = move _7 as *const i8 (Misc); + n[4]: copy n[3] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[5]: copy n[0] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); + n[6]: copy n[5] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); + n[7]: copy n[6] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); + n[8]: copy n[7] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); + n[9]: copy n[0] => _30 @ bb11[6]: fn exercise_allocator; _30 = &raw const (*_31); + n[10]: copy n[9] => _29 @ bb11[7]: fn exercise_allocator; _29 = move _30 as *const u8 (Pointer(ArrayToPointer)); + n[11]: copy n[10] => _28 @ bb11[9]: fn exercise_allocator; _28 = move _29 as *const i8 (Misc); + n[12]: copy n[11] => _1 @ bb0[0]: fn printf; _27 = printf(move _28, move _32); + n[13]: copy n[0] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); + n[14]: copy n[13] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); + n[15]: copy n[14] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); + n[16]: copy n[15] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); + n[17]: copy n[0] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); + n[18]: copy n[17] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); + n[19]: copy n[18] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); + n[20]: copy n[19] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); + n[21]: copy n[0] => _59 @ bb28[6]: fn exercise_allocator; _59 = &raw const (*_60); + n[22]: copy n[21] => _58 @ bb28[7]: fn exercise_allocator; _58 = move _59 as *const u8 (Pointer(ArrayToPointer)); + n[23]: copy n[22] => _57 @ bb28[9]: fn exercise_allocator; _57 = move _58 as *const i8 (Misc); + n[24]: copy n[23] => _1 @ bb0[0]: fn printf; _56 = printf(move _57, move _61); + n[25]: copy n[0] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); + n[26]: copy n[25] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); + n[27]: copy n[26] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); + n[28]: copy n[27] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); + n[29]: copy n[0] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); + n[30]: copy n[29] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); + n[31]: copy n[30] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); + n[32]: copy n[31] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); + n[33]: copy n[0] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); + n[34]: copy n[33] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); + n[35]: copy n[34] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); + n[36]: copy n[35] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); + n[37]: copy n[0] => _91 @ bb47[6]: fn exercise_allocator; _91 = &raw const (*_92); + n[38]: copy n[37] => _90 @ bb47[7]: fn exercise_allocator; _90 = move _91 as *const u8 (Pointer(ArrayToPointer)); + n[39]: copy n[38] => _89 @ bb47[9]: fn exercise_allocator; _89 = move _90 as *const i8 (Misc); + n[40]: copy n[39] => _1 @ bb0[0]: fn printf; _88 = printf(move _89, move _93); + n[41]: copy n[0] => _8 @ bb2[12]: fn simple_analysis; _8 = &raw const (*_9); + n[42]: copy n[41] => _7 @ bb2[13]: fn simple_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[43]: copy n[42] => _6 @ bb2[15]: fn simple_analysis; _6 = move _7 as *const i8 (Misc); + n[44]: copy n[43] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[45]: copy n[43] => _5 @ bb0[6]: fn analysis2_helper; _5 = &raw const (*_6); + n[46]: copy n[45] => _4 @ bb0[7]: fn analysis2_helper; _4 = move _5 as *const u8 (Pointer(ArrayToPointer)); + n[47]: copy n[46] => _3 @ bb0[9]: fn analysis2_helper; _3 = move _4 as *const i8 (Misc); + n[48]: copy n[47] => _1 @ bb0[0]: fn printf; _2 = printf(move _3, move _7); + n[49]: copy n[0] => _8 @ bb2[12]: fn inter_function_analysis; _8 = &raw const (*_9); + n[50]: copy n[49] => _7 @ bb2[13]: fn inter_function_analysis; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); + n[51]: copy n[50] => _6 @ bb2[15]: fn inter_function_analysis; _6 = move _7 as *const i8 (Misc); + n[52]: copy n[51] => _1 @ bb0[0]: fn printf; _5 = printf(move _6, move _10); + n[53]: copy n[0] => _10 @ bb2[19]: fn invalid; _10 = &raw const (*_11); + n[54]: copy n[53] => _9 @ bb2[20]: fn invalid; _9 = move _10 as *const u8 (Pointer(ArrayToPointer)); + n[55]: copy n[54] => _8 @ bb2[22]: fn invalid; _8 = move _9 as *const i8 (Misc); + n[56]: copy n[55] => _1 @ bb0[0]: fn printf; _7 = printf(move _8, move _12); + n[57]: copy n[0] => _16 @ bb3[10]: fn invalid; _16 = &raw const (*_17); + n[58]: copy n[57] => _15 @ bb3[11]: fn invalid; _15 = move _16 as *const u8 (Pointer(ArrayToPointer)); + n[59]: copy n[58] => _14 @ bb3[13]: fn invalid; _14 = move _15 as *const i8 (Misc); + n[60]: copy n[59] => _1 @ bb0[0]: fn printf; _13 = printf(move _14, move _18); } nodes_that_need_write = [] @@ -219,6 +205,11 @@ g { } nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); n[1]: copy n[0] => _1 @ bb22[3]: fn exercise_allocator; _1 = move _40 as *mut pointers::S (Misc); @@ -252,6 +243,11 @@ g { } nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _72 @ bb39[2]: fn exercise_allocator; _72 = calloc(move _73, move _74); n[1]: copy n[0] => _1 @ bb40[2]: fn exercise_allocator; _1 = move _72 as *mut pointers::S (Misc); @@ -293,6 +289,11 @@ g { } nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] +g { + n[0]: sized(4) _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); @@ -306,6 +307,11 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(4) _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); @@ -321,6 +327,11 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(4) _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); @@ -335,6 +346,11 @@ g { } nodes_that_need_write = [4, 2, 1, 0] +g { + n[0]: sized(4) _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); @@ -345,22 +361,21 @@ g { nodes_that_need_write = [] g { - n[0]: copy _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[2]: copy n[0] => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; - n[3]: addr.load n[2] => _ @ bb6[6]: fn main_0; _12 = (*_13); - n[4]: copy n[0] => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; - n[5]: addr.store n[4] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); - n[6]: copy n[0] => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; - n[7]: addr.load n[6] => _ @ bb3[5]: fn no_owner; _11 = (*_12); - n[8]: copy n[0] => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; - n[9]: addr.store n[8] => _ @ bb2[10]: fn invalid; (*_6) = move _5; - n[10]: copy n[0] => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; - n[11]: addr.load n[10] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); - n[12]: copy n[0] => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; - n[13]: addr.store n[12] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; + n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[2]: addr.load n[0] => _ @ bb6[6]: fn main_0; _12 = (*_13); + n[3]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); + n[4]: addr.load n[0] => _ @ bb3[5]: fn no_owner; _11 = (*_12); + n[5]: addr.store n[0] => _ @ bb2[10]: fn invalid; (*_6) = move _5; + n[6]: addr.load n[0] => _ @ bb3[18]: fn invalid; _18 = ((*(*_19)).0: i32); + n[7]: addr.store n[0] => _ @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); } -nodes_that_need_write = [13, 12, 9, 8, 5, 4, 1, 0] +nodes_that_need_write = [7, 5, 3, 1, 0] + +g { + n[0]: sized(8) _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] g { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); @@ -371,6 +386,16 @@ g { } nodes_that_need_write = [] +g { + n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + g { n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); @@ -389,6 +414,31 @@ g { } nodes_that_need_write = [3, 1, 0] +g { + n[0]: sized(8) _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(4) _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + +g { + n[0]: sized(4) _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + +g { + n[0]: sized(8) _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; +} +nodes_that_need_write = [] + g { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn testing; _1 = const 10_i32; @@ -1026,6 +1076,6 @@ g { } nodes_that_need_write = [1, 0] -num_graphs = 67 -num_nodes = 755 +num_graphs = 81 +num_nodes = 749 From 7ed2e40d67dbf9e73e00cc07432ac937f1e07fef Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Fri, 7 Jun 2024 20:52:09 -0700 Subject: [PATCH 09/17] Add corner case for Offset(0, _, _) nodes Handle Offset nodes with a base pointer of 0 where the offset is non-zero, potentially resulting in a brand new pointer. One such case occurs in mod_cgi from lighttpd: const uintptr_t baseptr = (uintptr_t)env->b->ptr; for (i = 0; i < env->oused; ++i) envp[i] += baseptr; --- analysis/runtime/src/handlers.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/analysis/runtime/src/handlers.rs b/analysis/runtime/src/handlers.rs index f2063d9ea0..fae5f24079 100644 --- a/analysis/runtime/src/handlers.rs +++ b/analysis/runtime/src/handlers.rs @@ -82,6 +82,18 @@ pub fn reallocarray(mir_loc: MirLocId, old_ptr: usize, nmemb: u64, size: u64, ne /// = note: rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does /// ``` pub fn offset(mir_loc: MirLocId, ptr: usize, offset: isize, new_ptr: usize) { + // Corner case: Offset(..) events with a base pointer of zero are special + // because the result might be an actual pointer, e.g., c2rust will + // emit a pointer increment `a += b` as `a = a.offset(b)` which we need + // to ignore here if `a == 0` which is equivalent to `a = b`. + if ptr == 0 { + RUNTIME.send_event(Event { + mir_loc, + kind: EventKind::CopyPtr(offset as usize), + }); + return; + } + RUNTIME.send_event(Event { mir_loc, kind: EventKind::Offset(ptr, offset, new_ptr), From b9b575063e1e27fb13aea288210aac94ed701ad8 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 24 Apr 2024 22:14:45 -0700 Subject: [PATCH 10/17] Add is_null flag to PDG graphs Mark each PDG graph with a boolean flag that represents whether that graph corresponds to the null pointer or not. The PDG construction algorithm seems to build one unique graph for all null pointers in the entire program. --- pdg/src/builder.rs | 14 +- pdg/src/graph.rs | 14 +- pdg/src/info.rs | 32 ++-- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 166 +++++++++--------- ...lysis_tests_misc_pdg_snapshot_release.snap | 162 ++++++++--------- 5 files changed, 203 insertions(+), 185 deletions(-) diff --git a/pdg/src/builder.rs b/pdg/src/builder.rs index 885dfaaf5f..85f4ea8b53 100644 --- a/pdg/src/builder.rs +++ b/pdg/src/builder.rs @@ -323,13 +323,25 @@ pub fn add_node( info: None, }; + let ptr_is_null = ptr.map_or(false, |ptr| ptr == 0); let graph_id = source .as_ref() .and_then(|p| parent(&node_kind, p)) .map(|pi| pi.gid) - .unwrap_or_else(|| graphs.graphs.push(Graph::new())); + .unwrap_or_else(|| graphs.graphs.push(Graph::new(ptr_is_null))); let node_id = graphs.graphs[graph_id].nodes.push(node); + // Assert that we're not mixing null and non-null pointers + assert!( + graphs.graphs[graph_id].is_null == ptr_is_null, + "graph[{}].is_null == {:?} != {:x?} for {:?}:{:?}", + graph_id, + graphs.graphs[graph_id].is_null, + ptr, + event, + event_metadata + ); + update_provenance( provenances, &event.kind, diff --git a/pdg/src/graph.rs b/pdg/src/graph.rs index 59052d85b2..5b55037057 100644 --- a/pdg/src/graph.rs +++ b/pdg/src/graph.rs @@ -283,18 +283,24 @@ impl Display for DisplayNode<'_> { } /// A pointer derivation graph, which tracks the handling of one object throughout its lifetime. -#[derive(Debug, Default, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)] +#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)] pub struct Graph { /// The nodes in the graph. Nodes are stored in increasing order by timestamp. The first /// node, called the "root node", creates the object described by this graph, and all other /// nodes are derived from it. #[serde(with = "crate::util::serde::index_vec")] pub nodes: IndexVec, + + /// Whether this graph was built from a null pointer. + pub is_null: bool, } impl Graph { - pub fn new() -> Self { - Self::default() + pub fn new(is_null: bool) -> Self { + Self { + nodes: Default::default(), + is_null, + } } } @@ -313,7 +319,7 @@ impl Display for Graph { .to_string() }) .collect::>(); - writeln!(f, "g {{")?; + writeln!(f, "g is_null={} {{", self.is_null)?; for line in pad_columns(&lines, sep, " ") { let line = line.trim_end(); writeln!(f, "\t{line}")?; diff --git a/pdg/src/info.rs b/pdg/src/info.rs index 29d6aaf83f..b38baa7daa 100644 --- a/pdg/src/info.rs +++ b/pdg/src/info.rs @@ -298,7 +298,7 @@ mod test { /// ``` #[test] fn unique_interleave() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = 0; let a = mk_addr_of_local(&mut g, 0_u32); @@ -346,7 +346,7 @@ mod test { /// ``` #[test] fn unique_interleave_onesided() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = 0; // A let a = mk_addr_of_local(&mut g, 0_u32); @@ -390,7 +390,7 @@ mod test { /// ``` #[test] fn unique_sub_borrow() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = 0; let a = mk_addr_of_local(&mut g, 0_u32); @@ -436,7 +436,7 @@ mod test { /// ``` #[test] fn unique_sub_borrow_bad() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = 0; let a = mk_addr_of_local(&mut g, 0_u32); @@ -482,7 +482,7 @@ mod test { /// ``` #[test] fn okay_use_different_fields() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); @@ -530,7 +530,7 @@ mod test { /// ``` #[test] fn same_fields_cousins() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); @@ -579,7 +579,7 @@ mod test { /// ``` #[test] fn field_vs_raw() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); @@ -625,7 +625,7 @@ mod test { /// ``` #[test] fn fields_different_levels() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = Point { x: 0, y: 0 }; let a = mk_addr_of_local(&mut g, 0_u32); @@ -669,7 +669,7 @@ mod test { /// ``` #[test] fn lots_of_siblings() { - let mut g = Graph::default(); + let mut g = Graph::new(false); let (x, y, z) = (vec![0_usize], vec![1_usize], vec![2_usize]); let (red, green, _blue) = (vec![0_usize], vec![1_usize], vec![2_usize]); @@ -755,7 +755,7 @@ mod test { /// ``` #[test] fn field_no_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); @@ -813,7 +813,7 @@ mod test { /// ``` #[test] fn nested_field_no_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); @@ -867,7 +867,7 @@ mod test { /// ``` #[test] fn diff_field_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); //let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); @@ -921,7 +921,7 @@ mod test { /// ``` #[test] fn nested_field_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = (1, (2, 3)); let a = mk_addr_of_local(&mut g, 0_u32); @@ -983,7 +983,7 @@ mod test { /// ``` #[test] fn field_offset_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); @@ -1045,7 +1045,7 @@ mod test { /// ``` #[test] fn field_offset_no_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = ([1, 2], [3, 4]); let a = mk_addr_of_local(&mut g, 0_u32); @@ -1115,7 +1115,7 @@ mod test { /// `rustc` would reject the modified code. #[test] fn offset_field_conflict() { - let mut g = Graph::default(); + let mut g = Graph::new(false); // let mut a = ([1, 2], [3, 4]); // let p = &mut a; diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index 6dc27c4621..289cd2e548 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -3,21 +3,21 @@ source: pdg/src/main.rs assertion_line: 376 expression: pdg --- -g { +g is_null=false { n[0]: &_1 _ => _ @ bb3[0]: fn main; _23 = &raw mut _1; n[1]: copy n[0] => _11 @ bb3[10]: fn main; _11 = &(*_23); n[2]: copy n[1] => _1 @ bb0[0]: fn deref; _10 = deref(move _11); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: copy _ => _10 @ bb3[11]: fn main; _10 = deref(move _11); n[1]: copy n[0] => _9 @ bb4[0]: fn main; _9 = &(*_10); n[2]: copy n[1] => _1 @ bb0[0]: fn iter; _8 = iter(move _9); } nodes_that_need_write = [] -g { +g is_null=true { n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); @@ -30,7 +30,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_5 _ => _ @ bb10[0]: fn main; _24 = &raw mut _5; n[1]: copy n[0] => _19 @ bb10[9]: fn main; _19 = &(*_24); n[2]: copy n[1] => _1 @ bb0[0]: fn len; _18 = len(move _19); @@ -38,13 +38,13 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: copy _ => _21 @ bb12[7]: fn main; _21 = as_mut_ptr(move _22); n[1]: copy n[0] => _2 @ bb0[0]: fn main_0; _15 = main_0(move _16, move _21); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; @@ -55,7 +55,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; @@ -93,14 +93,14 @@ g { } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: copy _ => _14 @ bb9[4]: fn recur; _14 = _2; n[1]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; n[2]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; @@ -113,7 +113,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); @@ -178,7 +178,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; @@ -205,12 +205,12 @@ g { } nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _41 @ bb22[2]: fn exercise_allocator; _41 = reallocarray(move _42, move _44, move _45); n[1]: copy n[0] => _1 @ bb23[3]: fn exercise_allocator; _1 = move _41 as *mut pointers::S (Misc); n[2]: copy n[1] => _48 @ bb23[7]: fn exercise_allocator; _48 = _1; @@ -243,12 +243,12 @@ g { } nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _61 @ bb29[5]: fn exercise_allocator; _61 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _74 @ bb41[2]: fn exercise_allocator; _74 = calloc(move _75, move _76); n[1]: copy n[0] => _1 @ bb42[2]: fn exercise_allocator; _1 = move _74 as *mut pointers::S (Misc); n[2]: copy n[1] => _79 @ bb42[6]: fn exercise_allocator; _79 = _1; @@ -289,12 +289,12 @@ g { } nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _94 @ bb49[5]: fn exercise_allocator; _94 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; @@ -307,12 +307,12 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; @@ -327,12 +327,12 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); @@ -346,12 +346,12 @@ g { } nodes_that_need_write = [4, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: value.load n[0] => _12 @ bb6[6]: fn main_0; _12 = (*_13); @@ -360,7 +360,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: addr.load n[0] => _ @ bb6[6]: fn main_0; _12 = (*_13); @@ -372,12 +372,12 @@ g { } nodes_that_need_write = [7, 5, 3, 1, 0] -g { +g is_null=false { n[0]: sized(8) _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: value.load n[0] => _11 @ bb3[5]: fn no_owner; _11 = (*_12); @@ -386,17 +386,17 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; @@ -414,32 +414,32 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(8) _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(4) _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(4) _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn testing; _1 = const 10_i32; n[2]: copy n[0] => _4 @ bb0[9]: fn testing; _4 = &mut (*_8); @@ -450,7 +450,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb0[11]: fn testing; _9 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb0[10]: fn testing; _3 = &raw mut (*_4); n[2]: copy n[0] => _5 @ bb0[15]: fn testing; _5 = &mut (*_9); @@ -458,7 +458,7 @@ g { } nodes_that_need_write = [3, 2, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; @@ -467,7 +467,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; @@ -484,14 +484,14 @@ g { } nodes_that_need_write = [4, 2, 1, 0] -g { +g is_null=false { n[0]: &_13 _ => _ @ bb4[14]: fn simple1; _22 = &raw mut _13; n[1]: addr.store n[0] => _ @ bb4[13]: fn simple1; _13 = _11; n[2]: copy n[0] => _14 @ bb4[17]: fn simple1; _14 = &raw const (*_22); } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn lighttpd_test; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn lighttpd_test; _1 = move _2 as *mut *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn lighttpd_test; _9 = _1; @@ -514,7 +514,7 @@ g { } nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; @@ -540,7 +540,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); @@ -557,7 +557,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; @@ -585,7 +585,7 @@ g { } nodes_that_need_write = [12, 8, 7, 6, 3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; @@ -626,14 +626,14 @@ g { } nodes_that_need_write = [17, 15, 13, 11, 9, 7, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_malloc_free; _5 = _1; n[2]: free n[1] => _4 @ bb2[5]: fn test_malloc_free; _4 = free(move _5); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_malloc_free_cast; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_malloc_free_cast; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _7 @ bb2[7]: fn test_malloc_free_cast; _7 = _1; @@ -642,7 +642,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_arg; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_arg; _5 = _1; n[2]: copy n[1] => _1 @ bb0[0]: fn foo; _4 = foo(move _5); @@ -653,7 +653,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_arg_rec; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_arg_rec; _5 = _1; n[2]: copy n[1] => _2 @ bb0[0]: fn foo_rec; _4 = foo_rec(const 3_i32, move _5); @@ -679,7 +679,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_shared_ref; _7 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_shared_ref; _1 = const 2_u8; n[2]: copy n[0] => _2 @ bb0[5]: fn test_shared_ref; _2 = &(*_7); @@ -692,7 +692,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_unique_ref; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_unique_ref; _1 = const 10_i32; n[2]: copy n[0] => _4 @ bb0[9]: fn test_unique_ref; _4 = &mut (*_8); @@ -703,7 +703,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb0[11]: fn test_unique_ref; _9 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb0[10]: fn test_unique_ref; _3 = &raw mut (*_4); n[2]: copy n[0] => _5 @ bb0[15]: fn test_unique_ref; _5 = &mut (*_9); @@ -711,14 +711,14 @@ g { } nodes_that_need_write = [3, 2, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_realloc_reassign; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_realloc_reassign; _5 = _1; n[2]: free n[1] => _4 @ bb4[2]: fn test_realloc_reassign; _4 = realloc(move _5, move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _4 @ bb4[2]: fn test_realloc_reassign; _4 = realloc(move _5, move _6); n[1]: copy n[0] => _1 @ bb5[2]: fn test_realloc_reassign; _1 = move _4; n[2]: copy n[1] => _11 @ bb5[6]: fn test_realloc_reassign; _11 = _1; @@ -726,21 +726,21 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_realloc_fresh; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_realloc_fresh; _5 = _1; n[2]: free n[1] => _4 @ bb3[2]: fn test_realloc_fresh; _4 = realloc(move _5, move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _4 @ bb3[2]: fn test_realloc_fresh; _4 = realloc(move _5, move _6); n[1]: copy n[0] => _9 @ bb4[5]: fn test_realloc_fresh; _9 = _4; n[2]: free n[1] => _8 @ bb4[6]: fn test_realloc_fresh; _8 = free(move _9); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_addr; _2 = calloc(const 1_u64, move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_addr; _1 = move _2 as *mut pointers::S (Misc); n[2]: addr.load n[1] => _ @ bb2[5]: fn test_load_addr; _5 = (*_1); @@ -750,7 +750,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_overwrite; _1 = malloc(move _2); n[1]: copy n[0] => _4 @ bb2[3]: fn test_overwrite; _4 = _1; n[2]: copy n[1] => _12 @ bb5[4]: fn test_overwrite; _12 = _4; @@ -758,7 +758,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _5 @ bb3[2]: fn test_overwrite; _5 = malloc(move _6); n[1]: copy n[0] => _8 @ bb4[3]: fn test_overwrite; _8 = _5; n[2]: copy n[1] => _1 @ bb4[4]: fn test_overwrite; _1 = move _8; @@ -767,7 +767,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; @@ -778,7 +778,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; @@ -791,7 +791,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; @@ -802,7 +802,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[3, 3]@48 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); @@ -815,7 +815,7 @@ g { } nodes_that_need_write = [5, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); @@ -828,7 +828,7 @@ g { } nodes_that_need_write = [5, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_ptr_int_ptr; _5 = _1; n[2]: ptr_to_int n[1] => _ @ bb2[5]: fn test_ptr_int_ptr; _4 = move _5 as usize (PointerExposeAddress); @@ -838,21 +838,21 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value; _1 = malloc(move _2); n[1]: value.load n[0] => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); n[2]: free n[1] => _5 @ bb2[9]: fn test_load_value; _5 = free(move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_load_value; _7 = &raw mut _1; n[1]: copy n[0] => _4 @ bb2[4]: fn test_load_value; _4 = &raw const (*_7); n[2]: addr.load n[1] => _ @ bb2[8]: fn test_load_value; _6 = (*_4); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_store_value; _1 = malloc(move _2); n[1]: value.load n[0] => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[1] => _6 @ bb2[10]: fn test_store_value; _6 = _4; @@ -862,7 +862,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_store_value; _9 = &raw mut _1; n[1]: addr.load n[0] => _ @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[0] => _5 @ bb2[7]: fn test_store_value; _5 = &raw mut (*_9); @@ -871,7 +871,7 @@ g { } nodes_that_need_write = [3, 2, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; @@ -886,7 +886,7 @@ g { } nodes_that_need_write = [6, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); n[2]: project[2]@16 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); @@ -899,7 +899,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); n[1]: value.load n[0] => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[2]: value.store n[1] => _4.* @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; @@ -908,7 +908,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_load_value_store_value; _8 = &raw mut _1; n[1]: copy n[0] => _4 @ bb2[4]: fn test_load_value_store_value; _4 = &raw mut (*_8); n[2]: addr.load n[1] => _ @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); @@ -917,7 +917,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _59 = &raw mut _40; n[1]: addr.store n[0] => _ @ bb32[3]: fn main_0; _40 = [const 2_i32, const 5_i32, const 3_i32, const 1_i32, const 6_i32]; n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_59); @@ -999,7 +999,7 @@ g { } nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] -g { +g is_null=false { n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); @@ -1008,17 +1008,17 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: addr.load _ => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: addr.store _ => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } nodes_that_need_write = [0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _10 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken; _1 = const 2_i32; n[2]: addr.load n[0] => _ @ bb0[6]: fn test_addr_taken; _3 = (*_10); @@ -1027,7 +1027,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; n[1]: project[2]@16 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); n[2]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); @@ -1035,7 +1035,7 @@ g { } nodes_that_need_write = [2, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb2[2]: fn test_addr_taken_loop; _20 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb2[1]: fn test_addr_taken_loop; _3 = const 2_i32; n[2]: copy n[0] => _4 @ bb5[0]: fn test_addr_taken_loop; _4 = &(*_20); @@ -1050,7 +1050,7 @@ g { } nodes_that_need_write = [9, 8, 5, 4, 1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb1[1]: fn test_addr_taken_cond; _6 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb1[0]: fn test_addr_taken_cond; _2 = const 1_i32; n[2]: copy n[0] => _4 @ bb4[3]: fn test_addr_taken_cond; _4 = &(*_6); @@ -1058,7 +1058,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb3[1]: fn test_addr_taken_cond; _6 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb3[0]: fn test_addr_taken_cond; _2 = const 2_i32; n[2]: copy n[0] => _4 @ bb4[3]: fn test_addr_taken_cond; _4 = &(*_6); @@ -1066,7 +1066,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb1[1]: fn test_addr_taken_init_cond; _8 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb1[0]: fn test_addr_taken_init_cond; _2 = const 1_i32; n[2]: copy n[0] => _6 @ bb1[3]: fn test_addr_taken_init_cond; _6 = &(*_8); @@ -1077,7 +1077,7 @@ g { } nodes_that_need_write = [5, 4, 1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb4[3]: fn test_addr_taken_init_cond; _8 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb4[2]: fn test_addr_taken_init_cond; _2 = const 2_i32; n[2]: addr.load n[0] => _ @ bb4[5]: fn test_addr_taken_init_cond; _7 = (*_8); diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index ff88678909..1a30309e2c 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -3,21 +3,21 @@ source: pdg/src/main.rs assertion_line: 384 expression: pdg --- -g { +g is_null=false { n[0]: &_1 _ => _ @ bb3[0]: fn main; _22 = &raw mut _1; n[1]: copy n[0] => _11 @ bb3[10]: fn main; _11 = &(*_22); n[2]: copy n[1] => _1 @ bb0[0]: fn deref; _10 = deref(move _11); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: copy _ => _10 @ bb3[11]: fn main; _10 = deref(move _11); n[1]: copy n[0] => _9 @ bb4[0]: fn main; _9 = &(*_10); n[2]: copy n[1] => _1 @ bb0[0]: fn iter; _8 = iter(move _9); } nodes_that_need_write = [] -g { +g is_null=true { n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); @@ -30,7 +30,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_5 _ => _ @ bb10[0]: fn main; _23 = &raw mut _5; n[1]: copy n[0] => _19 @ bb10[9]: fn main; _19 = &(*_23); n[2]: copy n[1] => _1 @ bb0[0]: fn len; _18 = len(move _19); @@ -38,13 +38,13 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: copy _ => _20 @ bb11[8]: fn main; _20 = as_mut_ptr(move _21); n[1]: copy n[0] => _2 @ bb0[0]: fn main_0; _15 = main_0(move _16, move _20); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; @@ -55,7 +55,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; @@ -93,14 +93,14 @@ g { } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: copy _ => _13 @ bb8[4]: fn recur; _13 = _2; n[1]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; n[2]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn exercise_allocator; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn exercise_allocator; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn exercise_allocator; ((*_1).0: i32) = const 10_i32; @@ -113,7 +113,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn exercise_allocator; _9 = const b"%i\n\x00"; n[1]: copy n[0] => _8 @ bb2[12]: fn exercise_allocator; _8 = &raw const (*_9); n[2]: copy n[1] => _7 @ bb2[13]: fn exercise_allocator; _7 = move _8 as *const u8 (Pointer(ArrayToPointer)); @@ -178,7 +178,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _11 @ bb5[2]: fn exercise_allocator; _11 = realloc(move _12, move _14); n[1]: copy n[0] => _1 @ bb6[2]: fn exercise_allocator; _1 = move _11 as *mut pointers::S (Misc); n[2]: copy n[1] => _19 @ bb6[6]: fn exercise_allocator; _19 = _1; @@ -205,12 +205,12 @@ g { } nodes_that_need_write = [9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _31 @ bb11[5]: fn exercise_allocator; _31 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _40 @ bb21[2]: fn exercise_allocator; _40 = reallocarray(move _41, move _43, move _44); n[1]: copy n[0] => _1 @ bb22[3]: fn exercise_allocator; _1 = move _40 as *mut pointers::S (Misc); n[2]: copy n[1] => _47 @ bb22[7]: fn exercise_allocator; _47 = _1; @@ -243,12 +243,12 @@ g { } nodes_that_need_write = [13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _60 @ bb28[5]: fn exercise_allocator; _60 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _72 @ bb39[2]: fn exercise_allocator; _72 = calloc(move _73, move _74); n[1]: copy n[0] => _1 @ bb40[2]: fn exercise_allocator; _1 = move _72 as *mut pointers::S (Misc); n[2]: copy n[1] => _77 @ bb40[6]: fn exercise_allocator; _77 = _1; @@ -289,12 +289,12 @@ g { } nodes_that_need_write = [17, 15, 14, 13, 11, 10, 9, 7, 6, 5, 3, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _92 @ bb47[5]: fn exercise_allocator; _92 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple_analysis; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple_analysis; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn simple_analysis; ((*_1).0: i32) = const 10_i32; @@ -307,12 +307,12 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn simple_analysis; _9 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn analysis2; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn analysis2; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn analysis2; ((*_1).0: i32) = const 10_i32; @@ -327,12 +327,12 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _6 @ bb0[5]: fn analysis2_helper; _6 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _0 @ bb0[2]: fn malloc_wrapper; _0 = malloc(move _3); n[1]: copy n[0] => _2 @ bb1[2]: fn inter_function_analysis; _2 = malloc_wrapper(move _3); n[2]: copy n[1] => _1 @ bb2[1]: fn inter_function_analysis; _1 = move _2 as *mut pointers::S (Misc); @@ -346,12 +346,12 @@ g { } nodes_that_need_write = [4, 2, 1, 0] -g { +g is_null=false { n[0]: sized(4) _ => _9 @ bb2[11]: fn inter_function_analysis; _9 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: value.load n[0] => _12 @ bb6[6]: fn main_0; _12 = (*_13); @@ -360,7 +360,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; n[1]: addr.store n[0] => _ @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: addr.load n[0] => _ @ bb6[6]: fn main_0; _12 = (*_13); @@ -372,12 +372,12 @@ g { } nodes_that_need_write = [7, 5, 3, 1, 0] -g { +g is_null=false { n[0]: sized(8) _ => _13 @ bb6[5]: fn main_0; _13 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn no_owner; _2 = malloc(move _3); n[1]: value.store n[0] => _5.* @ bb2[3]: fn no_owner; (*_5) = move _2 as *mut pointers::S (Misc); n[2]: value.load n[0] => _11 @ bb3[5]: fn no_owner; _11 = (*_12); @@ -386,17 +386,17 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _5 @ bb2[2]: fn no_owner; _5 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _12 @ bb3[4]: fn no_owner; _12 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn invalid; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn invalid; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[5]: fn invalid; ((*_1).0: i32) = const 10_i32; @@ -414,32 +414,32 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: sized(8) _ => _6 @ bb2[9]: fn invalid; _6 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(4) _ => _11 @ bb2[18]: fn invalid; _11 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(4) _ => _17 @ bb3[9]: fn invalid; _17 = const b"%i\n\x00"; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _19 @ bb3[17]: fn invalid; _19 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: sized(8) _ => _20 @ bb4[6]: fn invalid; _20 = const {alloc8: *mut *mut pointers::S}; } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn testing; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn testing; _1 = const 10_i32; n[2]: copy n[0] => _4 @ bb0[9]: fn testing; _4 = &mut (*_8); @@ -450,7 +450,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb0[11]: fn testing; _9 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb0[10]: fn testing; _3 = &raw mut (*_4); n[2]: copy n[0] => _5 @ bb0[15]: fn testing; _5 = &mut (*_9); @@ -458,7 +458,7 @@ g { } nodes_that_need_write = [3, 2, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn simple1; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn simple1; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _8 @ bb2[8]: fn simple1; _8 = _1; @@ -467,7 +467,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn simple1; _6 = realloc(move _7, move _9); n[1]: copy n[0] => _5 @ bb4[2]: fn simple1; _5 = move _6 as *mut pointers::S (Misc); n[2]: copy n[1] => _11 @ bb4[6]: fn simple1; _11 = _5; @@ -484,14 +484,14 @@ g { } nodes_that_need_write = [4, 2, 1, 0] -g { +g is_null=false { n[0]: &_13 _ => _ @ bb4[14]: fn simple1; _22 = &raw mut _13; n[1]: addr.store n[0] => _ @ bb4[13]: fn simple1; _13 = _11; n[2]: copy n[0] => _14 @ bb4[17]: fn simple1; _14 = &raw const (*_22); } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn lighttpd_test; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn lighttpd_test; _1 = move _2 as *mut *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn lighttpd_test; _9 = _1; @@ -514,7 +514,7 @@ g { } nodes_that_need_write = [15, 14, 13, 12, 7, 6, 5, 4, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn lighttpd_test; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn lighttpd_test; _5 = move _6 as *mut pointers::fdevents (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[6]: fn lighttpd_test; ((*_5).0: *mut *mut pointers::fdnode_st) = move _9; @@ -540,7 +540,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: &_11 _ => _ @ bb4[12]: fn lighttpd_test; _24 = &raw mut _11; n[1]: addr.store n[0] => _ @ bb4[11]: fn lighttpd_test; _11 = pointers::server { ev: move _12 }; n[2]: copy n[0] => _10 @ bb4[15]: fn lighttpd_test; _10 = &mut (*_24); @@ -557,7 +557,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: alloc _ => _5 @ bb1[2]: fn connection_accepted; _5 = malloc(move _6); n[1]: copy n[0] => _4 @ bb2[1]: fn connection_accepted; _4 = move _5 as *mut pointers::connection (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn connection_accepted; ((*_4).0: i32) = move _8; @@ -585,7 +585,7 @@ g { } nodes_that_need_write = [12, 8, 7, 6, 3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _3 @ bb1[2]: fn fdnode_init; _3 = calloc(move _4, move _6); n[1]: copy n[0] => _2 @ bb2[2]: fn fdnode_init; _2 = move _3 as *mut pointers::fdnode_st (Misc); n[2]: copy n[1] => _10 @ bb2[9]: fn fdnode_init; _10 = _2; @@ -626,14 +626,14 @@ g { } nodes_that_need_write = [17, 15, 13, 11, 9, 7, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_malloc_free; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_malloc_free; _5 = _1; n[2]: free n[1] => _4 @ bb2[5]: fn test_malloc_free; _4 = free(move _5); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_malloc_free_cast; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_malloc_free_cast; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _7 @ bb2[7]: fn test_malloc_free_cast; _7 = _1; @@ -642,7 +642,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_arg; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_arg; _5 = _1; n[2]: copy n[1] => _1 @ bb0[0]: fn foo; _4 = foo(move _5); @@ -653,7 +653,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_arg_rec; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_arg_rec; _5 = _1; n[2]: copy n[1] => _2 @ bb0[0]: fn foo_rec; _4 = foo_rec(const 3_i32, move _5); @@ -679,7 +679,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_shared_ref; _7 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_shared_ref; _1 = const 2_u8; n[2]: copy n[0] => _2 @ bb0[5]: fn test_shared_ref; _2 = &(*_7); @@ -692,7 +692,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_unique_ref; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_unique_ref; _1 = const 10_i32; n[2]: copy n[0] => _4 @ bb0[9]: fn test_unique_ref; _4 = &mut (*_8); @@ -703,7 +703,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb0[11]: fn test_unique_ref; _9 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb0[10]: fn test_unique_ref; _3 = &raw mut (*_4); n[2]: copy n[0] => _5 @ bb0[15]: fn test_unique_ref; _5 = &mut (*_9); @@ -711,14 +711,14 @@ g { } nodes_that_need_write = [3, 2, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_realloc_reassign; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_realloc_reassign; _5 = _1; n[2]: free n[1] => _4 @ bb3[4]: fn test_realloc_reassign; _4 = realloc(move _5, move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _4 @ bb3[4]: fn test_realloc_reassign; _4 = realloc(move _5, move _6); n[1]: copy n[0] => _1 @ bb4[2]: fn test_realloc_reassign; _1 = move _4; n[2]: copy n[1] => _10 @ bb4[6]: fn test_realloc_reassign; _10 = _1; @@ -726,21 +726,21 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_realloc_fresh; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_realloc_fresh; _5 = _1; n[2]: free n[1] => _4 @ bb3[2]: fn test_realloc_fresh; _4 = realloc(move _5, move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _4 @ bb3[2]: fn test_realloc_fresh; _4 = realloc(move _5, move _6); n[1]: copy n[0] => _9 @ bb4[5]: fn test_realloc_fresh; _9 = _4; n[2]: free n[1] => _8 @ bb4[6]: fn test_realloc_fresh; _8 = free(move _9); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_addr; _2 = calloc(const 1_u64, move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_addr; _1 = move _2 as *mut pointers::S (Misc); n[2]: addr.load n[1] => _ @ bb2[5]: fn test_load_addr; _5 = (*_1); @@ -750,7 +750,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_overwrite; _1 = malloc(move _2); n[1]: copy n[0] => _4 @ bb2[3]: fn test_overwrite; _4 = _1; n[2]: copy n[1] => _12 @ bb5[4]: fn test_overwrite; _12 = _4; @@ -758,7 +758,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _5 @ bb3[2]: fn test_overwrite; _5 = malloc(move _6); n[1]: copy n[0] => _8 @ bb4[3]: fn test_overwrite; _8 = _5; n[2]: copy n[1] => _1 @ bb4[4]: fn test_overwrite; _1 = move _8; @@ -767,7 +767,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_store_addr; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_addr; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[4]: fn test_store_addr; ((*_1).0: i32) = const 10_i32; @@ -778,7 +778,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_other_store_self; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_load_other_store_self; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[4]: fn test_load_other_store_self; ((*_1).0: i32) = const 10_i32; @@ -791,7 +791,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn test_load_other_store_self; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn test_load_other_store_self; _5 = move _6 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb4[7]: fn test_load_other_store_self; ((*_5).0: i32) = move _9; @@ -802,7 +802,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self; _2 = calloc(move _3, move _4); n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[3, 3]@48 n[1] => _ @ bb2[6]: fn test_load_self_store_self; _6 = (((*_1).3: pointers::T).3: i32); @@ -815,7 +815,7 @@ g { } nodes_that_need_write = [5, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_load_self_store_self_inter; _2 = calloc(move _3, move _4); n[1]: copy n[0] => _1 @ bb2[2]: fn test_load_self_store_self_inter; _1 = move _2 as *mut pointers::S (Misc); n[2]: project[0]@0 n[1] => _ @ bb2[6]: fn test_load_self_store_self_inter; _6 = ((*_1).0: i32); @@ -828,7 +828,7 @@ g { } nodes_that_need_write = [5, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_ptr_int_ptr; _1 = malloc(move _2); n[1]: copy n[0] => _5 @ bb2[4]: fn test_ptr_int_ptr; _5 = _1; n[2]: ptr_to_int n[1] => _ @ bb2[5]: fn test_ptr_int_ptr; _4 = move _5 as usize (PointerExposeAddress); @@ -838,21 +838,21 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value; _1 = malloc(move _2); n[1]: value.load n[0] => _6 @ bb2[8]: fn test_load_value; _6 = (*_4); n[2]: free n[1] => _5 @ bb2[9]: fn test_load_value; _5 = free(move _6); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_load_value; _7 = &raw mut _1; n[1]: copy n[0] => _4 @ bb2[4]: fn test_load_value; _4 = &raw const (*_7); n[2]: addr.load n[1] => _ @ bb2[8]: fn test_load_value; _6 = (*_4); } nodes_that_need_write = [] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_store_value; _1 = malloc(move _2); n[1]: value.load n[0] => _4 @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[1] => _6 @ bb2[10]: fn test_store_value; _6 = _4; @@ -862,7 +862,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_store_value; _9 = &raw mut _1; n[1]: addr.load n[0] => _ @ bb2[4]: fn test_store_value; _4 = (*_9); n[2]: copy n[0] => _5 @ bb2[7]: fn test_store_value; _5 = &raw mut (*_9); @@ -871,7 +871,7 @@ g { } nodes_that_need_write = [3, 2, 0] -g { +g is_null=false { n[0]: alloc _ => _2 @ bb1[2]: fn test_store_value_field; _2 = malloc(move _3); n[1]: copy n[0] => _1 @ bb2[1]: fn test_store_value_field; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _9 @ bb4[5]: fn test_store_value_field; _9 = _1; @@ -886,7 +886,7 @@ g { } nodes_that_need_write = [6, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _6 @ bb3[2]: fn test_store_value_field; _6 = malloc(move _7); n[1]: copy n[0] => _5 @ bb4[1]: fn test_store_value_field; _5 = move _6 as *mut pointers::S (Misc); n[2]: project[2]@16 n[1] => _ @ bb4[6]: fn test_store_value_field; ((*_5).2: *const pointers::S) = move _9 as *const pointers::S (Pointer(MutToConstPointer)); @@ -899,7 +899,7 @@ g { } nodes_that_need_write = [3, 1, 0] -g { +g is_null=false { n[0]: alloc _ => _1 @ bb1[2]: fn test_load_value_store_value; _1 = malloc(move _2); n[1]: value.load n[0] => _5 @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[2]: value.store n[1] => _4.* @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; @@ -908,7 +908,7 @@ g { } nodes_that_need_write = [] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb2[0]: fn test_load_value_store_value; _8 = &raw mut _1; n[1]: copy n[0] => _4 @ bb2[4]: fn test_load_value_store_value; _4 = &raw mut (*_8); n[2]: addr.load n[1] => _ @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); @@ -919,7 +919,7 @@ g { } nodes_that_need_write = [6, 3, 1, 0] -g { +g is_null=false { n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _59 = &raw mut _40; n[1]: addr.store n[0] => _ @ bb32[3]: fn main_0; _40 = [const 2_i32, const 5_i32, const 3_i32, const 1_i32, const 6_i32]; n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_59); @@ -1001,7 +1001,7 @@ g { } nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] -g { +g is_null=false { n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); @@ -1010,7 +1010,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken; _1 = const 2_i32; n[2]: addr.load n[0] => _ @ bb0[6]: fn test_addr_taken; _3 = (*_8); @@ -1019,7 +1019,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_1 _ => _ @ bb0[0]: fn test_addr_taken_arg; _3 = &raw mut _1; n[1]: project[2]@16 n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); n[2]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); @@ -1027,7 +1027,7 @@ g { } nodes_that_need_write = [2, 0] -g { +g is_null=false { n[0]: &_3 _ => _ @ bb2[2]: fn test_addr_taken_loop; _19 = &raw mut _3; n[1]: addr.store n[0] => _ @ bb2[1]: fn test_addr_taken_loop; _3 = const 2_i32; n[2]: copy n[0] => _4 @ bb5[0]: fn test_addr_taken_loop; _4 = &(*_19); @@ -1042,7 +1042,7 @@ g { } nodes_that_need_write = [9, 8, 5, 4, 1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb1[1]: fn test_addr_taken_cond; _6 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb1[0]: fn test_addr_taken_cond; _2 = const 1_i32; n[2]: copy n[0] => _4 @ bb4[3]: fn test_addr_taken_cond; _4 = &(*_6); @@ -1050,7 +1050,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb3[1]: fn test_addr_taken_cond; _6 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb3[0]: fn test_addr_taken_cond; _2 = const 2_i32; n[2]: copy n[0] => _4 @ bb4[3]: fn test_addr_taken_cond; _4 = &(*_6); @@ -1058,7 +1058,7 @@ g { } nodes_that_need_write = [1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb1[1]: fn test_addr_taken_init_cond; _8 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb1[0]: fn test_addr_taken_init_cond; _2 = const 1_i32; n[2]: copy n[0] => _6 @ bb1[3]: fn test_addr_taken_init_cond; _6 = &(*_8); @@ -1069,7 +1069,7 @@ g { } nodes_that_need_write = [5, 4, 1, 0] -g { +g is_null=false { n[0]: &_2 _ => _ @ bb4[3]: fn test_addr_taken_init_cond; _8 = &raw mut _2; n[1]: addr.store n[0] => _ @ bb4[2]: fn test_addr_taken_init_cond; _2 = const 2_i32; n[2]: addr.load n[0] => _ @ bb4[5]: fn test_addr_taken_init_cond; _7 = (*_8); From ea9d532b11d9545e03d576ca911d60eda05469ee Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 24 Apr 2024 22:15:48 -0700 Subject: [PATCH 11/17] Add an extra null pointer test to analysis example Add one test where a function argument can be either null or non-null in the recur() function of the analysis/tests/misc example code. --- analysis/tests/misc/src/pointers.rs | 4 + ...nalysis_tests_misc_pdg_snapshot_debug.snap | 115 ++++++++++-------- ...lysis_tests_misc_pdg_snapshot_release.snap | 115 ++++++++++-------- 3 files changed, 134 insertions(+), 100 deletions(-) diff --git a/analysis/tests/misc/src/pointers.rs b/analysis/tests/misc/src/pointers.rs index 4d165bfff9..d704a7d14d 100644 --- a/analysis/tests/misc/src/pointers.rs +++ b/analysis/tests/misc/src/pointers.rs @@ -93,6 +93,9 @@ pub unsafe extern "C" fn malloc_wrapper(mut size: size_t) -> *mut libc::c_void { #[no_mangle] pub unsafe extern "C" fn recur(x: libc::c_int, s: *mut S) { if x == 0 { + if s.is_null() { + return; + } return free(s as *mut libc::c_void); } @@ -122,6 +125,7 @@ pub unsafe extern "C" fn simple() { let s = *y; *x = s; recur(3, x); + recur(3, std::ptr::null_mut()); free(x2 as *mut libc::c_void); } diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index 289cd2e548..d3f4c5feca 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -18,15 +18,28 @@ g is_null=false { nodes_that_need_write = [] g is_null=true { - n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); - n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); - n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); - n[4]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[5]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[6]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[7]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[8]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); + n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); + n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: copy n[0] => _23 @ bb5[4]: fn simple; _23 = null_mut(); + n[4]: copy n[3] => _2 @ bb0[0]: fn recur; _22 = recur(const 3_i32, move _23); + n[5]: copy n[4] => _17 @ bb15[3]: fn recur; _17 = _2; + n[6]: copy n[5] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[7]: copy n[6] => _17 @ bb15[3]: fn recur; _17 = _2; + n[8]: copy n[7] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[9]: copy n[8] => _17 @ bb15[3]: fn recur; _17 = _2; + n[10]: copy n[9] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[11]: copy n[10] => _9 @ bb1[3]: fn recur; _9 = _2; + n[12]: copy n[11] => _1 @ bb0[0]: fn is_null; _8 = is_null(move _9); + n[13]: copy n[10] => _18 @ bb16[4]: fn recur; _18 = _2; + n[14]: copy n[10] => _18 @ bb16[4]: fn recur; _18 = _2; + n[15]: copy n[10] => _18 @ bb16[4]: fn recur; _18 = _2; + n[16]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[17]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); + n[18]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[19]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[20]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[21]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -49,54 +62,56 @@ g is_null=false { n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; n[3]: project[0]@0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); - n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; - n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); - n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); + n[4]: copy n[2] => _26 @ bb7[5]: fn simple; _26 = _5; + n[5]: copy n[4] => _25 @ bb7[6]: fn simple; _25 = move _26 as *mut libc::c_void (Misc); + n[6]: free n[5] => _24 @ bb7[8]: fn simple; _24 = free(move _25); } nodes_that_need_write = [] g is_null=false { - n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); - n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; - n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; - n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); - n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); - n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; - n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; - n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); - n[25]: copy n[24] => _13 @ bb8[3]: fn recur; _13 = _2; - n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[27]: copy n[26] => _13 @ bb8[3]: fn recur; _13 = _2; - n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[29]: copy n[28] => _13 @ bb8[3]: fn recur; _13 = _2; - n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _13); - n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; - n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); - n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); + n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); + n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; + n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; + n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); + n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); + n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); + n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; + n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; + n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); + n[25]: copy n[24] => _17 @ bb15[3]: fn recur; _17 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[27]: copy n[26] => _17 @ bb15[3]: fn recur; _17 = _2; + n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[29]: copy n[28] => _17 @ bb15[3]: fn recur; _17 = _2; + n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _17); + n[31]: copy n[30] => _9 @ bb1[3]: fn recur; _9 = _2; + n[32]: copy n[31] => _1 @ bb0[0]: fn is_null; _8 = is_null(move _9); + n[33]: copy n[30] => _12 @ bb9[4]: fn recur; _12 = _2; + n[34]: copy n[33] => _11 @ bb9[5]: fn recur; _11 = move _12 as *mut libc::c_void (Misc); + n[35]: free n[34] => _0 @ bb9[7]: fn recur; _0 = free(move _11); } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] g is_null=false { - n[0]: copy _ => _14 @ bb9[4]: fn recur; _14 = _2; - n[1]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; - n[2]: copy n[0] => _14 @ bb9[4]: fn recur; _14 = _2; + n[0]: copy _ => _18 @ bb16[4]: fn recur; _18 = _2; + n[1]: copy n[0] => _18 @ bb16[4]: fn recur; _18 = _2; + n[2]: copy n[0] => _18 @ bb16[4]: fn recur; _18 = _2; } nodes_that_need_write = [] @@ -1085,5 +1100,5 @@ g is_null=false { nodes_that_need_write = [1, 0] num_graphs = 83 -num_nodes = 749 +num_nodes = 764 diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index 1a30309e2c..3a21c4a2ff 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -18,15 +18,28 @@ g is_null=false { nodes_that_need_write = [] g is_null=true { - n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); - n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); - n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[3]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); - n[4]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[5]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[6]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[7]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[8]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[0]: copy _ => _14 @ bb6[4]: fn main; _14 = null_mut(); + n[1]: copy n[0] => _1 @ bb0[0]: fn once; _13 = once(move _14); + n[2]: int_to_ptr n[0] => _17 @ bb4[29]: fn simple; _17 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[3]: copy n[0] => _23 @ bb5[4]: fn simple; _23 = null_mut(); + n[4]: copy n[3] => _2 @ bb0[0]: fn recur; _22 = recur(const 3_i32, move _23); + n[5]: copy n[4] => _16 @ bb14[9]: fn recur; _16 = _2; + n[6]: copy n[5] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[7]: copy n[6] => _16 @ bb14[9]: fn recur; _16 = _2; + n[8]: copy n[7] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[9]: copy n[8] => _16 @ bb14[9]: fn recur; _16 = _2; + n[10]: copy n[9] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[11]: copy n[10] => _9 @ bb1[3]: fn recur; _9 = _2; + n[12]: copy n[11] => _1 @ bb0[0]: fn is_null; _8 = is_null(move _9); + n[13]: copy n[10] => _17 @ bb15[4]: fn recur; _17 = _2; + n[14]: copy n[10] => _17 @ bb15[4]: fn recur; _17 = _2; + n[15]: copy n[10] => _17 @ bb15[4]: fn recur; _17 = _2; + n[16]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); + n[17]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); + n[18]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[19]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[20]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[21]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -49,54 +62,56 @@ g is_null=false { n[1]: copy n[0] => _1 @ bb2[1]: fn simple; _1 = move _2 as *mut pointers::S (Misc); n[2]: copy n[1] => _5 @ bb2[5]: fn simple; _5 = _1; n[3]: project[0]@0 n[1] => _10 @ bb4[5]: fn simple; _10 = &raw const ((*_1).0: i32); - n[4]: copy n[2] => _24 @ bb5[5]: fn simple; _24 = _5; - n[5]: copy n[4] => _23 @ bb5[6]: fn simple; _23 = move _24 as *mut libc::c_void (Misc); - n[6]: free n[5] => _22 @ bb5[8]: fn simple; _22 = free(move _23); + n[4]: copy n[2] => _26 @ bb7[5]: fn simple; _26 = _5; + n[5]: copy n[4] => _25 @ bb7[6]: fn simple; _25 = move _26 as *mut libc::c_void (Misc); + n[6]: free n[5] => _24 @ bb7[8]: fn simple; _24 = free(move _25); } nodes_that_need_write = [] g is_null=false { - n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); - n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); - n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; - n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; - n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; - n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); - n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; - n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; - n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); - n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); - n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); - n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; - n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; - n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); - n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; - n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; - n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); - n[25]: copy n[24] => _12 @ bb7[9]: fn recur; _12 = _2; - n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[27]: copy n[26] => _12 @ bb7[9]: fn recur; _12 = _2; - n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[29]: copy n[28] => _12 @ bb7[9]: fn recur; _12 = _2; - n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _9 = recur(move _10, move _12); - n[31]: copy n[30] => _8 @ bb1[2]: fn recur; _8 = _2; - n[32]: copy n[31] => _7 @ bb1[3]: fn recur; _7 = move _8 as *mut libc::c_void (Misc); - n[33]: free n[32] => _0 @ bb1[5]: fn recur; _0 = free(move _7); + n[0]: alloc _ => _7 @ bb3[2]: fn simple; _7 = malloc(move _8); + n[1]: copy n[0] => _6 @ bb4[1]: fn simple; _6 = move _7 as *mut pointers::S (Misc); + n[2]: copy n[1] => _11 @ bb4[8]: fn simple; _11 = _6; + n[3]: copy n[2] => _1 @ bb4[9]: fn simple; _1 = move _11; + n[4]: project[0]@0 n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[5]: addr.store n[3] => _ @ bb4[11]: fn simple; ((*_1).0: i32) = const 10_i32; + n[6]: project[0]@0 n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[7]: addr.load n[3] => _ @ bb4[13]: fn simple; _12 = ((*_1).0: i32); + n[8]: project[0]@0 n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[9]: addr.store n[1] => _ @ bb4[14]: fn simple; ((*_6).0: i32) = move _12; + n[10]: project[1]@8 n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[11]: addr.store n[3] => _ @ bb4[16]: fn simple; ((*_1).1: u64) = const 9_u64; + n[12]: project[0]@0 n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[13]: addr.load n[3] => _ @ bb4[18]: fn simple; _13 = ((*_1).0: i32); + n[14]: project[1]@8 n[3] => _14 @ bb4[21]: fn simple; _14 = &raw const ((*_1).1: u64); + n[15]: copy n[3] => _15 @ bb4[24]: fn simple; _15 = &raw const (*_1); + n[16]: project[2]@16 n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[17]: addr.store n[3] => _ @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[18]: value.store n[15] => _1.*.2 @ bb4[25]: fn simple; ((*_1).2: *const pointers::S) = move _15; + n[19]: project[3]@24 n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[20]: addr.store n[1] => _ @ bb4[32]: fn simple; ((*_6).3: pointers::T) = move _16; + n[21]: addr.load n[1] => _ @ bb4[35]: fn simple; _18 = (*_6); + n[22]: addr.store n[3] => _ @ bb4[39]: fn simple; (*_1) = move _19; + n[23]: copy n[3] => _21 @ bb4[43]: fn simple; _21 = _1; + n[24]: copy n[23] => _2 @ bb0[0]: fn recur; _20 = recur(const 3_i32, move _21); + n[25]: copy n[24] => _16 @ bb14[9]: fn recur; _16 = _2; + n[26]: copy n[25] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[27]: copy n[26] => _16 @ bb14[9]: fn recur; _16 = _2; + n[28]: copy n[27] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[29]: copy n[28] => _16 @ bb14[9]: fn recur; _16 = _2; + n[30]: copy n[29] => _2 @ bb0[0]: fn recur; _13 = recur(move _14, move _16); + n[31]: copy n[30] => _9 @ bb1[3]: fn recur; _9 = _2; + n[32]: copy n[31] => _1 @ bb0[0]: fn is_null; _8 = is_null(move _9); + n[33]: copy n[30] => _12 @ bb9[4]: fn recur; _12 = _2; + n[34]: copy n[33] => _11 @ bb9[5]: fn recur; _11 = move _12 as *mut libc::c_void (Misc); + n[35]: free n[34] => _0 @ bb9[7]: fn recur; _0 = free(move _11); } nodes_that_need_write = [22, 20, 17, 11, 9, 5, 3, 2, 1, 0] g is_null=false { - n[0]: copy _ => _13 @ bb8[4]: fn recur; _13 = _2; - n[1]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; - n[2]: copy n[0] => _13 @ bb8[4]: fn recur; _13 = _2; + n[0]: copy _ => _17 @ bb15[4]: fn recur; _17 = _2; + n[1]: copy n[0] => _17 @ bb15[4]: fn recur; _17 = _2; + n[2]: copy n[0] => _17 @ bb15[4]: fn recur; _17 = _2; } nodes_that_need_write = [] @@ -1077,5 +1092,5 @@ g is_null=false { nodes_that_need_write = [1, 0] num_graphs = 81 -num_nodes = 749 +num_nodes = 764 From 33e051bb9a889c548f8b4bab88af4630fcca7433 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Sun, 4 Aug 2024 19:39:21 -0700 Subject: [PATCH 12/17] Log unknown PDG functions instead of panicking --- c2rust-analyze/src/analyze.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/c2rust-analyze/src/analyze.rs b/c2rust-analyze/src/analyze.rs index ca06002a4c..3395c2c5f8 100644 --- a/c2rust-analyze/src/analyze.rs +++ b/c2rust-analyze/src/analyze.rs @@ -949,10 +949,11 @@ fn run(tcx: TyCtxt) { let ldid = match func_def_path_hash_to_ldid.get(&def_path_hash) { Some(&x) => x, None => { - panic!( + eprintln!( "pdg: unknown DefPathHash {:?} for function {:?}", n.function.id, n.function.name ); + continue; } }; let info = func_info.get_mut(&ldid).unwrap(); From 01f6e2f1f9b607861227171524f1b84cda5c095f Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Sun, 4 Aug 2024 19:39:46 -0700 Subject: [PATCH 13/17] Log and ignore out-of-bounds locals in PDG The dynamic instrumentation code inserts additional locals for its own instrumentation code. --- c2rust-analyze/src/analyze.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/c2rust-analyze/src/analyze.rs b/c2rust-analyze/src/analyze.rs index 3395c2c5f8..32511addd8 100644 --- a/c2rust-analyze/src/analyze.rs +++ b/c2rust-analyze/src/analyze.rs @@ -977,6 +977,14 @@ fn run(tcx: TyCtxt) { let dest = dest_pl.local; let dest = Local::from_u32(dest.index); + if acx.local_tys.get(dest).is_none() { + eprintln!( + "pdg: {}: local {:?} appears as dest, but is out of bounds", + n.function.name, dest + ); + info.acx_data.set(acx.into_data()); + continue; + } let ptr = match acx.ptr_of(dest) { Some(x) => x, None => { From 425ce04dd7e4fde77384f5cfc9b552d85fe67852 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Wed, 24 Apr 2024 22:17:09 -0700 Subject: [PATCH 14/17] Use PDG to remove NON_NULL from pointers in static analysis Remove the NON_NULL permission from all nodes in the null graph from the PDG. --- c2rust-analyze/src/analyze.rs | 45 +++++++++++++++-------------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/c2rust-analyze/src/analyze.rs b/c2rust-analyze/src/analyze.rs index 32511addd8..9fa102c2bd 100644 --- a/c2rust-analyze/src/analyze.rs +++ b/c2rust-analyze/src/analyze.rs @@ -997,36 +997,29 @@ fn run(tcx: TyCtxt) { } }; - let node_info = match n.info.as_ref() { - Some(x) => x, - None => { - eprintln!( - "pdg: {}: node with dest {:?} is missing NodeInfo", - n.function.name, dest - ); - info.acx_data.set(acx.into_data()); - continue; - } - }; - let old_perms = asn.perms()[ptr]; let mut perms = old_perms; - if node_info.flows_to.load.is_some() { - perms.insert(PermissionSet::READ); + if g.is_null { + perms.remove(PermissionSet::NON_NULL); } - if node_info.flows_to.store.is_some() { - perms.insert(PermissionSet::WRITE); - } - if node_info.flows_to.pos_offset.is_some() { - perms.insert(PermissionSet::OFFSET_ADD); - } - if node_info.flows_to.neg_offset.is_some() { - perms.insert(PermissionSet::OFFSET_SUB); - } - if !node_info.unique { - perms.remove(PermissionSet::UNIQUE); + + if let Some(node_info) = n.info.as_ref() { + if node_info.flows_to.load.is_some() { + perms.insert(PermissionSet::READ); + } + if node_info.flows_to.store.is_some() { + perms.insert(PermissionSet::WRITE); + } + if node_info.flows_to.pos_offset.is_some() { + perms.insert(PermissionSet::OFFSET_ADD); + } + if node_info.flows_to.neg_offset.is_some() { + perms.insert(PermissionSet::OFFSET_SUB); + } + if !node_info.unique { + perms.remove(PermissionSet::UNIQUE); + } } - // TODO: PermissionSet::NON_NULL if perms != old_perms { let added = perms & !old_perms; From 74c9bf4c44cc2fd1ffa79b59d190058d684e71b8 Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Mon, 5 Aug 2024 16:20:11 -0700 Subject: [PATCH 15/17] Unsound: add non-null pointers from PDG to updates_forbidden If the dynamic analysis tells us a pointer is never NULL (i.e. it never shows up in an is_null graph), then force the NON_NULL permission on it using updates_forbidden. This is potentially an unsound transformation because the pointer may actually be NULL on other inputs not covered by the sample ones. --- c2rust-analyze/src/analyze.rs | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/c2rust-analyze/src/analyze.rs b/c2rust-analyze/src/analyze.rs index 9fa102c2bd..84391a23a7 100644 --- a/c2rust-analyze/src/analyze.rs +++ b/c2rust-analyze/src/analyze.rs @@ -943,6 +943,29 @@ fn run(tcx: TyCtxt) { let f = std::fs::File::open(pdg_file_path).unwrap(); let graphs: Graphs = bincode::deserialize_from(f).unwrap(); + let mut known_nulls = HashSet::new(); + for g in &graphs.graphs { + for n in &g.nodes { + let dest_pl = match n.dest.as_ref() { + Some(x) => x, + None => { + continue; + } + }; + if !dest_pl.projection.is_empty() { + continue; + } + let dest = dest_pl.local; + let dest = Local::from_u32(dest.index); + if g.is_null { + known_nulls.insert((n.function.id, dest)); + } + } + } + + let allow_unsound = + env::var("C2RUST_ANALYZE_PDG_ALLOW_UNSOUND").map_or(false, |val| &val == "1"); + for g in &graphs.graphs { for n in &g.nodes { let def_path_hash: (u64, u64) = n.function.id.0.into(); @@ -962,6 +985,8 @@ fn run(tcx: TyCtxt) { let mir = mir.borrow(); let acx = gacx.function_context_with_data(&mir, info.acx_data.take()); let mut asn = gasn.and(&mut info.lasn); + let mut updates_forbidden = + g_updates_forbidden.and_mut(&mut info.l_updates_forbidden); let dest_pl = match n.dest.as_ref() { Some(x) => x, @@ -999,8 +1024,14 @@ fn run(tcx: TyCtxt) { let old_perms = asn.perms()[ptr]; let mut perms = old_perms; - if g.is_null { + if known_nulls.contains(&(n.function.id, dest)) { perms.remove(PermissionSet::NON_NULL); + } else if allow_unsound { + perms.insert(PermissionSet::NON_NULL); + // Unsound update: if we have never seen a NULL for + // this local in the PDG, prevent the static analysis + // from changing that permission. + updates_forbidden[ptr].insert(PermissionSet::NON_NULL); } if let Some(node_info) = n.info.as_ref() { From e50743c1bc468cad51466533a99094584f64901d Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Mon, 26 Aug 2024 19:36:20 -0700 Subject: [PATCH 16/17] Update reference PDG for analysis/tests/minimal --- analysis/tests/minimal/reference_pdg.bc | Bin 1470 -> 1450 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/analysis/tests/minimal/reference_pdg.bc b/analysis/tests/minimal/reference_pdg.bc index 6a9034e8d4809ba387f9dd4a8d3b7fd9a05e47b7..c116f496134cda31cc04305d4321a82a5c7079e5 100644 GIT binary patch literal 1450 zcmb7D%TB{E5cHP!OMnn?^$9gSku-fBkPwGn`2-803iZ%dqJatt@fGkH`~xSxi6b7b z*G(%>9Ul^V7lUar96#Vx^C7inH-y8H zkC?8$(ie|+Gd+4Lv`LBZJ8iqq6anqfaC;yBVRMX!T_&~A_mlCo(CMWaHZxMhw_|WO z8AK5%mzRS$^bykpeNeAAOgC}gV$h{V6e{BZUEoB}vvP54hGu*QVMroGG%WIOFY))+ zV>Cz$X+xkz!@AuB4Xq^&ZL6U|7U?Ddl-tK?4sb?lQEKaxCpOt=@;uO{RVm9kV=A=^ zR2{mY>hrVJIqa^2-EKNnq^Lx7*MUQ(IAc!>Fazd< literal 1470 zcmb7EOHRWu5Vgx+AOS+a)+>~hE=ZH6?SefgU~3^%p)T4=G{6P816O0i7B0XJ33Wc6 zBsD>DEVXuK>^Jk~jonc^cHI1P6TScDz1Oea=jGeS?YG#A$+DQvA8=R4ZB-kv(D-rW zEOunB&Bf#0i+vpO#t?OF<%xYxw6x=54gNL1eY@a zNKCgr2;$ILY>KI4+ELezV)BKcOMP@%6$eO$6G89S3j-0-@CcHjD`mxCJ^$RxzeVLm zKD||e(@Jl`RB{-29CF~$B8sR z(neU?ah-?7W@6rL1zOa5P%IjhM$Mgh31Lvj}ZICrec{{;_6 zJ$1Qixe1axT>xQahozob@ZCBWsPaWPbC#$JJu-~3N%&omXTd2c>idl%4TOE|`{V*6 lb>D~FFzu#uXhR>K_s_|b)8v!OhO>We&tby!$0yv-w*pIgA({XH From 036e230c6e8b85d7ac5643904f6ac63c4f049bcd Mon Sep 17 00:00:00 2001 From: Andrei Homescu Date: Tue, 22 Oct 2024 18:37:55 -0700 Subject: [PATCH 17/17] Disable test_ref_field which fails on Darwin --- analysis/tests/misc/src/pointers.rs | 6 +++- ...nalysis_tests_misc_pdg_snapshot_debug.snap | 33 ++++--------------- ...lysis_tests_misc_pdg_snapshot_release.snap | 27 ++++----------- 3 files changed, 18 insertions(+), 48 deletions(-) diff --git a/analysis/tests/misc/src/pointers.rs b/analysis/tests/misc/src/pointers.rs index d704a7d14d..e7366fe999 100644 --- a/analysis/tests/misc/src/pointers.rs +++ b/analysis/tests/misc/src/pointers.rs @@ -746,7 +746,11 @@ unsafe fn main_0(mut argc: libc::c_int, mut argv: *mut *mut libc::c_char) -> lib test_load_value_store_value(); let nums = &mut [2i32, 5i32, 3i32, 1i32, 6i32]; insertion_sort(nums.len() as libc::c_int, nums as *mut libc::c_int); - test_ref_field(); + // TODO: this test is broken on Darwin because the fields structure fields + // alias with locals of other functions, and the locals are different between + // Linux and Darwin. We should re-enable test_ref_field once we track stack + // lifetimes (see https://github.com/immunant/c2rust/issues/1117). + //test_ref_field(); test_addr_taken(); let mut t = T { field: 0i32, diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap index d3f4c5feca..0e01ad109b 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_debug.snap @@ -36,10 +36,8 @@ g is_null=true { n[15]: copy n[10] => _18 @ bb16[4]: fn recur; _18 = _2; n[16]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); n[17]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[18]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[19]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[20]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[21]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[18]: int_to_ptr n[0] => _50 @ bb35[3]: fn main_0; _50 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[19]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -933,9 +931,9 @@ g is_null=false { nodes_that_need_write = [3, 1, 0] g is_null=false { - n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _59 = &raw mut _40; + n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _58 = &raw mut _40; n[1]: addr.store n[0] => _ @ bb32[3]: fn main_0; _40 = [const 2_i32, const 5_i32, const 3_i32, const 1_i32, const 6_i32]; - n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_59); + n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_58); n[3]: copy n[2] => _45 @ bb32[12]: fn main_0; _45 = &(*_39); n[4]: copy n[3] => _44 @ bb32[13]: fn main_0; _44 = move _45 as &[i32] (Pointer(Unsize)); n[5]: copy n[4] => _1 @ bb0[0]: fn len; _43 = len(move _44); @@ -1014,25 +1012,6 @@ g is_null=false { } nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] -g is_null=false { - n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; - n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; - n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); - n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; -} -nodes_that_need_write = [1, 0] - -g is_null=false { - n[0]: addr.load _ => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); -} -nodes_that_need_write = [] - -g is_null=false { - n[0]: addr.store _ => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; -} -nodes_that_need_write = [0] - g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _10 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken; _1 = const 2_i32; @@ -1099,6 +1078,6 @@ g is_null=false { } nodes_that_need_write = [1, 0] -num_graphs = 83 -num_nodes = 764 +num_graphs = 80 +num_nodes = 755 diff --git a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap index 3a21c4a2ff..09e34b8a04 100644 --- a/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap +++ b/pdg/src/snapshots/c2rust_pdg__tests__analysis_tests_misc_pdg_snapshot_release.snap @@ -36,10 +36,8 @@ g is_null=true { n[15]: copy n[10] => _17 @ bb15[4]: fn recur; _17 = _2; n[16]: value.store n[0] => _20.* @ bb4[7]: fn invalid; (*_20) = const 0_usize as *mut pointers::S (PointerFromExposedAddress); n[17]: value.store n[0] => _17.* @ bb8[4]: fn fdevent_unregister; (*_17) = const 0_usize as *mut pointers::fdnode_st (PointerFromExposedAddress); - n[18]: int_to_ptr n[0] => _2 @ bb0[2]: fn test_ref_field; _2 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[19]: int_to_ptr n[0] => _5 @ bb0[8]: fn test_ref_field; _5 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[20]: int_to_ptr n[0] => _51 @ bb36[3]: fn main_0; _51 = const 0_usize as *const pointers::S (PointerFromExposedAddress); - n[21]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[18]: int_to_ptr n[0] => _50 @ bb35[3]: fn main_0; _50 = const 0_usize as *const pointers::S (PointerFromExposedAddress); + n[19]: value.store n[0] => _3.*.2 @ bb0[1]: fn test_addr_taken_arg; ((*_3).2: *const pointers::S) = const 0_usize as *const pointers::S (PointerFromExposedAddress); } nodes_that_need_write = [] @@ -929,15 +927,13 @@ g is_null=false { n[2]: addr.load n[1] => _ @ bb2[7]: fn test_load_value_store_value; _5 = (*_4); n[3]: addr.store n[1] => _ @ bb2[8]: fn test_load_value_store_value; (*_4) = move _5; n[4]: addr.load n[1] => _ @ bb2[12]: fn test_load_value_store_value; _7 = (*_4); - n[5]: addr.load n[0] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[6]: addr.store n[0] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; } -nodes_that_need_write = [6, 3, 1, 0] +nodes_that_need_write = [3, 1, 0] g is_null=false { - n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _59 = &raw mut _40; + n[0]: &_40 _ => _ @ bb32[4]: fn main_0; _58 = &raw mut _40; n[1]: addr.store n[0] => _ @ bb32[3]: fn main_0; _40 = [const 2_i32, const 5_i32, const 3_i32, const 1_i32, const 6_i32]; - n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_59); + n[2]: copy n[0] => _39 @ bb32[5]: fn main_0; _39 = &mut (*_58); n[3]: copy n[2] => _45 @ bb32[12]: fn main_0; _45 = &(*_39); n[4]: copy n[3] => _44 @ bb32[13]: fn main_0; _44 = move _45 as &[i32] (Pointer(Unsize)); n[5]: copy n[4] => _1 @ bb0[0]: fn len; _43 = len(move _44); @@ -1016,15 +1012,6 @@ g is_null=false { } nodes_that_need_write = [77, 76, 75, 68, 67, 66, 65, 64, 63, 56, 55, 54, 47, 46, 45, 35, 34, 33, 29, 28, 27, 17, 16, 15, 8, 7, 6, 2, 1, 0] -g is_null=false { - n[0]: &_4 _ => _ @ bb0[12]: fn test_ref_field; _8 = &raw mut _4; - n[1]: addr.store n[0] => _ @ bb0[11]: fn test_ref_field; _4 = pointers::S { field: const 0_i32, field2: const 0_u64, field3: move _5, field4: move _6 }; - n[2]: copy n[0] => _3 @ bb0[16]: fn test_ref_field; _3 = &mut (*_8); - n[3]: project[3, 3]@48 n[2] => _ @ bb0[18]: fn test_ref_field; _7 = (((*_3).3: pointers::T).3: i32); - n[4]: project[3, 3]@48 n[2] => _ @ bb0[19]: fn test_ref_field; (((*_3).3: pointers::T).3: i32) = move _7; -} -nodes_that_need_write = [1, 0] - g is_null=false { n[0]: &_1 _ => _ @ bb0[2]: fn test_addr_taken; _8 = &raw mut _1; n[1]: addr.store n[0] => _ @ bb0[1]: fn test_addr_taken; _1 = const 2_i32; @@ -1091,6 +1078,6 @@ g is_null=false { } nodes_that_need_write = [1, 0] -num_graphs = 81 -num_nodes = 764 +num_graphs = 80 +num_nodes = 755