Skip to content

Commit

Permalink
as_mut_ptr & offset
Browse files Browse the repository at this point in the history
  • Loading branch information
Medowhill committed Jan 22, 2024
1 parent bee14ad commit da4c3d8
Show file tree
Hide file tree
Showing 5 changed files with 264 additions and 38 deletions.
6 changes: 1 addition & 5 deletions src/bin/urcrat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,5 @@ fn main() {
}

let file = args.input.join("c2rust-lib.rs");
steensgaard::analyze_path(&file);
// relational::analyze_str(
// "
// ",
// );
relational::analyze_path(&file);
}
5 changes: 1 addition & 4 deletions src/relational/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ pub struct Analyzer<'tcx, 'a> {
dead_locals: Vec<BitSet<Local>>,
local_tys: Vec<TyStructure>,
local_ptr_tys: HashMap<Local, TyStructure>,
local_def_id: LocalDefId,
pub local_def_id: LocalDefId,
indirect_assigns: &'a HashMap<LocalDefId, HashSet<Local>>,
reachability: &'a HashMap<LocalDefId, HashSet<LocalDefId>>,
alias_graph: &'a steensgaard::AliasGraph,
Expand Down Expand Up @@ -274,9 +274,6 @@ impl TyStructure {
match ty.kind() {
TyKind::Adt(adt_def, generic_args) => {
if adt_def.adt_kind() == AdtKind::Enum {
let def_id = adt_def.did();
let name = tcx.def_path(def_id).to_string_no_crate_verbose();
assert!(name.contains("::Option") && !def_id.is_local(), "{name}");
Self::Adt(vec![Self::Leaf])
} else {
let variant = &adt_def.variants()[VariantIdx::from_usize(0)];
Expand Down
58 changes: 57 additions & 1 deletion src/relational/domains.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ impl AbsLoc {
pub fn root(&self) -> NodeId {
self.root
}

#[inline]
pub fn projection(&self) -> &[AccElem] {
&self.projection
}
}

#[derive(Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -454,7 +459,7 @@ impl Graph {
*obj = Obj::Ptr(AbsLoc::new(id, vec![]));
}

fn x_eq(&mut self, x: &AccPath, deref: bool) {
pub fn x_eq(&mut self, x: &AccPath, deref: bool) {
let obj = self.lvalue(x, deref);
*obj = Obj::default();
}
Expand All @@ -473,6 +478,57 @@ impl Graph {
*obj = Obj::Ptr(loc);
}

pub fn x_eq_offset(&mut self, x: &AccPath, y: &AccPath, idx: OpVal) {
let (id, _) = self.get_local_node_mut(y.local);
let loc = self.get_pointed_loc_mut(id, &[]);
let mut loc = if loc.projection.is_empty() {
let Obj::Ptr(loc) = &mut self.nodes[id].obj else { panic!() };
loc.projection.push(AccElem::Int(0));
let loc = loc.clone();
self.obj_at_location_mut(&loc);
loc
} else {
loc
};
let elem = loc.projection.last_mut().unwrap();
if let AccElem::Int(n) = elem {
match idx {
OpVal::Place(idx, idx_deref) => {
assert!(idx.projection.is_empty());
assert!(!idx_deref);
*elem = AccElem::Symbolic(self.find_aliases(idx.local));
let obj = self.lvalue(x, false);
*obj = Obj::Ptr(loc);
}
OpVal::Int(idx) => {
*n += idx as usize;
let obj = self.lvalue(x, false);
*obj = Obj::Ptr(loc);
}
OpVal::Other => {
let obj = self.lvalue(x, false);
*obj = Obj::default();
}
}
} else {
let obj = self.lvalue(x, false);
*obj = Obj::default();
}
}

pub fn x_eq_offset_int(&mut self, x: &AccPath, y: &AccPath, idx: u128) {
let (id, _) = self.get_local_node_mut(y.local);
let mut loc = self.get_pointed_loc_mut(id, &[]);
let obj = self.lvalue(x, false);
let elem = loc.projection.last_mut().unwrap();
if let AccElem::Int(n) = elem {
*n += idx as usize;
*obj = Obj::Ptr(loc);
} else {
*obj = Obj::default();
}
}

pub fn filter_x_int(&mut self, x: &AccPath, deref: bool, n: u128) {
let ptr = self.set_obj_ptr(|this| this.lvalue(x, deref));
assert!(ptr.projection.is_empty());
Expand Down
88 changes: 62 additions & 26 deletions src/relational/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,24 @@ impl<'tcx> Analyzer<'tcx, '_> {
_ => unreachable!(),
};
state.gm().assign(&l, l_deref, &OpVal::Int(v));
} else if matches!(ty.kind(), TyKind::Uint(UintTy::Usize)) {
state.gm().assign(&l, l_deref, &r);
} else {
state.gm().assign(&l, l_deref, &OpVal::Other);
state.gm().assign(&l, l_deref, &r);
}
}
CastKind::PointerCoercion(coercion) => {
if *coercion == PointerCoercion::MutToConstPointer {
let r = self.transfer_op(r, state);
state.gm().assign_with_suffixes(&l, l_deref, &r, &suffixes);
} else {
CastKind::PointerCoercion(coercion) => match coercion {
PointerCoercion::ReifyFnPointer
| PointerCoercion::UnsafeFnPointer
| PointerCoercion::ClosureFnPointer(_) => {
state
.gm()
.assign_with_suffixes(&l, l_deref, &OpVal::Other, &suffixes);
}
}
PointerCoercion::MutToConstPointer | PointerCoercion::Unsize => {
let r = self.transfer_op(r, state);
state.gm().assign_with_suffixes(&l, l_deref, &r, &suffixes);
}
PointerCoercion::ArrayToPointer => todo!(),
},
_ => {
state
.gm()
Expand Down Expand Up @@ -333,11 +335,12 @@ impl<'tcx> Analyzer<'tcx, '_> {
block: *target,
statement_index: 0,
};
match func {
let need_update = match func {
Operand::Copy(func) | Operand::Move(func) => {
assert!(func.projection.is_empty());
let callees = self.resolve_indirect_calls(func.local);
self.transfer_intra_call(&callees, &mut state);
true
}
Operand::Constant(box constant) => {
let ConstantKind::Val(value, ty) = constant.literal else { unreachable!() };
Expand All @@ -357,23 +360,34 @@ impl<'tcx> Analyzer<'tcx, '_> {
let code =
self.tcx.sess.source_map().span_to_snippet(span).unwrap();
assert_eq!(code, "BitfieldStruct");
true
} else if seg1.contains("{extern#") {
self.transfer_c_call(seg0, inputs, args, &mut state);
self.transfer_c_call(inputs, args, &mut state);
true
} else {
self.transfer_intra_call(
&HashSet::from_iter([local_def_id]),
&mut state,
);
true
}
} else {
self.transfer_rust_call(
(seg3, seg2, seg1, seg0),
inputs,
args,
destination,
&mut state,
);
)
}
}
};
if need_update {
let (l, l_deref) = AccPath::from_place(*destination, &state);
let suffixes = self.get_path_suffixes(&l, l_deref);
state
.gm()
.assign_with_suffixes(&l, l_deref, &OpVal::Other, &suffixes);
}
vec![(location, state)]
}
Expand All @@ -390,29 +404,51 @@ impl<'tcx> Analyzer<'tcx, '_> {
}
}

fn transfer_c_call(
&self,
_name: &str,
_inputs: &[Ty<'_>],
_args: &[Operand<'_>],
_state: &mut AbsMem,
) {
todo!()
fn transfer_c_call(&self, inputs: &[Ty<'_>], args: &[Operand<'_>], state: &mut AbsMem) {
let graph = state.gm();
for (ty, arg) in inputs.iter().zip(args) {
if ty.is_mutable_ptr() {
if let Operand::Copy(arg) | Operand::Move(arg) = arg {
for (local, depth) in self.find_may_aliases(arg.local) {
graph.invalidate_deref(local, depth, None);
}
}
}
}
}

fn transfer_rust_call(
&self,
name: (&str, &str, &str, &str),
inputs: &[Ty<'_>],
_args: &[Operand<'_>],
_state: &mut AbsMem,
) {
args: &[Operand<'_>],
dst: &Place<'_>,
state: &mut AbsMem,
) -> bool {
if inputs.iter().all(|t| t.is_primitive()) {
return;
return true;
}
let (d, d_deref) = AccPath::from_place(*dst, state);
assert!(!d_deref);
match name {
("", "option", _, "unwrap") => {}
_ => todo!("{:?}", name),
("", "option", _, "unwrap") | ("ptr", _, _, "is_null") => true,
("", "slice", _, "as_ptr" | "as_mut_ptr") => {
let (Operand::Copy(a) | Operand::Move(a)) = args[0] else { panic!() };
let (mut a, a_deref) = AccPath::from_place(a, state);
assert!(!a_deref);
a.projection.push(AccElem::Int(0));
state.gm().x_eq_ref_y(&d, &a, true);
false
}
("ptr", _, _, "offset") => {
let (Operand::Copy(ptr) | Operand::Move(ptr)) = args[0] else { panic!() };
let (ptr, ptr_deref) = AccPath::from_place(ptr, state);
assert!(!ptr_deref);
let idx = self.transfer_op(&args[1], state);
state.gm().x_eq_offset(&d, &ptr, idx);
false
}
_ => todo!("{:?} {:?}", self.local_def_id, name),
}
}
}
Expand Down
Loading

0 comments on commit da4c3d8

Please sign in to comment.