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:
Alastair Robertson 2023-07-03 05:18:25 -07:00 committed by Alastair Robertson
parent e1b16a3d7e
commit 3ec81aaa5f
9 changed files with 80 additions and 17 deletions

View File

@ -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());

View File

@ -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:

View File

@ -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") \

View File

@ -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]);
}

View File

@ -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,

View File

@ -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");

View File

@ -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_;

View File

@ -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

View File

@ -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