Maintain type/name of Incomplete type

This commit is contained in:
Thierry Treyer 2023-09-28 10:59:54 -07:00 committed by Jake Hillion
parent 37991140da
commit 3065dd14e9
9 changed files with 108 additions and 31 deletions

View File

@ -87,43 +87,55 @@ Type& DrgnParser::enumerateType(struct drgn_type* type) {
if (auto it = drgn_types_.find(type); it != drgn_types_.end()) if (auto it = drgn_types_.find(type); it != drgn_types_.end())
return it->second; return it->second;
if (!drgn_utils::isSizeComplete(type) && bool isTypeIncomplete = !drgn_utils::isSizeComplete(type) &&
drgn_type_kind(type) != DRGN_TYPE_VOID) { drgn_type_kind(type) != DRGN_TYPE_VOID;
return makeType<Primitive>(nullptr, Primitive::Kind::Incomplete);
}
enum drgn_type_kind kind = drgn_type_kind(type); enum drgn_type_kind kind = drgn_type_kind(type);
Type* t = nullptr; Type* t = nullptr;
depth_++; depth_++;
switch (kind) { try {
case DRGN_TYPE_CLASS: switch (kind) {
case DRGN_TYPE_STRUCT: case DRGN_TYPE_CLASS:
case DRGN_TYPE_UNION: case DRGN_TYPE_STRUCT:
t = &enumerateClass(type); case DRGN_TYPE_UNION:
break; t = &enumerateClass(type);
case DRGN_TYPE_ENUM: break;
t = &enumerateEnum(type); case DRGN_TYPE_ENUM:
break; t = &enumerateEnum(type);
case DRGN_TYPE_TYPEDEF: break;
t = &enumerateTypedef(type); case DRGN_TYPE_TYPEDEF:
break; t = &enumerateTypedef(type);
case DRGN_TYPE_POINTER: break;
t = &enumeratePointer(type); case DRGN_TYPE_POINTER:
break; t = &enumeratePointer(type);
case DRGN_TYPE_ARRAY: break;
t = &enumerateArray(type); case DRGN_TYPE_ARRAY:
break; t = &enumerateArray(type);
case DRGN_TYPE_INT: break;
case DRGN_TYPE_BOOL: case DRGN_TYPE_INT:
case DRGN_TYPE_FLOAT: case DRGN_TYPE_BOOL:
case DRGN_TYPE_VOID: case DRGN_TYPE_FLOAT:
t = &enumeratePrimitive(type); case DRGN_TYPE_VOID:
break; t = &enumeratePrimitive(type);
default: break;
throw DrgnParserError{"Unknown drgn type kind: " + std::to_string(kind)}; default:
throw DrgnParserError{"Unknown drgn type kind: " +
std::to_string(kind)};
}
} catch (const DrgnParserError& e) {
if (isTypeIncomplete) {
t = &makeType<Primitive>(type, Primitive::Kind::Incomplete);
} else {
depth_--;
throw e;
}
} }
depth_--; depth_--;
if (isTypeIncomplete) {
return makeType<Incomplete>(nullptr, *t);
}
return *t; return *t;
} }

View File

@ -78,6 +78,12 @@ void EnforceCompatibility::visit(Class& c) {
return true; return true;
if (auto* ptr = dynamic_cast<Pointer*>(&member.type())) { if (auto* ptr = dynamic_cast<Pointer*>(&member.type())) {
if (auto* incomplete = dynamic_cast<Incomplete*>(&ptr->pointeeType())) {
// This is a pointer to an incomplete type. CodeGen v1 does not record
// the pointer's address in this case.
return true;
}
if (auto* primitive = dynamic_cast<Primitive*>(&ptr->pointeeType())) { if (auto* primitive = dynamic_cast<Primitive*>(&ptr->pointeeType())) {
if (primitive->kind() == Primitive::Kind::Incomplete) { if (primitive->kind() == Primitive::Kind::Incomplete) {
// This is a pointer to an incomplete type. CodeGen v1 does not record // This is a pointer to an incomplete type. CodeGen v1 does not record

View File

@ -36,6 +36,12 @@ void Printer::print(const Type& type) {
depth_--; depth_--;
} }
void Printer::visit(const Incomplete& i) {
prefix();
out_ << "Incomplete:" << std::endl;
print(i.underlyingType());
}
void Printer::visit(const Class& c) { void Printer::visit(const Class& c) {
if (prefix(c)) if (prefix(c))
return; return;

View File

@ -32,6 +32,7 @@ class Printer : public ConstVisitor {
void print(const Type& type); void print(const Type& type);
void visit(const Incomplete& i) override;
void visit(const Class& c) override; void visit(const Class& c) override;
void visit(const Container& c) override; void visit(const Container& c) override;
void visit(const Primitive& p) override; void visit(const Primitive& p) override;

View File

@ -29,6 +29,8 @@ namespace oi::detail::type_graph {
OI_TYPE_LIST OI_TYPE_LIST
#undef X #undef X
const std::string Incomplete::kName = "void";
std::string Primitive::getName(Kind kind) { std::string Primitive::getName(Kind kind) {
switch (kind) { switch (kind) {
case Kind::Int8: case Kind::Int8:

View File

@ -40,6 +40,7 @@
#include "oi/EnumBitset.h" #include "oi/EnumBitset.h"
#define OI_TYPE_LIST \ #define OI_TYPE_LIST \
X(Incomplete) \
X(Class) \ X(Class) \
X(Container) \ X(Container) \
X(Primitive) \ X(Primitive) \
@ -184,6 +185,49 @@ struct TemplateParam {
std::optional<std::string> value; std::optional<std::string> value;
}; };
/*
* Incomplete
*
* A wrapper around a type we couldn't determine the size of.
*/
class Incomplete : public Type {
public:
Incomplete(Type& underlyingType) : underlyingType_(underlyingType) {
}
static inline constexpr bool has_node_id = false;
DECLARE_ACCEPT
const std::string& name() const override {
return kName;
}
std::string_view inputName() const override {
return underlyingType_.inputName();
}
size_t size() const override {
return 0;
}
uint64_t align() const override {
return 0;
}
NodeId id() const override {
return -1;
}
Type& underlyingType() const {
return underlyingType_;
}
private:
Type& underlyingType_;
static const std::string kName;
};
/* /*
* Class * Class
* *

View File

@ -71,6 +71,8 @@ class RecursiveVisitor : public Visitor {
if (type) if (type)
accept(*type); accept(*type);
} }
virtual void visit(Incomplete&) {
}
virtual void visit(Class& c) { virtual void visit(Class& c) {
for (const auto& param : c.templateParams) { for (const auto& param : c.templateParams) {
accept(param.type()); accept(param.type());

View File

@ -211,6 +211,9 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
std::to_string(refId)}; std::to_string(refId)};
type = &it->second.get(); type = &it->second.get();
} else if (nodeTypeName == "Incomplete") {
auto& underlyingType = parseType(input, indent + 2);
type = &typeGraph_.makeType<Incomplete>(underlyingType);
} else if (nodeTypeName == "Class" || nodeTypeName == "Struct" || } else if (nodeTypeName == "Class" || nodeTypeName == "Struct" ||
nodeTypeName == "Union") { nodeTypeName == "Union") {
// Format: "Class: MyClass (size: 12)" // Format: "Class: MyClass (size: 12)"

View File

@ -367,7 +367,8 @@ TEST_F(DrgnParserTest, PointerNoFollow) {
TEST_F(DrgnParserTest, PointerIncomplete) { TEST_F(DrgnParserTest, PointerIncomplete) {
test("oid_test_case_pointers_incomplete_raw", R"( test("oid_test_case_pointers_incomplete_raw", R"(
[0] Pointer [0] Pointer
Primitive: void (incomplete) Incomplete:
Primitive: void (incomplete)
)"); )");
} }