mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-09 21:24:14 +00:00
Printer: Use NodeIds for stable IDs when printing graphs
This removes Printer's legacy behaviour of generating an ID for each node as it gets printed. This old method meant that if new nodes were added to or removed from a graph, every ID after the new/removed node would change. Now IDs are stable so it is easier to follow specific nodes through multiple transformation passes in CodeGen.
This commit is contained in:
parent
dca99fc4ad
commit
ff31971bd3
@ -42,7 +42,7 @@ void print(const TypeGraph& typeGraph) {
|
||||
return;
|
||||
|
||||
std::stringstream out;
|
||||
Printer printer{out, typeGraph.size()};
|
||||
Printer printer{out, typeGraph.resetTracker(), typeGraph.size()};
|
||||
for (const auto& type : typeGraph.rootTypes()) {
|
||||
printer.print(type);
|
||||
}
|
||||
|
@ -19,7 +19,8 @@
|
||||
|
||||
namespace oi::detail::type_graph {
|
||||
|
||||
Printer::Printer(std::ostream& out, size_t numTypes) : out_(out) {
|
||||
Printer::Printer(std::ostream& out, NodeTracker& tracker, size_t numTypes)
|
||||
: tracker_(tracker), out_(out) {
|
||||
if (numTypes == 0) {
|
||||
baseIndent_ = 0;
|
||||
return;
|
||||
@ -139,19 +140,16 @@ bool Printer::prefix(const Type* type) {
|
||||
int indent = baseIndent_ + depth_ * 2;
|
||||
|
||||
if (type) {
|
||||
if (auto it = nodeNums_.find(type); it != nodeNums_.end()) {
|
||||
if (tracker_.visit(*type)) {
|
||||
// Node has already been printed - print a reference to it this time
|
||||
out_ << std::string(indent, ' ');
|
||||
int nodeNum = it->second;
|
||||
out_ << "[" << nodeNum << "]" << std::endl;
|
||||
out_ << "[" << type->id() << "]" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
int nodeNum = nextNodeNum_++;
|
||||
std::string nodeId = "[" + std::to_string(nodeNum) + "]";
|
||||
std::string nodeId = "[" + std::to_string(type->id()) + "]";
|
||||
out_ << nodeId;
|
||||
indent -= nodeId.size();
|
||||
nodeNums_.insert({type, nodeNum});
|
||||
}
|
||||
|
||||
out_ << std::string(indent, ' ');
|
||||
|
@ -16,8 +16,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "NodeTracker.h"
|
||||
#include "Types.h"
|
||||
#include "Visitor.h"
|
||||
|
||||
@ -28,7 +28,7 @@ namespace oi::detail::type_graph {
|
||||
*/
|
||||
class Printer : public ConstVisitor {
|
||||
public:
|
||||
Printer(std::ostream& out, size_t numTypes);
|
||||
Printer(std::ostream& out, NodeTracker& tracker, size_t numTypes);
|
||||
|
||||
void print(const Type& type);
|
||||
|
||||
@ -53,11 +53,10 @@ class Printer : public ConstVisitor {
|
||||
void print_qualifiers(const QualifierSet& qualifiers);
|
||||
static std::string align_str(uint64_t align);
|
||||
|
||||
NodeTracker& tracker_;
|
||||
std::ostream& out_;
|
||||
int baseIndent_;
|
||||
int depth_ = -1;
|
||||
int nextNodeNum_ = 0;
|
||||
std::unordered_map<const Type*, int> nodeNums_;
|
||||
};
|
||||
|
||||
} // namespace oi::detail::type_graph
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
namespace oi::detail::type_graph {
|
||||
|
||||
NodeTracker& TypeGraph::resetTracker() noexcept {
|
||||
NodeTracker& TypeGraph::resetTracker() const noexcept {
|
||||
tracker_.reset();
|
||||
tracker_.resize(size());
|
||||
return tracker_;
|
||||
|
@ -48,7 +48,7 @@ class TypeGraph {
|
||||
rootTypes_.push_back(type);
|
||||
}
|
||||
|
||||
NodeTracker& resetTracker() noexcept;
|
||||
NodeTracker& resetTracker() const noexcept;
|
||||
|
||||
// Override of the generic makeType function that returns singleton Primitive
|
||||
// objects
|
||||
@ -58,6 +58,7 @@ class TypeGraph {
|
||||
template <typename T, typename... Args>
|
||||
T& makeType(NodeId id, Args&&... args) {
|
||||
static_assert(T::has_node_id, "Unnecessary node ID provided");
|
||||
next_id_ = std::max(next_id_, id + 1);
|
||||
auto type_unique_ptr = std::make_unique<T>(id, std::forward<Args>(args)...);
|
||||
auto type_raw_ptr = type_unique_ptr.get();
|
||||
types_.push_back(std::move(type_unique_ptr));
|
||||
@ -87,7 +88,7 @@ class TypeGraph {
|
||||
std::vector<std::reference_wrapper<Type>> rootTypes_;
|
||||
// Store all type objects in vectors for ownership. Order is not significant.
|
||||
std::vector<std::unique_ptr<Type>> types_;
|
||||
NodeTracker tracker_;
|
||||
mutable NodeTracker tracker_;
|
||||
NodeId next_id_ = 0;
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ std::string AddChildrenTest::run(std::string_view function,
|
||||
pass.run(typeGraph);
|
||||
|
||||
std::stringstream out;
|
||||
Printer printer{out, typeGraph.size()};
|
||||
Printer printer{out, typeGraph.resetTracker(), typeGraph.size()};
|
||||
printer.print(type);
|
||||
|
||||
return out.str();
|
||||
@ -35,8 +35,8 @@ std::string AddChildrenTest::run(std::string_view function,
|
||||
TEST_F(AddChildrenTest, SimpleStruct) {
|
||||
// Should do nothing
|
||||
test("oid_test_case_simple_struct", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: SimpleStruct (size: 16)
|
||||
[1] Pointer
|
||||
[0] Struct: SimpleStruct (size: 16)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4)
|
||||
@ -49,10 +49,10 @@ TEST_F(AddChildrenTest, SimpleStruct) {
|
||||
TEST_F(AddChildrenTest, InheritanceStatic) {
|
||||
// Should do nothing
|
||||
test("oid_test_case_inheritance_access_public", R"(
|
||||
[0] Pointer
|
||||
[1] Class: Public (size: 8)
|
||||
[2] Pointer
|
||||
[0] Class: Public (size: 8)
|
||||
Parent (offset: 0)
|
||||
[2] Class: Base (size: 4)
|
||||
[1] Class: Base (size: 4)
|
||||
Member: base_int (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: public_int (offset: 4)
|
||||
@ -62,8 +62,8 @@ TEST_F(AddChildrenTest, InheritanceStatic) {
|
||||
|
||||
TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
testMultiCompiler("oid_test_case_inheritance_polymorphic_a_as_a", R"(
|
||||
[0] Pointer
|
||||
[1] Class: A (size: 16)
|
||||
[1] Pointer
|
||||
[0] Class: A (size: 16)
|
||||
Member: _vptr$A (offset: 0)
|
||||
Primitive: uintptr_t
|
||||
Member: int_a (offset: 8)
|
||||
@ -73,19 +73,19 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: A
|
||||
Function: A
|
||||
Child
|
||||
[2] Class: B (size: 40)
|
||||
[8] Class: B (size: 40)
|
||||
Parent (offset: 0)
|
||||
[1]
|
||||
[0]
|
||||
Member: vec_b (offset: 16)
|
||||
[3] Container: std::vector (size: 24)
|
||||
[4] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[4] Class: allocator<int> (size: 1)
|
||||
[5] Class: allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Parent (offset: 0)
|
||||
[5] Typedef: __allocator_base<int>
|
||||
[7] Typedef: __allocator_base<int>
|
||||
[6] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
@ -105,9 +105,9 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: B
|
||||
Function: B
|
||||
Child
|
||||
[7] Class: C (size: 48)
|
||||
[10] Class: C (size: 48)
|
||||
Parent (offset: 0)
|
||||
[2]
|
||||
[8]
|
||||
Member: int_c (offset: 40)
|
||||
Primitive: int32_t
|
||||
Function: ~C (virtual)
|
||||
@ -116,8 +116,8 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: C
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: A (size: 16)
|
||||
[1] Pointer
|
||||
[0] Class: A (size: 16)
|
||||
Member: _vptr.A (offset: 0)
|
||||
Primitive: uintptr_t
|
||||
Member: int_a (offset: 8)
|
||||
@ -128,17 +128,17 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: ~A (virtual)
|
||||
Function: myfunc (virtual)
|
||||
Child
|
||||
[2] Class: B (size: 40)
|
||||
[7] Class: B (size: 40)
|
||||
Parent (offset: 0)
|
||||
[1]
|
||||
[0]
|
||||
Member: vec_b (offset: 16)
|
||||
[3] Container: std::vector (size: 24)
|
||||
[4] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[4] Class: allocator<int> (size: 1)
|
||||
[5] Class: allocator<int> (size: 1)
|
||||
Parent (offset: 0)
|
||||
[5] Class: new_allocator<int> (size: 1)
|
||||
[6] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: new_allocator
|
||||
@ -158,9 +158,9 @@ TEST_F(AddChildrenTest, InheritancePolymorphic) {
|
||||
Function: ~B (virtual)
|
||||
Function: myfunc (virtual)
|
||||
Child
|
||||
[6] Class: C (size: 48)
|
||||
[9] Class: C (size: 48)
|
||||
Parent (offset: 0)
|
||||
[2]
|
||||
[7]
|
||||
Member: int_c (offset: 40)
|
||||
Primitive: int32_t
|
||||
Function: operator=
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "TypeGraphParser.h"
|
||||
#include "mocks.h"
|
||||
#include "oi/CodeGen.h"
|
||||
#include "oi/type_graph/Printer.h"
|
||||
#include "oi/type_graph/TypeGraph.h"
|
||||
#include "oi/type_graph/Types.h"
|
||||
#include "type_graph_utils.h"
|
||||
@ -32,13 +31,13 @@ void testTransform(OICodeGen::Config& config,
|
||||
}
|
||||
|
||||
// Validate input formatting
|
||||
check(typeGraph.rootTypes(), input, "parsing input graph");
|
||||
check(typeGraph, input, "parsing input graph");
|
||||
|
||||
MockSymbolService symbols;
|
||||
CodeGen codegen{config, symbols};
|
||||
codegen.transform(typeGraph);
|
||||
|
||||
check(typeGraph.rootTypes(), expectedAfter, "after transform");
|
||||
check(typeGraph, expectedAfter, "after transform");
|
||||
}
|
||||
|
||||
void testTransform(std::string_view input, std::string_view expectedAfter) {
|
||||
@ -100,7 +99,7 @@ TEST(CodeGenTest, TransformContainerAllocatorParamInParent) {
|
||||
Primitive: int32_t
|
||||
Param
|
||||
DummyAllocator (size: 0)
|
||||
[1] Container: std::pair<int32_t const, int32_t> (size: 8)
|
||||
[3] Container: std::pair<int32_t const, int32_t> (size: 8)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Qualifiers: const
|
||||
|
@ -55,7 +55,7 @@ std::string DrgnParserTest::run(std::string_view function,
|
||||
Type& type = drgnParser.parse(drgnRoot);
|
||||
|
||||
std::stringstream out;
|
||||
Printer printer{out, typeGraph.size()};
|
||||
Printer printer{out, typeGraph.resetTracker(), typeGraph.size()};
|
||||
printer.print(type);
|
||||
|
||||
return out.str();
|
||||
@ -105,8 +105,8 @@ void DrgnParserTest::testMultiCompilerContains(
|
||||
|
||||
TEST_F(DrgnParserTest, SimpleStruct) {
|
||||
test("oid_test_case_simple_struct", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: SimpleStruct (size: 16)
|
||||
[1] Pointer
|
||||
[0] Struct: SimpleStruct (size: 16)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4)
|
||||
@ -118,8 +118,8 @@ TEST_F(DrgnParserTest, SimpleStruct) {
|
||||
|
||||
TEST_F(DrgnParserTest, SimpleClass) {
|
||||
test("oid_test_case_simple_class", R"(
|
||||
[0] Pointer
|
||||
[1] Class: SimpleClass (size: 16)
|
||||
[1] Pointer
|
||||
[0] Class: SimpleClass (size: 16)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4)
|
||||
@ -131,8 +131,8 @@ TEST_F(DrgnParserTest, SimpleClass) {
|
||||
|
||||
TEST_F(DrgnParserTest, SimpleUnion) {
|
||||
test("oid_test_case_simple_union", R"(
|
||||
[0] Pointer
|
||||
[1] Union: SimpleUnion (size: 8)
|
||||
[1] Pointer
|
||||
[0] Union: SimpleUnion (size: 8)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 0)
|
||||
@ -144,10 +144,10 @@ TEST_F(DrgnParserTest, SimpleUnion) {
|
||||
|
||||
TEST_F(DrgnParserTest, Inheritance) {
|
||||
test("oid_test_case_inheritance_access_public", R"(
|
||||
[0] Pointer
|
||||
[1] Class: Public (size: 8)
|
||||
[2] Pointer
|
||||
[0] Class: Public (size: 8)
|
||||
Parent (offset: 0)
|
||||
[2] Class: Base (size: 4)
|
||||
[1] Class: Base (size: 4)
|
||||
Member: base_int (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: public_int (offset: 4)
|
||||
@ -157,26 +157,26 @@ TEST_F(DrgnParserTest, Inheritance) {
|
||||
|
||||
TEST_F(DrgnParserTest, InheritanceMultiple) {
|
||||
test("oid_test_case_inheritance_multiple_a", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Derived_2 (size: 24)
|
||||
[6] Pointer
|
||||
[0] Struct: Derived_2 (size: 24)
|
||||
Parent (offset: 0)
|
||||
[2] Struct: Base_1 (size: 4)
|
||||
[1] Struct: Base_1 (size: 4)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Parent (offset: 4)
|
||||
[3] Struct: Derived_1 (size: 12)
|
||||
[2] Struct: Derived_1 (size: 12)
|
||||
Parent (offset: 0)
|
||||
[4] Struct: Base_2 (size: 4)
|
||||
[3] Struct: Base_2 (size: 4)
|
||||
Member: b (offset: 0)
|
||||
Primitive: int32_t
|
||||
Parent (offset: 4)
|
||||
[5] Struct: Base_3 (size: 4)
|
||||
[4] Struct: Base_3 (size: 4)
|
||||
Member: c (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: d (offset: 8)
|
||||
Primitive: int32_t
|
||||
Parent (offset: 16)
|
||||
[6] Struct: Base_4 (size: 4)
|
||||
[5] Struct: Base_4 (size: 4)
|
||||
Member: e (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: f (offset: 20)
|
||||
@ -186,17 +186,17 @@ TEST_F(DrgnParserTest, InheritanceMultiple) {
|
||||
|
||||
TEST_F(DrgnParserTest, Container) {
|
||||
testMultiCompiler("oid_test_case_std_vector_int_empty", R"(
|
||||
[0] Pointer
|
||||
[1] Container: std::vector (size: 24)
|
||||
[4] Pointer
|
||||
[0] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[2] Class: allocator<int> (size: 1)
|
||||
[1] Class: allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Parent (offset: 0)
|
||||
[3] Typedef: __allocator_base<int>
|
||||
[4] Class: new_allocator<int> (size: 1)
|
||||
[2] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: new_allocator
|
||||
@ -212,14 +212,14 @@ TEST_F(DrgnParserTest, Container) {
|
||||
Function: deallocate
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Container: std::vector (size: 24)
|
||||
[3] Pointer
|
||||
[0] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[2] Class: allocator<int> (size: 1)
|
||||
[1] Class: allocator<int> (size: 1)
|
||||
Parent (offset: 0)
|
||||
[3] Class: new_allocator<int> (size: 1)
|
||||
[2] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: new_allocator
|
||||
@ -257,36 +257,36 @@ TEST_F(DrgnParserTest, UnscopedEnum) {
|
||||
|
||||
TEST_F(DrgnParserTest, Typedef) {
|
||||
test("oid_test_case_typedefs_c_style", R"(
|
||||
[0] Typedef: TdUInt64
|
||||
[2] Typedef: TdUInt64
|
||||
[1] Typedef: uint64_t
|
||||
[2] Typedef: __uint64_t
|
||||
[0] Typedef: __uint64_t
|
||||
Primitive: uint64_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(DrgnParserTest, Using) {
|
||||
test("oid_test_case_typedefs_using", R"(
|
||||
[0] Typedef: UsingUInt64
|
||||
[2] Typedef: UsingUInt64
|
||||
[1] Typedef: uint64_t
|
||||
[2] Typedef: __uint64_t
|
||||
[0] Typedef: __uint64_t
|
||||
Primitive: uint64_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(DrgnParserTest, ArrayMember) {
|
||||
test("oid_test_case_arrays_member_int10", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Foo10 (size: 40)
|
||||
[2] Pointer
|
||||
[0] Struct: Foo10 (size: 40)
|
||||
Member: arr (offset: 0)
|
||||
[2] Array: (length: 10)
|
||||
[1] Array: (length: 10)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(DrgnParserTest, ArrayRef) {
|
||||
test("oid_test_case_arrays_ref_int10", R"(
|
||||
[0] Pointer
|
||||
[1] Array: (length: 10)
|
||||
[1] Pointer
|
||||
[0] Array: (length: 10)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
@ -300,23 +300,23 @@ TEST_F(DrgnParserTest, ArrayDirect) {
|
||||
|
||||
TEST_F(DrgnParserTest, Pointer) {
|
||||
test("oid_test_case_pointers_struct_primitive_ptrs", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: PrimitivePtrs (size: 24)
|
||||
[3] Pointer
|
||||
[0] Struct: PrimitivePtrs (size: 24)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 8)
|
||||
[2] Pointer
|
||||
[1] Pointer
|
||||
Primitive: int32_t
|
||||
Member: c (offset: 16)
|
||||
[3] Pointer
|
||||
[2] Pointer
|
||||
Primitive: void
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(DrgnParserTest, PointerNoFollow) {
|
||||
test("oid_test_case_pointers_struct_primitive_ptrs", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: PrimitivePtrs (size: 24)
|
||||
[1] Pointer
|
||||
[0] Struct: PrimitivePtrs (size: 24)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 8)
|
||||
@ -336,20 +336,20 @@ TEST_F(DrgnParserTest, PointerIncomplete) {
|
||||
|
||||
TEST_F(DrgnParserTest, Cycle) {
|
||||
test("oid_test_case_cycles_raw_ptr", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: RawNode (size: 16)
|
||||
[2] Pointer
|
||||
[0] Struct: RawNode (size: 16)
|
||||
Member: value (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: next (offset: 8)
|
||||
[2] Pointer
|
||||
[1]
|
||||
[1] Pointer
|
||||
[0]
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(DrgnParserTest, ClassTemplateInt) {
|
||||
test("oid_test_case_templates_int", R"(
|
||||
[0] Pointer
|
||||
[1] Class: TemplatedClass1<int> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: TemplatedClass1<int> (size: 4)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: val (offset: 0)
|
||||
@ -359,19 +359,19 @@ TEST_F(DrgnParserTest, ClassTemplateInt) {
|
||||
|
||||
TEST_F(DrgnParserTest, ClassTemplateVector) {
|
||||
testMultiCompiler("oid_test_case_templates_vector", R"(
|
||||
[0] Pointer
|
||||
[1] Class: TemplatedClass1<std::vector<int, std::allocator<int> > > (size: 24)
|
||||
[5] Pointer
|
||||
[0] Class: TemplatedClass1<std::vector<int, std::allocator<int> > > (size: 24)
|
||||
Param
|
||||
[2] Container: std::vector (size: 24)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[3] Class: allocator<int> (size: 1)
|
||||
[2] Class: allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Parent (offset: 0)
|
||||
[4] Typedef: __allocator_base<int>
|
||||
[5] Class: new_allocator<int> (size: 1)
|
||||
[3] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: new_allocator
|
||||
@ -386,21 +386,21 @@ TEST_F(DrgnParserTest, ClassTemplateVector) {
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
Member: val (offset: 0)
|
||||
[2]
|
||||
[1]
|
||||
Function: ~TemplatedClass1
|
||||
Function: TemplatedClass1
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: TemplatedClass1<std::vector<int, std::allocator<int> > > (size: 24)
|
||||
[4] Pointer
|
||||
[0] Class: TemplatedClass1<std::vector<int, std::allocator<int> > > (size: 24)
|
||||
Param
|
||||
[2] Container: std::vector (size: 24)
|
||||
[1] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[3] Class: allocator<int> (size: 1)
|
||||
[2] Class: allocator<int> (size: 1)
|
||||
Parent (offset: 0)
|
||||
[4] Class: new_allocator<int> (size: 1)
|
||||
[3] Class: new_allocator<int> (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Function: new_allocator
|
||||
@ -415,7 +415,7 @@ TEST_F(DrgnParserTest, ClassTemplateVector) {
|
||||
Function: allocate
|
||||
Function: deallocate
|
||||
Member: val (offset: 0)
|
||||
[2]
|
||||
[1]
|
||||
Function: TemplatedClass1
|
||||
Function: ~TemplatedClass1
|
||||
)");
|
||||
@ -423,10 +423,10 @@ TEST_F(DrgnParserTest, ClassTemplateVector) {
|
||||
|
||||
TEST_F(DrgnParserTest, ClassTemplateTwo) {
|
||||
test("oid_test_case_templates_two", R"(
|
||||
[0] Pointer
|
||||
[1] Class: TemplatedClass2<ns_templates::Foo, int> (size: 12)
|
||||
[3] Pointer
|
||||
[0] Class: TemplatedClass2<ns_templates::Foo, int> (size: 12)
|
||||
Param
|
||||
[2] Struct: Foo (size: 8)
|
||||
[1] Struct: Foo (size: 8)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4)
|
||||
@ -434,11 +434,11 @@ TEST_F(DrgnParserTest, ClassTemplateTwo) {
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Member: tc1 (offset: 0)
|
||||
[3] Class: TemplatedClass1<ns_templates::Foo> (size: 8)
|
||||
[2] Class: TemplatedClass1<ns_templates::Foo> (size: 8)
|
||||
Param
|
||||
[2]
|
||||
[1]
|
||||
Member: val (offset: 0)
|
||||
[2]
|
||||
[1]
|
||||
Member: val2 (offset: 8)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
@ -446,12 +446,12 @@ TEST_F(DrgnParserTest, ClassTemplateTwo) {
|
||||
|
||||
TEST_F(DrgnParserTest, ClassTemplateValue) {
|
||||
test("oid_test_case_templates_value", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: TemplatedClassVal<3> (size: 12)
|
||||
[2] Pointer
|
||||
[0] Struct: TemplatedClassVal<3> (size: 12)
|
||||
Param
|
||||
Value: 3
|
||||
Member: arr (offset: 0)
|
||||
[2] Array: (length: 3)
|
||||
[1] Array: (length: 3)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
}
|
||||
@ -459,14 +459,14 @@ TEST_F(DrgnParserTest, ClassTemplateValue) {
|
||||
TEST_F(DrgnParserTest, TemplateEnumValue) {
|
||||
testMultiCompilerContains("oid_test_case_enums_params_scoped_enum_val",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: MyClass<ns_enums_params::MyNS::ScopedEnum::One> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: MyClass<ns_enums_params::MyNS::ScopedEnum::One> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::ScopedEnum::One
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::ScopedEnum::One
|
||||
)");
|
||||
@ -475,14 +475,14 @@ TEST_F(DrgnParserTest, TemplateEnumValue) {
|
||||
TEST_F(DrgnParserTest, TemplateEnumValueGaps) {
|
||||
testMultiCompilerContains("oid_test_case_enums_params_scoped_enum_val_gaps",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::Twenty> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::Twenty> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
|
||||
)");
|
||||
@ -491,14 +491,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueGaps) {
|
||||
TEST_F(DrgnParserTest, TemplateEnumValueNegative) {
|
||||
testMultiCompilerContains(
|
||||
"oid_test_case_enums_params_scoped_enum_val_negative", R"(
|
||||
[0] Pointer
|
||||
[1] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4)
|
||||
[1] Pointer
|
||||
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4)
|
||||
Param
|
||||
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
|
||||
)");
|
||||
@ -519,8 +519,8 @@ TEST_F(DrgnParserTest, TemplateEnumValueNegative) {
|
||||
TEST_F(DrgnParserTest, StructAlignment) {
|
||||
GTEST_SKIP() << "Alignment not reported by drgn yet";
|
||||
test("oid_test_case_alignment_struct", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Align16 (size: 16, align: 16)
|
||||
[1] Pointer
|
||||
[0] Struct: Align16 (size: 16, align: 16)
|
||||
Member: c (offset: 0)
|
||||
Primitive: int8_t
|
||||
)");
|
||||
@ -529,8 +529,8 @@ TEST_F(DrgnParserTest, StructAlignment) {
|
||||
TEST_F(DrgnParserTest, MemberAlignment) {
|
||||
GTEST_SKIP() << "Alignment not reported by drgn yet";
|
||||
test("oid_test_case_alignment_member_alignment", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: MemberAlignment (size: 64)
|
||||
[1] Pointer
|
||||
[0] Struct: MemberAlignment (size: 64)
|
||||
Member: c (offset: 0)
|
||||
Primitive: int8_t
|
||||
Member: c32 (offset: 32, align: 32)
|
||||
@ -540,8 +540,8 @@ TEST_F(DrgnParserTest, MemberAlignment) {
|
||||
|
||||
TEST_F(DrgnParserTest, VirtualFunctions) {
|
||||
testMultiCompiler("oid_test_case_inheritance_polymorphic_a_as_a", R"(
|
||||
[0] Pointer
|
||||
[1] Class: A (size: 16)
|
||||
[1] Pointer
|
||||
[0] Class: A (size: 16)
|
||||
Member: _vptr$A (offset: 0)
|
||||
Primitive: uintptr_t
|
||||
Member: int_a (offset: 8)
|
||||
@ -552,8 +552,8 @@ TEST_F(DrgnParserTest, VirtualFunctions) {
|
||||
Function: A
|
||||
)",
|
||||
R"(
|
||||
[0] Pointer
|
||||
[1] Class: A (size: 16)
|
||||
[1] Pointer
|
||||
[0] Class: A (size: 16)
|
||||
Member: _vptr.A (offset: 0)
|
||||
Primitive: uintptr_t
|
||||
Member: int_a (offset: 8)
|
||||
@ -568,8 +568,8 @@ TEST_F(DrgnParserTest, VirtualFunctions) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsSingle) {
|
||||
test("oid_test_case_bitfields_single", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Single (size: 4)
|
||||
[1] Pointer
|
||||
[0] Struct: Single (size: 4)
|
||||
Member: bitfield (offset: 0, bitsize: 3)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
@ -577,8 +577,8 @@ TEST_F(DrgnParserTest, BitfieldsSingle) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsWithinBytes) {
|
||||
test("oid_test_case_bitfields_within_bytes", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: WithinBytes (size: 2)
|
||||
[1] Pointer
|
||||
[0] Struct: WithinBytes (size: 2)
|
||||
Member: a (offset: 0, bitsize: 3)
|
||||
Primitive: int8_t
|
||||
Member: b (offset: 0.375, bitsize: 5)
|
||||
@ -590,8 +590,8 @@ TEST_F(DrgnParserTest, BitfieldsWithinBytes) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsStraddleBytes) {
|
||||
test("oid_test_case_bitfields_straddle_bytes", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: StraddleBytes (size: 3)
|
||||
[1] Pointer
|
||||
[0] Struct: StraddleBytes (size: 3)
|
||||
Member: a (offset: 0, bitsize: 7)
|
||||
Primitive: int8_t
|
||||
Member: b (offset: 1, bitsize: 7)
|
||||
@ -603,8 +603,8 @@ TEST_F(DrgnParserTest, BitfieldsStraddleBytes) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsMixed) {
|
||||
test("oid_test_case_bitfields_mixed", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Mixed (size: 12)
|
||||
[1] Pointer
|
||||
[0] Struct: Mixed (size: 12)
|
||||
Member: a (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: b (offset: 4, bitsize: 4)
|
||||
@ -621,8 +621,8 @@ TEST_F(DrgnParserTest, BitfieldsMixed) {
|
||||
TEST_F(DrgnParserTest, BitfieldsMoreBitsThanType) {
|
||||
GTEST_SKIP() << "drgn errors out";
|
||||
test("oid_test_case_bitfields_more_bits_than_type", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: MoreBitsThanType (size: 4)
|
||||
[1] Pointer
|
||||
[0] Struct: MoreBitsThanType (size: 4)
|
||||
Member: a (offset: 0, bitsize: 8)
|
||||
Primitive: int8_t
|
||||
)");
|
||||
@ -630,8 +630,8 @@ TEST_F(DrgnParserTest, BitfieldsMoreBitsThanType) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsZeroBits) {
|
||||
test("oid_test_case_bitfields_zero_bits", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: ZeroBits (size: 2)
|
||||
[1] Pointer
|
||||
[0] Struct: ZeroBits (size: 2)
|
||||
Member: b1 (offset: 0, bitsize: 3)
|
||||
Primitive: int8_t
|
||||
Member: b2 (offset: 1, bitsize: 2)
|
||||
@ -641,8 +641,8 @@ TEST_F(DrgnParserTest, BitfieldsZeroBits) {
|
||||
|
||||
TEST_F(DrgnParserTest, BitfieldsEnum) {
|
||||
test("oid_test_case_bitfields_enum", R"(
|
||||
[0] Pointer
|
||||
[1] Struct: Enum (size: 4)
|
||||
[1] Pointer
|
||||
[0] Struct: Enum (size: 4)
|
||||
Member: e (offset: 0, bitsize: 2)
|
||||
Enum: MyEnum (size: 4)
|
||||
Member: f (offset: 0.25, bitsize: 4)
|
||||
|
@ -363,7 +363,7 @@ TEST(FlattenerTest, MemberOfParent) {
|
||||
Member: b (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: c (offset: 4)
|
||||
[1] Class: ClassC (size: 4)
|
||||
[2] Class: ClassC (size: 4)
|
||||
Member: c (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: a (offset: 8)
|
||||
@ -771,7 +771,7 @@ TEST(FlattenerTest, ParentClassAndContainer) {
|
||||
Member: b (offset: 0)
|
||||
Primitive: int32_t
|
||||
Member: __oi_parent (offset: 8)
|
||||
[1] Container: std::vector (size: 24)
|
||||
[2] Container: std::vector (size: 24)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
@ -809,7 +809,7 @@ TEST(FlattenerTest, AllocatorParamInParent) {
|
||||
Param
|
||||
[1] Struct: MyAlloc<std::pair<const int, int>> (size: 1)
|
||||
Param
|
||||
[2] Container: std::pair (size: 8)
|
||||
[3] Container: std::pair (size: 8)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Qualifiers: const
|
||||
|
@ -14,7 +14,7 @@ TEST(RemoveTopLevelPointerTest, TopLevelPointerRemoved) {
|
||||
Primitive: int32_t
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass (size: 4)
|
||||
[1] Class: MyClass (size: 4)
|
||||
Member: n (offset: 0)
|
||||
Primitive: int32_t
|
||||
)");
|
||||
|
@ -101,7 +101,7 @@ TEST(TypeIdentifierTest, PassThroughTypes) {
|
||||
Param
|
||||
Primitive: int32_t
|
||||
Param
|
||||
[1] Container: std::allocator (size: 1)
|
||||
[2] Container: std::allocator (size: 1)
|
||||
Param
|
||||
Primitive: int32_t
|
||||
)");
|
||||
|
@ -17,13 +17,13 @@ using type_graph::TypeGraph;
|
||||
template <typename T>
|
||||
using ref = std::reference_wrapper<T>;
|
||||
|
||||
void check(const std::vector<ref<Type>>& types,
|
||||
void check(const TypeGraph& typeGraph,
|
||||
std::string_view expected,
|
||||
std::string_view comment) {
|
||||
std::stringstream out;
|
||||
type_graph::Printer printer(out, types.size());
|
||||
type_graph::Printer printer(out, typeGraph.resetTracker(), typeGraph.size());
|
||||
|
||||
for (const auto& type : types) {
|
||||
for (const auto& type : typeGraph.rootTypes()) {
|
||||
printer.print(type);
|
||||
}
|
||||
|
||||
@ -45,52 +45,15 @@ void test(type_graph::Pass pass,
|
||||
}
|
||||
|
||||
// Validate input formatting
|
||||
check(typeGraph.rootTypes(), input, "parsing input graph");
|
||||
|
||||
// Run pass and check results
|
||||
test(pass, typeGraph.rootTypes(), expectedAfter);
|
||||
}
|
||||
|
||||
void testNoChange(type_graph::Pass pass, std::string_view input) {
|
||||
input.remove_prefix(1); // Remove initial '\n'
|
||||
TypeGraph typeGraph;
|
||||
TypeGraphParser parser{typeGraph};
|
||||
try {
|
||||
parser.parse(input);
|
||||
} catch (const TypeGraphParserError& err) {
|
||||
FAIL() << "Error parsing input graph: " << err.what();
|
||||
}
|
||||
|
||||
// Validate input formatting
|
||||
check(typeGraph.rootTypes(), input, "parsing input graph");
|
||||
|
||||
// Run pass and check results
|
||||
test(pass, typeGraph.rootTypes(), input);
|
||||
}
|
||||
|
||||
void test(type_graph::Pass pass,
|
||||
std::vector<ref<Type>> rootTypes,
|
||||
std::string_view expectedBefore,
|
||||
std::string_view expectedAfter) {
|
||||
if (expectedBefore.data()) {
|
||||
check(rootTypes, expectedBefore, "before running pass");
|
||||
}
|
||||
|
||||
TypeGraph typeGraph;
|
||||
for (const auto& type : rootTypes) {
|
||||
typeGraph.addRoot(type);
|
||||
}
|
||||
check(typeGraph, input, "parsing input graph");
|
||||
|
||||
pass.run(typeGraph);
|
||||
|
||||
// Must use typeGraph's root types here, as the pass may have modified them
|
||||
check(typeGraph.rootTypes(), expectedAfter, "after running pass");
|
||||
check(typeGraph, expectedAfter, "after running pass");
|
||||
}
|
||||
|
||||
void test(type_graph::Pass pass,
|
||||
std::vector<ref<Type>> rootTypes,
|
||||
std::string_view expectedAfter) {
|
||||
test(pass, rootTypes, {}, expectedAfter);
|
||||
void testNoChange(type_graph::Pass pass, std::string_view input) {
|
||||
test(pass, input, input);
|
||||
}
|
||||
|
||||
Container getVector(NodeId id) {
|
||||
|
@ -8,11 +8,12 @@
|
||||
|
||||
namespace oi::detail::type_graph {
|
||||
class Pass;
|
||||
class TypeGraph;
|
||||
} // namespace oi::detail::type_graph
|
||||
|
||||
using namespace oi::detail;
|
||||
|
||||
void check(const std::vector<std::reference_wrapper<type_graph::Type>>& types,
|
||||
void check(const type_graph::TypeGraph& typeGraph,
|
||||
std::string_view expected,
|
||||
std::string_view comment);
|
||||
|
||||
@ -22,15 +23,6 @@ void test(type_graph::Pass pass,
|
||||
|
||||
void testNoChange(type_graph::Pass pass, std::string_view input);
|
||||
|
||||
void test(type_graph::Pass pass,
|
||||
std::vector<std::reference_wrapper<type_graph::Type>> rootTypes,
|
||||
std::string_view expectedBefore,
|
||||
std::string_view expectedAfter);
|
||||
|
||||
void test(type_graph::Pass pass,
|
||||
std::vector<std::reference_wrapper<type_graph::Type>> rootTypes,
|
||||
std::string_view expectedAfter);
|
||||
|
||||
type_graph::Container getVector(type_graph::NodeId id = 0);
|
||||
type_graph::Container getMap(type_graph::NodeId id = 0);
|
||||
type_graph::Container getList(type_graph::NodeId id = 0);
|
||||
|
Loading…
Reference in New Issue
Block a user