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())
return it->second;
if (!drgn_utils::isSizeComplete(type) &&
drgn_type_kind(type) != DRGN_TYPE_VOID) {
return makeType<Primitive>(nullptr, Primitive::Kind::Incomplete);
}
bool isTypeIncomplete = !drgn_utils::isSizeComplete(type) &&
drgn_type_kind(type) != DRGN_TYPE_VOID;
enum drgn_type_kind kind = drgn_type_kind(type);
Type* t = nullptr;
depth_++;
switch (kind) {
case DRGN_TYPE_CLASS:
case DRGN_TYPE_STRUCT:
case DRGN_TYPE_UNION:
t = &enumerateClass(type);
break;
case DRGN_TYPE_ENUM:
t = &enumerateEnum(type);
break;
case DRGN_TYPE_TYPEDEF:
t = &enumerateTypedef(type);
break;
case DRGN_TYPE_POINTER:
t = &enumeratePointer(type);
break;
case DRGN_TYPE_ARRAY:
t = &enumerateArray(type);
break;
case DRGN_TYPE_INT:
case DRGN_TYPE_BOOL:
case DRGN_TYPE_FLOAT:
case DRGN_TYPE_VOID:
t = &enumeratePrimitive(type);
break;
default:
throw DrgnParserError{"Unknown drgn type kind: " + std::to_string(kind)};
try {
switch (kind) {
case DRGN_TYPE_CLASS:
case DRGN_TYPE_STRUCT:
case DRGN_TYPE_UNION:
t = &enumerateClass(type);
break;
case DRGN_TYPE_ENUM:
t = &enumerateEnum(type);
break;
case DRGN_TYPE_TYPEDEF:
t = &enumerateTypedef(type);
break;
case DRGN_TYPE_POINTER:
t = &enumeratePointer(type);
break;
case DRGN_TYPE_ARRAY:
t = &enumerateArray(type);
break;
case DRGN_TYPE_INT:
case DRGN_TYPE_BOOL:
case DRGN_TYPE_FLOAT:
case DRGN_TYPE_VOID:
t = &enumeratePrimitive(type);
break;
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_--;
if (isTypeIncomplete) {
return makeType<Incomplete>(nullptr, *t);
}
return *t;
}

View File

@ -78,6 +78,12 @@ void EnforceCompatibility::visit(Class& c) {
return true;
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 (primitive->kind() == Primitive::Kind::Incomplete) {
// 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_--;
}
void Printer::visit(const Incomplete& i) {
prefix();
out_ << "Incomplete:" << std::endl;
print(i.underlyingType());
}
void Printer::visit(const Class& c) {
if (prefix(c))
return;

View File

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

View File

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

View File

@ -40,6 +40,7 @@
#include "oi/EnumBitset.h"
#define OI_TYPE_LIST \
X(Incomplete) \
X(Class) \
X(Container) \
X(Primitive) \
@ -184,6 +185,49 @@ struct TemplateParam {
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
*

View File

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

View File

@ -211,6 +211,9 @@ Type& TypeGraphParser::parseType(std::string_view& input, size_t rootIndent) {
std::to_string(refId)};
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" ||
nodeTypeName == "Union") {
// Format: "Class: MyClass (size: 12)"

View File

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