Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rs_bindings_from_cc/collect_namespaces.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ NamespacesHierarchy CollectNamespaces(const IR& ir) {
}

NamespaceTrie trie(ir.current_target, id_to_namespace);
for (auto namespace_id : ir.top_level_item_ids.at(ir.current_target)) {
for (auto namespace_id : ir.top_level_item_ids(ir.current_target)) {
if (id_to_namespace.count(namespace_id) == 0) {
continue;
}
Expand Down
3 changes: 3 additions & 0 deletions rs_bindings_from_cc/decl_importer.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class Invocation {
// The main output of the import process
IR ir_;

// Transient map of top level items used to build the tree.
absl::flat_hash_map<BazelLabel, std::vector<ItemId>> top_level_item_ids_;

// Returns whether to record extra location information for Kythe annotations.
bool kythe_annotations() const { return kythe_annotations_; }

Expand Down
14 changes: 7 additions & 7 deletions rs_bindings_from_cc/importer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -870,20 +870,20 @@ void Importer::Import(clang::TranslationUnitDecl* translation_unit_decl) {
for (auto& ordered_item : ordered_items) {
invocation_.ir_.items.push_back(ordered_item.second);
}
invocation_.ir_.top_level_item_ids =
invocation_.top_level_item_ids_ =
GetTopLevelItemIdsInSourceOrder(translation_unit_decl);

// TODO(b/257302656): Consider placing the generated template instantiations
// into a separate namespace (maybe `crubit::instantiated_templates` ?).
llvm::copy(GetOrderedItemIdsOfTemplateInstantiations(),
std::back_inserter(
invocation_.ir_.top_level_item_ids[invocation_.target_]));
llvm::copy(
GetOrderedItemIdsOfTemplateInstantiations(),
std::back_inserter(invocation_.top_level_item_ids_[invocation_.target_]));

// Remove any unsupported alien (to the current target) items.
// IsUnsupportedAndAlien only returns true for items outside the current
// target that are unsupported. You have to run it only if label is not equal
// to the current target; you can skip the current target.
for (auto& [label, item_ids] : invocation_.ir_.top_level_item_ids) {
for (auto& [label, item_ids] : invocation_.top_level_item_ids_) {
if (label == invocation_.target_) continue;
item_ids.erase(std::remove_if(item_ids.begin(), item_ids.end(),
[&](ItemId item_id) {
Expand Down Expand Up @@ -967,10 +967,10 @@ std::optional<IR::Item> Importer::GetDeclItem(clang::Decl* decl) {

// Logic for `ClassTemplateSpecializationDecl`: insert them into
// `class_template_instantiations_`, so that they will get included in
// IR::top_level_item_ids.
// the top-level items.
// Note: The 'gating' logic here needs to be consistent with the 'gating'
// logic in `GetItemIdsInSourceOrder`, or else the class template
// instantiation decl ID is inserted into the IR::top_level_item_ids but does
// instantiation decl ID is inserted into the top-level items but does
// not have its corresponding IR item, resulting in lookup failures (crashes)
// when generating bindings.
if (result.has_value()) {
Expand Down
6 changes: 3 additions & 3 deletions rs_bindings_from_cc/importer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ TEST(ImporterTest, TopLevelItemIds) {
ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));

std::vector<IR::Item> items;
for (const auto& id : ir.top_level_item_ids.at(ir.current_target)) {
for (const auto& id : ir.top_level_item_ids(ir.current_target)) {
auto item = FindItemById(ir, id);
ASSERT_TRUE(item.has_value());
items.push_back(*item);
Expand Down Expand Up @@ -956,7 +956,7 @@ TEST(ImporterTest, ForwardDeclarationAndDefinition) {
ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));

std::vector<IR::Item> items;
for (const auto& id : ir.top_level_item_ids.at(ir.current_target)) {
for (const auto& id : ir.top_level_item_ids(ir.current_target)) {
auto item = FindItemById(ir, id);
items.push_back(*item);
}
Expand All @@ -976,7 +976,7 @@ TEST(ImporterTest, DuplicateForwardDeclarations) {
ASSERT_OK_AND_ASSIGN(IR ir, IrFromCc({file}));

std::vector<IR::Item> items;
for (const auto& id : ir.top_level_item_ids.at(ir.current_target)) {
for (const auto& id : ir.top_level_item_ids(ir.current_target)) {
auto item = FindItemById(ir, id);
items.push_back(*item);
}
Expand Down
31 changes: 18 additions & 13 deletions rs_bindings_from_cc/ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1720,16 +1720,6 @@ flat_proto::Namespace Namespace::ToFlatProto() const {
}

llvm::json::Value IR::ToJson() const {
llvm::json::Object top_level_item_ids_json;
for (const auto& [target, item_ids] : top_level_item_ids) {
std::vector<llvm::json::Value> item_ids_json;
item_ids_json.reserve(item_ids.size());
for (const auto& item_id : item_ids) {
item_ids_json.push_back(item_id.value());
}
top_level_item_ids_json[target.value()] = std::move(item_ids_json);
}

llvm::json::Object features_json;
for (const auto& [target, features] : crubit_features) {
std::vector<std::string> sorted_features(features.begin(), features.end());
Expand Down Expand Up @@ -1758,8 +1748,6 @@ llvm::json::Value IR::ToJson() const {
llvm::json::Object result{
{"public_headers", public_headers},
{"current_target", current_target},
{"items", llvm::json::Array{}},
{"top_level_item_ids", std::move(top_level_item_ids_json)},
{"top_level_items", std::move(top_level_items_json)},
{"crubit_features", std::move(features_json)},
{"reexported_namespaces", reexported_namespaces},
Expand Down Expand Up @@ -1848,10 +1836,27 @@ void SetMustBindItem(IR::Item& item) {
item.as_variant());
}

ItemId Item::id() const {
return std::visit([](const auto& val) { return val.id; }, as_variant());
}

std::vector<ItemId> IR::top_level_item_ids(const BazelLabel& target) const {
std::vector<ItemId> ids;
auto it = top_level_items.find(target);
if (it != top_level_items.end()) {
ids.reserve(it->second.size());
for (const auto& item : it->second) {
ids.push_back(item->id());
}
}
return ids;
}

// Produces a nested IR which inlines child items on namespaces and records to
// replace the legacy representation (an array of item IDs).
// See crubit.rs-better-ir for more context.
void IR::BuildTree() {
void IR::BuildTree(
absl::flat_hash_map<BazelLabel, std::vector<ItemId>> top_level_item_ids) {
top_level_items.clear();
absl::flat_hash_map<ItemId, std::shared_ptr<Item>> item_map;
item_map.reserve(items.size());
Expand Down
11 changes: 7 additions & 4 deletions rs_bindings_from_cc/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,6 @@ struct Record {
// Set if this is [[deprecated]]. If no message was given, will be "".
std::optional<std::string> deprecated;

// TODO(b/523265360): Remove child_item_ids.
std::vector<std::shared_ptr<Item>> children;
};

Expand Down Expand Up @@ -1084,7 +1083,6 @@ struct Namespace {
std::optional<std::string> deprecated;
std::optional<std::string> doc_comment;

// TODO(b/523265360): Remove child_item_ids.
std::vector<std::shared_ptr<Item>> children;
};

Expand Down Expand Up @@ -1148,6 +1146,8 @@ struct Item

const Base& as_variant() const { return *this; }
Base& as_variant() { return *this; }

ItemId id() const;
};

// A complete intermediate representation of bindings for publicly accessible
Expand Down Expand Up @@ -1188,12 +1188,15 @@ struct IR {
BazelLabel current_target;

using Item = ::crubit::Item;
// TODO(b/530340081): Should refactor this out to stage flat items elsewhere.
std::vector<Item> items;
absl::flat_hash_map<BazelLabel, std::vector<ItemId>> top_level_item_ids;
absl::flat_hash_map<BazelLabel, std::vector<std::shared_ptr<Item>>>
top_level_items;

void BuildTree();
std::vector<ItemId> top_level_item_ids(const BazelLabel& target) const;

void BuildTree(
absl::flat_hash_map<BazelLabel, std::vector<ItemId>> top_level_item_ids);
// Empty string signals that the bindings should be generated in the crate
// root. This is the default state.
//
Expand Down
33 changes: 20 additions & 13 deletions rs_bindings_from_cc/ir_from_cc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ struct UseModFromSrc {
};

absl::StatusOr<std::vector<UseModFromSrc>> CreateUseModsFromExtraRustSrcs(
IR& ir, absl::Span<const std::string> extra_rs_srcs) {
IR& ir, absl::Span<const std::string> extra_rs_srcs,
const absl::flat_hash_map<BazelLabel, std::vector<ItemId>>&
top_level_item_ids) {
std::vector<Namespace*> all_namespaces = ir.get_items_if<Namespace>();
absl::flat_hash_map<std::string, ItemId> name_to_top_level_ns;
absl::flat_hash_set<ItemId> top_level_item_id_set =
absl::flat_hash_set<ItemId>(
ir.top_level_item_ids[ir.current_target].begin(),
ir.top_level_item_ids[ir.current_target].end());
absl::flat_hash_set<ItemId> top_level_item_id_set;
if (auto it = top_level_item_ids.find(ir.current_target);
it != top_level_item_ids.end()) {
top_level_item_id_set.insert(it->second.begin(), it->second.end());
}
absl::flat_hash_map<ItemId, Namespace*> id_to_namespace;
for (auto ns : all_namespaces) {
if (ns->owning_target != ir.current_target) {
Expand Down Expand Up @@ -143,22 +146,24 @@ absl::StatusOr<std::vector<UseModFromSrc>> CreateUseModsFromExtraRustSrcs(
}

// Convert the extra_rs_srcs into UseMod items and add them to the IR.
absl::Status AddUseModToIr(IR& ir,
absl::Span<const std::string> extra_rs_srcs) {
absl::Status AddUseModToIr(
IR& ir, absl::Span<const std::string> extra_rs_srcs,
absl::flat_hash_map<BazelLabel, std::vector<ItemId>>& top_level_item_ids) {
// We have to reserve the space for the new items here because below we store
// pointers to the Namespace items in the `UseModFromSrc`. If we reserve the
// space after creating the `UseModFromSrc`, the pointers might be
// invalidated.
ir.items.reserve(ir.items.size() + extra_rs_srcs.size());
CRUBIT_ASSIGN_OR_RETURN(std::vector<UseModFromSrc> use_mods,
CreateUseModsFromExtraRustSrcs(ir, extra_rs_srcs));
CRUBIT_ASSIGN_OR_RETURN(
std::vector<UseModFromSrc> use_mods,
CreateUseModsFromExtraRustSrcs(ir, extra_rs_srcs, top_level_item_ids));
for (auto& use_mod_from_src : use_mods) {
ir.items.push_back(std::move(use_mod_from_src.use_mod));
if (use_mod_from_src.enclosing_namespace.has_value()) {
use_mod_from_src.enclosing_namespace.value()->child_item_ids.push_back(
use_mod_from_src.use_mod.id);
} else {
ir.top_level_item_ids[ir.current_target].push_back(
top_level_item_ids[ir.current_target].push_back(
use_mod_from_src.use_mod.id);
}
}
Expand Down Expand Up @@ -235,12 +240,14 @@ absl::StatusOr<IR> IrFromCc(IrFromCcOptions options) {
"Could not compile header contents");
}

if (absl::Status status =
AddUseModToIr(invocation.ir_, options.extra_rs_srcs);
absl::flat_hash_map<BazelLabel, std::vector<ItemId>> top_level_item_ids =
invocation.top_level_item_ids_;
if (absl::Status status = AddUseModToIr(invocation.ir_, options.extra_rs_srcs,
top_level_item_ids);
!status.ok()) {
return status;
}
invocation.ir_.BuildTree();
invocation.ir_.BuildTree(std::move(top_level_item_ids));
invocation.ir_.reexported_namespaces =
std::vector<std::string>(options.reexported_namespaces.begin(),
options.reexported_namespaces.end());
Expand Down