TypeGraph: Respect [[codegen.ignore]] config value

This commit is contained in:
Alastair Robertson 2023-06-01 09:09:15 -07:00 committed by Alastair Robertson
parent 91dc954d40
commit 62575a7c3e
9 changed files with 214 additions and 4 deletions

View File

@ -28,6 +28,7 @@
#include "type_graph/DrgnParser.h"
#include "type_graph/Flattener.h"
#include "type_graph/NameGen.h"
#include "type_graph/RemoveIgnored.h"
#include "type_graph/RemoveTopLevelPointer.h"
#include "type_graph/TopoSorter.h"
#include "type_graph/TypeGraph.h"
@ -420,6 +421,7 @@ bool CodeGen::generate(drgn_type* drgnType, std::string& code) {
pm.addPass(type_graph::Flattener::createPass());
pm.addPass(type_graph::TypeIdentifier::createPass());
}
pm.addPass(type_graph::RemoveIgnored::createPass(config_.membersToStub));
pm.addPass(type_graph::AddPadding::createPass());
pm.addPass(type_graph::NameGen::createPass());
pm.addPass(type_graph::AlignmentCalc::createPass());

View File

@ -19,12 +19,13 @@
#include <unordered_set>
#include "PassManager.h"
#include "TypeGraph.h"
#include "Types.h"
#include "Visitor.h"
namespace type_graph {
class TypeGraph;
/*
* AddPadding
*

View File

@ -7,6 +7,7 @@ add_library(type_graph
NameGen.cpp
PassManager.cpp
Printer.cpp
RemoveIgnored.cpp
RemoveTopLevelPointer.cpp
TopoSorter.cpp
TypeIdentifier.cpp

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "RemoveIgnored.h"
#include "TypeGraph.h"
namespace type_graph {
Pass RemoveIgnored::createPass(
const std::vector<std::pair<std::string, std::string>>& membersToIgnore) {
auto fn = [&membersToIgnore](TypeGraph& typeGraph) {
RemoveIgnored removeIgnored{typeGraph, membersToIgnore};
for (auto& type : typeGraph.rootTypes()) {
removeIgnored.visit(type);
}
};
return Pass("RemoveIgnored", fn);
}
void RemoveIgnored::visit(Type& type) {
if (visited_.count(&type) != 0)
return;
visited_.insert(&type);
type.accept(*this);
}
void RemoveIgnored::visit(Class& c) {
for (size_t i = 0; i < c.members.size(); i++) {
if (!ignoreMember(c.name(), c.members[i].name)) {
continue;
}
auto* primitive = typeGraph_.make_type<Primitive>(Primitive::Kind::Int8);
auto* paddingArray =
typeGraph_.make_type<Array>(primitive, c.members[i].type->size());
c.members[i] = Member{paddingArray, c.members[i].name, c.members[i].offset};
}
}
bool RemoveIgnored::ignoreMember(const std::string& typeName,
const std::string& memberName) const {
for (const auto& [ignoredType, ignoredMember] : membersToIgnore_) {
if (typeName == ignoredType && memberName == ignoredMember) {
return true;
}
}
return false;
}
} // namespace type_graph

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <unordered_set>
#include "PassManager.h"
#include "Types.h"
#include "Visitor.h"
namespace type_graph {
class TypeGraph;
/*
* RemoveIgnored
*
* Remove types and members as requested by the [[codegen.ignore]] section in
* the OI config.
*/
class RemoveIgnored : public RecursiveVisitor {
public:
static Pass createPass(
const std::vector<std::pair<std::string, std::string>>& membersToIgnore);
RemoveIgnored(
TypeGraph& typeGraph,
const std::vector<std::pair<std::string, std::string>>& membersToIgnore)
: typeGraph_(typeGraph), membersToIgnore_(membersToIgnore) {
}
void visit(Type& type) override;
void visit(Class& c) override;
private:
bool ignoreMember(const std::string& typeName,
const std::string& memberName) const;
std::unordered_set<Type*> visited_;
TypeGraph& typeGraph_;
const std::vector<std::pair<std::string, std::string>>& membersToIgnore_;
};
} // namespace type_graph

View File

@ -16,7 +16,6 @@
#pragma once
#include <unordered_set>
#include <vector>
#include "PassManager.h"
#include "Types.h"

View File

@ -54,6 +54,7 @@ add_executable(test_type_graph
test_drgn_parser.cpp
test_flattener.cpp
test_name_gen.cpp
test_remove_ignored.cpp
test_remove_top_level_pointer.cpp
test_topo_sorter.cpp
test_type_identifier.cpp

View File

@ -1,9 +1,7 @@
#include <gtest/gtest.h>
#include "oi/type_graph/AddPadding.h"
#include "oi/type_graph/PassManager.h"
#include "oi/type_graph/Printer.h"
#include "oi/type_graph/TypeGraph.h"
#include "oi/type_graph/Types.h"
#include "test/type_graph_utils.h"

View File

@ -0,0 +1,87 @@
#include <gtest/gtest.h>
#include "oi/type_graph/Printer.h"
#include "oi/type_graph/RemoveIgnored.h"
#include "oi/type_graph/Types.h"
#include "test/type_graph_utils.h"
using namespace type_graph;
TEST(RemoveIgnoredTest, Match) {
auto classB = Class{Class::Kind::Class, "ClassB", 4};
auto classA = Class{Class::Kind::Class, "ClassA", 12};
classA.members.push_back(Member(&classB, "a", 0));
classA.members.push_back(Member(&classB, "b", 4));
classA.members.push_back(Member(&classB, "c", 8));
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "b"},
};
test(RemoveIgnored::createPass(membersToIgnore), {classA}, R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
[1] Class: ClassB (size: 4)
Member: b (offset: 4)
[1]
Member: c (offset: 8)
[1]
)",
R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
[1] Class: ClassB (size: 4)
Member: b (offset: 4)
[2] Array: (length: 4)
Primitive: int8_t
Member: c (offset: 8)
[1]
)");
}
TEST(RemoveIgnoredTest, TypeMatchMemberMiss) {
auto classB = Class{Class::Kind::Class, "ClassB", 4};
auto classA = Class{Class::Kind::Class, "ClassA", 12};
classA.members.push_back(Member(&classB, "a", 0));
classA.members.push_back(Member(&classB, "b", 4));
classA.members.push_back(Member(&classB, "c", 8));
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassA", "x"},
};
test(RemoveIgnored::createPass(membersToIgnore), {classA}, R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
[1] Class: ClassB (size: 4)
Member: b (offset: 4)
[1]
Member: c (offset: 8)
[1]
)");
}
TEST(RemoveIgnoredTest, MemberMatchWrongType) {
auto classB = Class{Class::Kind::Class, "ClassB", 4};
auto classA = Class{Class::Kind::Class, "ClassA", 12};
classA.members.push_back(Member(&classB, "a", 0));
classA.members.push_back(Member(&classB, "b", 4));
classA.members.push_back(Member(&classB, "c", 8));
const std::vector<std::pair<std::string, std::string>>& membersToIgnore = {
{"ClassB", "b"},
};
test(RemoveIgnored::createPass(membersToIgnore), {classA}, R"(
[0] Class: ClassA (size: 12)
Member: a (offset: 0)
[1] Class: ClassB (size: 4)
Member: b (offset: 4)
[1]
Member: c (offset: 8)
[1]
)");
}