DrgnParser: store type of template param value

This commit is contained in:
Jake Hillion 2023-08-16 12:44:58 -07:00 committed by Jake Hillion
parent ca0c71fa40
commit a2f7462a5d
12 changed files with 74 additions and 67 deletions

View File

@ -282,8 +282,27 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
drgn_type_template_parameter* tparams,
size_t i,
std::vector<TemplateParam>& params) {
drgn_qualified_type tparamQualType;
struct drgn_error* err =
drgn_template_parameter_type(&tparams[i], &tparamQualType);
if (err) {
warnForDrgnError(
type,
"Error looking up template parameter type (" + std::to_string(i) + ")",
err);
return;
}
struct drgn_type* tparamType = tparamQualType.type;
QualifierSet qualifiers;
qualifiers[Qualifier::Const] =
(tparamQualType.qualifiers & DRGN_QUALIFIER_CONST);
auto& ttype = enumerateType(tparamType);
const drgn_object* obj = nullptr;
if (auto* err = drgn_template_parameter_object(&tparams[i], &obj)) {
if (err = drgn_template_parameter_object(&tparams[i], &obj); err != nullptr) {
warnForDrgnError(type,
"Error looking up template parameter object (" +
std::to_string(i) + ")",
@ -291,26 +310,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
return;
}
struct drgn_qualified_type tparamQualType;
if (obj == nullptr) {
// This template parameter is a typename
struct drgn_error* err =
drgn_template_parameter_type(&tparams[i], &tparamQualType);
if (err) {
warnForDrgnError(type,
"Error looking up template parameter type (" +
std::to_string(i) + ")",
err);
return;
}
struct drgn_type* tparamType = tparamQualType.type;
QualifierSet qualifiers;
qualifiers[Qualifier::Const] =
(tparamQualType.qualifiers & DRGN_QUALIFIER_CONST);
auto& ttype = enumerateType(tparamType);
params.emplace_back(ttype, qualifiers);
} else {
// This template parameter is a value
@ -319,7 +319,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
if (drgn_type_kind(obj->type) == DRGN_TYPE_ENUM) {
char* nameStr = nullptr;
size_t length = 0;
auto* err = drgn_type_fully_qualified_name(obj->type, &nameStr, &length);
err = drgn_type_fully_qualified_name(obj->type, &nameStr, &length);
if (err != nullptr || nameStr == nullptr) {
throw DrgnParserError{"Failed to get enum's fully qualified name", err};
}
@ -383,7 +383,7 @@ void DrgnParser::enumerateTemplateParam(struct drgn_type* type,
}
}
params.emplace_back(std::move(value));
params.emplace_back(ttype, std::move(value));
}
}

View File

@ -100,13 +100,13 @@ void fixAllocatorParams(Class& alloc) {
return;
}
Type* allocParam = parentClass->templateParams[0].type();
if (!allocParam) {
if (parentClass->templateParams[0].value) {
// Nothing we can do
return;
}
Type& typeToAllocate = stripTypedefs(*allocParam);
Type& allocParam = parentClass->templateParams[0].type();
Type& typeToAllocate = stripTypedefs(allocParam);
alloc.templateParams.push_back(TemplateParam{typeToAllocate});
}
} // namespace

View File

@ -113,7 +113,7 @@ void NameGen::visit(Container& c) {
if (param.value) {
name += *param.value;
} else {
name += param.type()->name();
name += param.type().name();
// The "const" keyword must come after the type name so that pointers are
// handled correctly.
//

View File

@ -162,9 +162,8 @@ void Printer::print_param(const TemplateParam& param) {
out_ << "Param" << std::endl;
if (param.value) {
print_value(*param.value);
} else {
print(*param.type());
}
print(param.type());
print_qualifiers(param.qualifiers);
depth_--;
}

View File

@ -60,22 +60,22 @@ void TypeIdentifier::visit(Container& c) {
// TODO these two arrays could be looped over in sync for better performance
for (size_t i = 0; i < c.templateParams.size(); i++) {
const auto& param = c.templateParams[i];
if (dynamic_cast<Dummy*>(param.type()) ||
dynamic_cast<DummyAllocator*>(param.type()) ||
dynamic_cast<Container*>(param.type())) {
if (dynamic_cast<Dummy*>(&param.type()) ||
dynamic_cast<DummyAllocator*>(&param.type()) ||
dynamic_cast<Container*>(&param.type())) {
// In case the TypeIdentifier pass is run multiple times, we don't want to
// replace dummies again as the context of the original replacement has
// been lost.
continue;
}
if (Class* paramClass = dynamic_cast<Class*>(param.type())) {
if (Class* paramClass = dynamic_cast<Class*>(&param.type())) {
bool replaced = false;
for (const auto& info : passThroughTypes_) {
if (std::regex_search(paramClass->fqName(), info.matcher)) {
// Create dummy containers
auto& dummy =
typeGraph_.makeType<Container>(info, param.type()->size());
typeGraph_.makeType<Container>(info, param.type().size());
dummy.templateParams = paramClass->templateParams;
c.templateParams[i] = dummy;
replaced = true;
@ -89,22 +89,22 @@ void TypeIdentifier::visit(Container& c) {
if (std::find(stubParams.begin(), stubParams.end(), i) !=
stubParams.end()) {
size_t size = param.type()->size();
size_t size = param.type().size();
if (size == 1) {
// Hack: when we get a reported size of 1 for these parameters, it
// turns out that a size of 0 is actually expected.
size = 0;
}
if (isAllocator(*param.type())) {
auto* allocator =
dynamic_cast<Class*>(param.type()); // TODO please don't do this...
Type& typeToAllocate = *allocator->templateParams.at(0).type();
auto& dummy = typeGraph_.makeType<DummyAllocator>(
typeToAllocate, size, param.type()->align());
if (isAllocator(param.type())) {
auto* allocator = dynamic_cast<Class*>(
&param.type()); // TODO please don't do this...
Type& typeToAllocate = allocator->templateParams.at(0).type();
auto& dummy = typeGraph_.makeType<DummyAllocator>(typeToAllocate, size,
param.type().align());
c.templateParams[i] = dummy;
} else {
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type()->align());
auto& dummy = typeGraph_.makeType<Dummy>(size, param.type().align());
c.templateParams[i] = dummy;
}
}

View File

@ -143,23 +143,23 @@ struct Parent {
uint64_t bitOffset;
};
class TemplateParam {
public:
struct TemplateParam {
// TODO make ctors explicit
TemplateParam(Type& type) : type_(&type) {
TemplateParam(Type& type) : type_(type) {
}
TemplateParam(Type& type, QualifierSet qualifiers)
: type_(&type), qualifiers(qualifiers) {
: type_(type), qualifiers(qualifiers) {
}
TemplateParam(std::string value) : value(std::move(value)) {
TemplateParam(Type& type, std::string value)
: type_(type), value(std::move(value)) {
}
Type* type() const {
Type& type() const {
return type_;
}
private:
Type* type_ = nullptr; // Note: type is not set when this param holds a value
std::reference_wrapper<Type> type_;
public:
QualifierSet qualifiers;

View File

@ -314,22 +314,19 @@ void TypeGraphParser::parseParams(T& c,
if (!tryRemovePrefix(line, "Param"))
break;
if (auto value = tryParseStringValue(input, "Value: ", rootIndent + 2);
value) {
c.templateParams.emplace_back(std::string{*value});
} else {
Type& type = parseType(input, rootIndent + 2);
TemplateParam param{type};
if (auto qualStr =
tryParseStringValue(input, "Qualifiers: ", rootIndent + 2);
qualStr) {
Qualifier qual = getQualifier(*qualStr);
param.qualifiers[qual] = true;
}
c.templateParams.push_back(param);
auto value = tryParseStringValue(input, "Value: ", rootIndent + 2);
Type& type = parseType(input, rootIndent + 2);
TemplateParam param{type};
if (value)
param.value = value;
if (auto qualStr =
tryParseStringValue(input, "Qualifiers: ", rootIndent + 2);
qualStr) {
Qualifier qual = getQualifier(*qualStr);
param.qualifiers[qual] = true;
}
c.templateParams.push_back(param);
}
// No more params for us - put back the line we just read
input = origInput;

View File

@ -450,6 +450,7 @@ TEST_F(DrgnParserTest, ClassTemplateValue) {
[0] Struct: TemplatedClassVal<3> (size: 12)
Param
Value: 3
Primitive: int32_t
Member: arr (offset: 0)
[1] Array: (length: 3)
Primitive: int32_t
@ -463,12 +464,14 @@ TEST_F(DrgnParserTest, TemplateEnumValue) {
[0] Class: MyClass<ns_enums_params::MyNS::ScopedEnum::One> (size: 4)
Param
Value: ns_enums_params::MyNS::ScopedEnum::One
Enum: ScopedEnum (size: 4)
)",
R"(
[1] Pointer
[0] Class: MyClass<(ns_enums_params::MyNS::ScopedEnum)1> (size: 4)
Param
Value: ns_enums_params::MyNS::ScopedEnum::One
Enum: ScopedEnum (size: 4)
)");
}
@ -479,12 +482,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueGaps) {
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::Twenty> (size: 4)
Param
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
Enum: EnumWithGaps (size: 4)
)",
R"(
[1] Pointer
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)20> (size: 4)
Param
Value: ns_enums_params::MyNS::EnumWithGaps::Twenty
Enum: EnumWithGaps (size: 4)
)");
}
@ -495,12 +500,14 @@ TEST_F(DrgnParserTest, TemplateEnumValueNegative) {
[0] Class: ClassGaps<ns_enums_params::MyNS::EnumWithGaps::MinusTwo> (size: 4)
Param
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
Enum: EnumWithGaps (size: 4)
)",
R"(
[1] Pointer
[0] Class: ClassGaps<(ns_enums_params::MyNS::EnumWithGaps)-2> (size: 4)
Param
Value: ns_enums_params::MyNS::EnumWithGaps::MinusTwo
Enum: EnumWithGaps (size: 4)
)");
}

View File

@ -914,6 +914,7 @@ TEST(FlattenerTest, AllocatorUnfixableParentParamIsValue) {
[2] Struct: MyAllocBase (size: 1)
Param
Value: 123
Primitive: int32_t
Function: allocate
Function: deallocate
Function: allocate

View File

@ -205,14 +205,15 @@ TEST(NameGenTest, ContainerParamsValue) {
auto myenum = Enum{"MyEnum", 4};
auto mycontainer = getVector();
mycontainer.templateParams.push_back(TemplateParam{"123"});
mycontainer.templateParams.push_back(TemplateParam{"MyEnum::OptionC"});
mycontainer.templateParams.push_back(TemplateParam{myint, "123"});
mycontainer.templateParams.push_back(
TemplateParam{myenum, "MyEnum::OptionC"});
NameGen nameGen;
nameGen.generateNames({mycontainer});
EXPECT_EQ(myint.name(), "int32_t");
EXPECT_EQ(myenum.name(), "MyEnum");
EXPECT_EQ(myenum.name(), "MyEnum_0");
EXPECT_EQ(mycontainer.name(), "std::vector<123, MyEnum::OptionC>");
}

View File

@ -12,6 +12,7 @@ TEST(PruneTest, PruneClass) {
Primitive: int32_t
Param
Value: "123"
Primitive: int32_t
Parent (offset: 0)
[1] Class: MyParent (size: 4)
Member: a (offset: 0)

View File

@ -94,7 +94,8 @@ MyClass
TEST(TopoSorterTest, TemplateParamValue) {
auto myclass = Class{1, Class::Kind::Class, "MyClass", 69};
myclass.templateParams.push_back(TemplateParam{"123"});
auto myint = Primitive{Primitive::Kind::Int32};
myclass.templateParams.push_back(TemplateParam{myint, "123"});
test({myclass}, R"(
MyClass