Skip to content

Commit

Permalink
fix #994
Browse files Browse the repository at this point in the history
  • Loading branch information
aneksteind committed Aug 2, 2023
1 parent 2f3a637 commit f730761
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 55 deletions.
63 changes: 56 additions & 7 deletions c2rust-analyze/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,10 @@ fn fn_origin_args_params<'tcx>(
FnOriginMap { fn_info }
}

fn construct_adt_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> AdtMetadataTable {
fn construct_adt_metadata<'tcx>(
tcx: TyCtxt<'tcx>,
foreign_mentioned_tys: &HashSet<DefId>,
) -> AdtMetadataTable<'tcx> {
let struct_dids: Vec<_> = tcx
.hir_crate_items(())
.definitions()
Expand Down Expand Up @@ -618,10 +621,12 @@ fn construct_adt_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> AdtMetadataTable {
{
for adt_field_lifetime_param in adt_field_metadata.lifetime_params.iter() {
adt_metadata_table.table.entry(*struct_did).and_modify(|adt| {
if let OriginParam::Hypothetical(h) = adt_field_lifetime_param {
eprintln!("\t\t\tbubbling {adt_field:?} origin {adt_field_lifetime_param:?} up into {adt_def:?} origins");
field_origin_args.insert(OriginArg::Hypothetical(*h));
adt.lifetime_params.insert(*adt_field_lifetime_param);
if !foreign_mentioned_tys.contains(&adt_field.did()) {
if let OriginParam::Hypothetical(h) = adt_field_lifetime_param {
eprintln!("\t\t\tbubbling {adt_field:?} origin {adt_field_lifetime_param:?} up into {adt_def:?} origins");
field_origin_args.insert(OriginArg::Hypothetical(*h));
adt.lifetime_params.insert(*adt_field_lifetime_param);
}
}
});
}
Expand Down Expand Up @@ -662,9 +667,53 @@ fn construct_adt_metadata<'tcx>(tcx: TyCtxt<'tcx>) -> AdtMetadataTable {
adt_metadata_table
}

fn foreign_mentioned_tys(tcx: TyCtxt) -> HashSet<DefId> {
let mut foreign_mentioned_tys = HashSet::new();
for ty in tcx
.hir_crate_items(())
.foreign_items()
.map(|item| item.def_id.to_def_id())
.filter_map(|did| match tcx.def_kind(did) {
DefKind::Fn | DefKind::AssocFn => Some(tcx.mk_fn_ptr(tcx.fn_sig(did))),
DefKind::Static(_) => Some(tcx.type_of(did)),
_ => None,
})
{
walk_adts(tcx, ty, &mut |did| foreign_mentioned_tys.insert(did));
}
foreign_mentioned_tys
}

/// Walks the type `ty` and applies a function `f` to it if it's an ADT
/// `f` gets applied recursively to `ty`'s generic types and fields (if applicable)
/// If `f` returns false, the fields of the ADT are not recursed into.
/// Otherwise, the function will naturally terminate given that the generic types
/// of a type are finite in length.
/// We only look for ADTs rather than other FFI-crossing types because ADTs
/// are the only nominal ones, which are the ones that we may rewrite.
fn walk_adts<'tcx, F>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, f: &mut F)
where
F: FnMut(DefId) -> bool,
{
for arg in ty.walk() {
if let GenericArgKind::Type(ty) = arg.unpack() {
if let TyKind::Adt(adt_def, _) = ty.kind() {
if !f(adt_def.did()) {
continue;
}
for field in adt_def.all_fields() {
let field_ty = tcx.type_of(field.did);
walk_adts(tcx, field_ty, f);
}
}
}
}
}

impl<'tcx> GlobalAnalysisCtxt<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> GlobalAnalysisCtxt<'tcx> {
let adt_metadata = construct_adt_metadata(tcx);
let foreign_mentioned_tys = foreign_mentioned_tys(tcx);
let adt_metadata = construct_adt_metadata(tcx, &foreign_mentioned_tys);
let fn_origins = fn_origin_args_params(tcx, &adt_metadata);
GlobalAnalysisCtxt {
tcx,
Expand All @@ -681,7 +730,7 @@ impl<'tcx> GlobalAnalysisCtxt<'tcx> {
addr_of_static: HashMap::new(),
adt_metadata,
fn_origins,
foreign_mentioned_tys: HashSet::new(),
foreign_mentioned_tys,
}
}

Expand Down
49 changes: 1 addition & 48 deletions c2rust-analyze/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use rustc_middle::mir::{
AggregateKind, BindingForm, Body, Constant, Local, LocalDecl, LocalInfo, LocalKind, Location,
Operand, Rvalue, StatementKind,
};
use rustc_middle::ty::{GenericArgKind, Ty, TyCtxt, TyKind, WithOptConstParam};
use rustc_middle::ty::{Ty, TyCtxt, TyKind, WithOptConstParam};
use rustc_span::Span;
use std::collections::{HashMap, HashSet};
use std::env;
Expand Down Expand Up @@ -282,49 +282,6 @@ fn update_pointer_info<'tcx>(acx: &mut AnalysisCtxt<'_, 'tcx>, mir: &Body<'tcx>)
}
}

fn foreign_mentioned_tys(tcx: TyCtxt) -> HashSet<DefId> {
let mut foreign_mentioned_tys = HashSet::new();
for ty in tcx
.hir_crate_items(())
.foreign_items()
.map(|item| item.def_id.to_def_id())
.filter_map(|did| match tcx.def_kind(did) {
DefKind::Fn | DefKind::AssocFn => Some(tcx.mk_fn_ptr(tcx.fn_sig(did))),
DefKind::Static(_) => Some(tcx.type_of(did)),
_ => None,
})
{
walk_adts(tcx, ty, &mut |did| foreign_mentioned_tys.insert(did));
}
foreign_mentioned_tys
}

/// Walks the type `ty` and applies a function `f` to it if it's an ADT
/// `f` gets applied recursively to `ty`'s generic types and fields (if applicable)
/// If `f` returns false, the fields of the ADT are not recursed into.
/// Otherwise, the function will naturally terminate given that the generic types
/// of a type are finite in length.
/// We only look for ADTs rather than other FFI-crossing types because ADTs
/// are the only nominal ones, which are the ones that we may rewrite.
fn walk_adts<'tcx, F>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, f: &mut F)
where
F: FnMut(DefId) -> bool,
{
for arg in ty.walk() {
if let GenericArgKind::Type(ty) = arg.unpack() {
if let TyKind::Adt(adt_def, _) = ty.kind() {
if !f(adt_def.did()) {
continue;
}
for field in adt_def.all_fields() {
let field_ty = tcx.type_of(field.did);
walk_adts(tcx, field_ty, f);
}
}
}
}
}

fn gather_foreign_sigs<'tcx>(gacx: &mut GlobalAnalysisCtxt<'tcx>, tcx: TyCtxt<'tcx>) {
for did in tcx
.hir_crate_items(())
Expand Down Expand Up @@ -587,10 +544,6 @@ fn run(tcx: TyCtxt) {
|| info.contains(PointerInfo::NOT_TEMPORARY_REF))
}

// track all types mentioned in extern blocks, we
// don't want to rewrite those
gacx.foreign_mentioned_tys = foreign_mentioned_tys(tcx);

let mut gasn =
GlobalAssignment::new(gacx.num_pointers(), PermissionSet::UNIQUE, FlagSet::empty());
for (ptr, &info) in gacx.ptr_info().iter() {
Expand Down
21 changes: 21 additions & 0 deletions c2rust-analyze/tests/filecheck/foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,24 @@ extern "C" {
// CHECK-DAG: fn f(bin: *mut Bin)
fn f(bin: *mut Bin);
}

extern "C" {
// CHECK-DAG: fn epoll_wait(events: *mut epoll_event);
fn epoll_wait(events: *mut epoll_event);
}

// CHECK-DAG: pub struct fdevents<'h7> {
pub struct fdevents {
// CHECK-DAG: pub epoll_events: &'h7 (epoll_event),
pub epoll_events: *mut epoll_event,
}

// CHECK-DAG: pub struct epoll_event {
pub struct epoll_event {
// CHECK-DAG: pub ptr: *mut u8,
pub ptr: *mut u8,
}

// CHECK-DAG: fn events<'h0>(f: fdevents<'h0>) {}
fn events(f: fdevents) {}

0 comments on commit f730761

Please sign in to comment.