mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
TypeGraph: Add "--tree-builder-v2" flag
This will eventually be used to enable running with Tree Builder v2. For now, when it is disabled it puts CodeGen v2 into compatibility mode, disabling features which weren't present in CodeGen v1 so that its output can be understood by Tree Builder v1.
This commit is contained in:
parent
e1b16a3d7e
commit
3ec81aaa5f
@ -778,7 +778,7 @@ void CodeGen::transform(type_graph::TypeGraph& typeGraph) {
|
||||
type_graph::TypeIdentifier::createPass(config_.passThroughTypes));
|
||||
}
|
||||
pm.addPass(type_graph::RemoveIgnored::createPass(config_.membersToStub));
|
||||
pm.addPass(type_graph::AddPadding::createPass());
|
||||
pm.addPass(type_graph::AddPadding::createPass(config_.features));
|
||||
pm.addPass(type_graph::NameGen::createPass());
|
||||
pm.addPass(type_graph::AlignmentCalc::createPass());
|
||||
pm.addPass(type_graph::RemoveTopLevelPointer::createPass());
|
||||
|
@ -33,9 +33,11 @@ std::string_view featureHelp(Feature f) {
|
||||
case Feature::CaptureThriftIsset:
|
||||
return "Capture isset data for Thrift object.";
|
||||
case Feature::TypeGraph:
|
||||
return "Use Type Graph for code generation (CodeGen V2).";
|
||||
return "Use Type Graph for code generation (CodeGen v2).";
|
||||
case Feature::TypedDataSegment:
|
||||
return "Use Typed Data Segment in generated code.";
|
||||
case Feature::TreeBuilderV2:
|
||||
return "Use Tree Builder v2 for reading the data segment";
|
||||
case Feature::GenJitDebug:
|
||||
return "Generate debug information for the JIT object.";
|
||||
case Feature::JitLogging:
|
||||
|
@ -28,6 +28,7 @@
|
||||
X(CaptureThriftIsset, "capture-thrift-isset") \
|
||||
X(TypeGraph, "type-graph") \
|
||||
X(TypedDataSegment, "typed-data-segment") \
|
||||
X(TreeBuilderV2, "tree-builder-v2") \
|
||||
X(GenJitDebug, "gen-jit-debug") \
|
||||
X(JitLogging, "jit-logging") \
|
||||
X(JitTiming, "jit-timing") \
|
||||
|
@ -17,16 +17,20 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Flattener.h"
|
||||
#include "TypeGraph.h"
|
||||
|
||||
template <typename T>
|
||||
using ref = std::reference_wrapper<T>;
|
||||
|
||||
using ObjectIntrospection::Feature;
|
||||
using ObjectIntrospection::FeatureSet;
|
||||
|
||||
namespace type_graph {
|
||||
|
||||
Pass AddPadding::createPass() {
|
||||
auto fn = [](TypeGraph& typeGraph) {
|
||||
AddPadding pass(typeGraph);
|
||||
Pass AddPadding::createPass(FeatureSet features) {
|
||||
auto fn = [features](TypeGraph& typeGraph) {
|
||||
AddPadding pass(typeGraph, features);
|
||||
for (auto& type : typeGraph.rootTypes()) {
|
||||
pass.visit(type);
|
||||
}
|
||||
@ -67,6 +71,19 @@ void AddPadding::visit(Class& c) {
|
||||
if (i >= 1) {
|
||||
addPadding(c.members[i - 1], c.members[i].bitOffset, paddedMembers);
|
||||
}
|
||||
|
||||
if (!features_[Feature::TreeBuilderV2] &&
|
||||
c.members[i].name.starts_with(Flattener::ParentPrefix)) {
|
||||
// CodeGen v1 can't handle parent containers. It replaces them with
|
||||
// padding.
|
||||
auto& primitive = typeGraph_.makeType<Primitive>(Primitive::Kind::Int8);
|
||||
auto& paddingArray =
|
||||
typeGraph_.makeType<Array>(primitive, c.members[i].type().size());
|
||||
paddedMembers.emplace_back(paddingArray, MemberPrefix,
|
||||
c.members[i].bitOffset);
|
||||
continue;
|
||||
}
|
||||
|
||||
paddedMembers.push_back(c.members[i]);
|
||||
}
|
||||
|
||||
|
@ -15,12 +15,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "PassManager.h"
|
||||
#include "Types.h"
|
||||
#include "Visitor.h"
|
||||
#include "oi/Features.h"
|
||||
|
||||
namespace type_graph {
|
||||
|
||||
@ -35,9 +36,11 @@ class TypeGraph;
|
||||
*/
|
||||
class AddPadding final : public RecursiveVisitor {
|
||||
public:
|
||||
static Pass createPass();
|
||||
static Pass createPass(ObjectIntrospection::FeatureSet features);
|
||||
|
||||
explicit AddPadding(TypeGraph& typeGraph) : typeGraph_(typeGraph) {
|
||||
explicit AddPadding(TypeGraph& typeGraph,
|
||||
ObjectIntrospection::FeatureSet features)
|
||||
: typeGraph_(typeGraph), features_(features) {
|
||||
}
|
||||
|
||||
using RecursiveVisitor::visit;
|
||||
@ -50,6 +53,7 @@ class AddPadding final : public RecursiveVisitor {
|
||||
private:
|
||||
std::unordered_set<Type*> visited_;
|
||||
TypeGraph& typeGraph_;
|
||||
ObjectIntrospection::FeatureSet features_;
|
||||
|
||||
void addPadding(const Member& prevMember,
|
||||
uint64_t paddingEndBits,
|
||||
|
@ -71,7 +71,7 @@ void flattenParent(const Parent& parent,
|
||||
} else if (Container* parentContainer =
|
||||
dynamic_cast<Container*>(&parentType)) {
|
||||
// Create a new member to represent this parent container
|
||||
flattenedMembers.emplace_back(*parentContainer, "__parent",
|
||||
flattenedMembers.emplace_back(*parentContainer, Flattener::ParentPrefix,
|
||||
parent.bitOffset);
|
||||
} else {
|
||||
throw std::runtime_error("Invalid type for parent");
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
@ -42,6 +43,8 @@ class Flattener : public RecursiveVisitor {
|
||||
void visit(Class& c) override;
|
||||
void visit(Container& c) override;
|
||||
|
||||
static const inline std::string ParentPrefix = "__oi_parent";
|
||||
|
||||
private:
|
||||
std::unordered_set<Type*> visited_;
|
||||
std::vector<Member> flattened_members_;
|
||||
|
@ -5,6 +5,17 @@
|
||||
#include "test/type_graph_utils.h"
|
||||
|
||||
using namespace type_graph;
|
||||
using ObjectIntrospection::Feature;
|
||||
using ObjectIntrospection::FeatureSet;
|
||||
|
||||
namespace {
|
||||
void test(std::vector<std::reference_wrapper<type_graph::Type>> rootTypes,
|
||||
std::string_view expectedAfter) {
|
||||
FeatureSet features;
|
||||
features[Feature::TreeBuilderV2] = true;
|
||||
::test(AddPadding::createPass({}), rootTypes, expectedAfter);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(AddPaddingTest, BetweenMembers) {
|
||||
auto myclass = Class{0, Class::Kind::Class, "MyClass", 16};
|
||||
@ -13,7 +24,7 @@ TEST(AddPaddingTest, BetweenMembers) {
|
||||
myclass.members.push_back(Member{myint8, "n1", 0});
|
||||
myclass.members.push_back(Member{myint64, "n2", 8 * 8});
|
||||
|
||||
test(AddPadding::createPass(), {myclass}, R"(
|
||||
test({myclass}, R"(
|
||||
[0] Class: MyClass (size: 16)
|
||||
Member: n1 (offset: 0)
|
||||
Primitive: int8_t
|
||||
@ -32,7 +43,7 @@ TEST(AddPaddingTest, AtEnd) {
|
||||
myclass.members.push_back(Member{myint64, "n1", 0});
|
||||
myclass.members.push_back(Member{myint8, "n2", 8 * 8});
|
||||
|
||||
test(AddPadding::createPass(), {myclass}, R"(
|
||||
test({myclass}, R"(
|
||||
[0] Struct: MyStruct (size: 16)
|
||||
Member: n1 (offset: 0)
|
||||
Primitive: int64_t
|
||||
@ -51,7 +62,7 @@ TEST(AddPaddingTest, UnionNotPadded) {
|
||||
myclass.members.push_back(Member{myint64, "n1", 0});
|
||||
myclass.members.push_back(Member{myint8, "n2", 0});
|
||||
|
||||
test(AddPadding::createPass(), {myclass}, R"(
|
||||
test({myclass}, R"(
|
||||
[0] Union: MyUnion (size: 8)
|
||||
Member: n1 (offset: 0)
|
||||
Primitive: int64_t
|
||||
@ -86,7 +97,7 @@ TEST(AddPaddingTest, Bitfields) {
|
||||
myclass.members.push_back(b4);
|
||||
myclass.members.push_back(n);
|
||||
|
||||
test(AddPadding::createPass(), {myclass}, R"(
|
||||
test({myclass}, R"(
|
||||
[0] Class: MyClass (size: 16)
|
||||
Member: b1 (offset: 0, bitsize: 3)
|
||||
Primitive: int64_t
|
||||
@ -111,4 +122,29 @@ TEST(AddPaddingTest, Bitfields) {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(AddPaddingTest, CodeGenCompatibility) {
|
||||
auto myint = Primitive{Primitive::Kind::Int32};
|
||||
auto vector = getVector(1);
|
||||
vector.templateParams.push_back(TemplateParam{myint});
|
||||
|
||||
auto myclass = Class{0, Class::Kind::Class, "MyClass", 24};
|
||||
myclass.members.push_back(Member{vector, "__oi_parent", 0});
|
||||
|
||||
FeatureSet features;
|
||||
features[Feature::TreeBuilderV2] = false;
|
||||
test(AddPadding::createPass(features), {myclass}, R"(
|
||||
[0] Class: MyClass (size: 24)
|
||||
Member: __oi_parent (offset: 0)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass (size: 24)
|
||||
Member: __oi_padding (offset: 0)
|
||||
[1] Array: (length: 24)
|
||||
Primitive: int8_t
|
||||
)");
|
||||
}
|
||||
|
||||
// TODO test we follow class members, templates, children
|
||||
|
@ -705,7 +705,7 @@ TEST(FlattenerTest, ParentContainer) {
|
||||
)",
|
||||
R"(
|
||||
[0] Class: ClassA (size: 32)
|
||||
Member: __parent (offset: 0)
|
||||
Member: __oi_parent (offset: 0)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
@ -735,11 +735,11 @@ TEST(FlattenerTest, ParentTwoContainers) {
|
||||
)",
|
||||
R"(
|
||||
[0] Class: ClassA (size: 48)
|
||||
Member: __parent (offset: 0)
|
||||
Member: __oi_parent (offset: 0)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: __parent (offset: 24)
|
||||
Member: __oi_parent (offset: 24)
|
||||
[1]
|
||||
)");
|
||||
}
|
||||
@ -772,7 +772,7 @@ TEST(FlattenerTest, ParentClassAndContainer) {
|
||||
[0] Class: ClassA (size: 32)
|
||||
Member: b (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: __parent (offset: 8)
|
||||
Member: __oi_parent (offset: 8)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
|
Loading…
Reference in New Issue
Block a user