Skip to content

Commit

Permalink
prune_unused_decls: Rename to unwanted
Browse files Browse the repository at this point in the history
The criterion for whether it is desired for an item to be transpiled
have been broadened to possibly preserve unused functions as well. Thus,
the "unused" name part has been replaced with "unwanted", which
traditionally means unused but, in other configurations, can mean
"unused but not a function" now as well.
  • Loading branch information
chrysn committed Sep 4, 2020
1 parent dec5544 commit b19396a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 20 deletions.
40 changes: 21 additions & 19 deletions c2rust-transpile/src/c_ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,20 +519,22 @@ impl TypedAstContext {
}
}

pub fn prune_unused_decls(&mut self, preserve_unused_functions: bool) {
pub fn prune_unwanted_decls(&mut self, want_unused_functions: bool) {
// Starting from a set of root declarations, walk each one to find declarations it
// depends on. Then walk each of those, recursively.

// Declarations we still need to walk. Everything in here is also in `used`.
// Declarations we still need to walk. Everything in here is also in `wanted`.
let mut to_walk: Vec<CDeclId> = Vec::new();
// Declarations accessible from a root.
let mut used: HashSet<CDeclId> = HashSet::new();
let mut wanted: HashSet<CDeclId> = HashSet::new();

// Mark all the roots as used. Roots are all top-level functions and variables that might
// Mark all the roots as wanted. Roots are all top-level functions and variables that might
// be visible from another compilation unit.
//
// In addition, mark any other (unused) function wanted if configured.
for &decl_id in &self.c_decls_top {
let decl = self.index(decl_id);
let is_used = match decl.kind {
let is_wanted = match decl.kind {
CDeclKind::Function {
body: Some(_),
is_global: true,
Expand All @@ -545,7 +547,7 @@ impl TypedAstContext {
CDeclKind::Function {
body: Some(_),
..
} if preserve_unused_functions => true,
} if want_unused_functions => true,
CDeclKind::Variable {
is_defn: true,
is_externally_visible: true,
Expand All @@ -556,14 +558,14 @@ impl TypedAstContext {
_ => false,
};

if is_used {
if is_wanted {
to_walk.push(decl_id);
used.insert(decl_id);
wanted.insert(decl_id);
}
}

// Add all referenced macros to the set of used decls
// used.extend(self.macro_expansions.values().flatten());
// Add all referenced macros to the set of wanted decls
// wanted.extend(self.macro_expansions.values().flatten());

while let Some(enclosing_decl_id) = to_walk.pop() {
for some_id in DFNodes::new(self, SomeId::Decl(enclosing_decl_id)) {
Expand All @@ -572,13 +574,13 @@ impl TypedAstContext {
match self.c_types[&type_id].kind {
// This is a reference to a previously declared type. If we look
// through it we should(?) get something that looks like a declaration,
// which we can mark as used.
// which we can mark as wanted.
CTypeKind::Elaborated(decl_type_id) => {
let decl_id = self.c_types[&decl_type_id]
.kind
.as_decl_or_typedef()
.expect("target of CTypeKind::Elaborated isn't a decl?");
if used.insert(decl_id) {
if wanted.insert(decl_id) {
to_walk.push(decl_id);
}
}
Expand All @@ -593,20 +595,20 @@ impl TypedAstContext {
let expr = self.index(expr_id);
if let Some(macs) = self.macro_invocations.get(&expr_id) {
for mac_id in macs {
if used.insert(*mac_id) {
if wanted.insert(*mac_id) {
to_walk.push(*mac_id);
}
}
}
if let CExprKind::DeclRef(_, decl_id, _) = &expr.kind {
if used.insert(*decl_id) {
if wanted.insert(*decl_id) {
to_walk.push(*decl_id);
}
}
}

SomeId::Decl(decl_id) => {
if used.insert(decl_id) {
if wanted.insert(decl_id) {
to_walk.push(decl_id);
}

Expand All @@ -615,7 +617,7 @@ impl TypedAstContext {
// Special case for enums. The enum constant is used, so the whole
// enum is also used.
let parent_id = self.parents[&decl_id];
if used.insert(parent_id) {
if wanted.insert(parent_id) {
to_walk.push(parent_id);
}
}
Expand All @@ -632,17 +634,17 @@ impl TypedAstContext {

// Unset c_main if we are not retaining its declaration
if let Some(main_id) = self.c_main {
if !used.contains(&main_id) {
if !wanted.contains(&main_id) {
self.c_main = None;
}
}

// Prune any declaration that isn't considered live
self.c_decls
.retain(|&decl_id, _decl| used.contains(&decl_id));
.retain(|&decl_id, _decl| wanted.contains(&decl_id));

// Prune top declarations that are not considered live
self.c_decls_top.retain(|x| used.contains(x));
self.c_decls_top.retain(|x| wanted.contains(x));
}

pub fn sort_top_decls(&mut self) {
Expand Down
2 changes: 1 addition & 1 deletion c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ pub fn translate(

// Headers often pull in declarations that are unused;
// we simplify the translator output by omitting those.
t.ast_context.prune_unused_decls(tcfg.preserve_unused_functions);
t.ast_context.prune_unwanted_decls(tcfg.preserve_unused_functions);

enum Name<'a> {
VarName(&'a str),
Expand Down

0 comments on commit b19396a

Please sign in to comment.