From fe605e90b46849c8a6457f50886be23e77f67dcf Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 19:01:19 +0200 Subject: [PATCH] Refactor handling of DI type names --- .../TypeHierarchy/DIBasedTypeHierarchy.h | 4 +- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 2 - .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 86 +++++++------------ .../DIBasedTypeHierarchyData.cpp | 51 +++-------- .../DIBasedTypeHierarchySerializationTest.cpp | 9 +- 5 files changed, 50 insertions(+), 102 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index c6efe7310..b1bc594ed 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -70,9 +70,7 @@ class DIBasedTypeHierarchy [[nodiscard]] const auto &getAllVTables() const noexcept { return VTables; } - [[nodiscard]] std::string getTypeName(ClassType Type) const override { - return Type->getName().str(); - } + [[nodiscard]] std::string getTypeName(ClassType Type) const override; [[nodiscard]] bool hasVFTable(ClassType Type) const override; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index ff352b917..93672e59a 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -22,9 +22,7 @@ struct DIBasedTypeHierarchyData { // DITypes and llvm::Function * are serialized by serializing their names and // using the DebugInfoFinder to deserialize them - llvm::StringMap NameToType; llvm::StringMap TypeToVertex; - std::vector VertexTypes; std::vector> TransitiveDerivedIndex; std::vector Hierarchy; std::vector> VTables; diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 86b0e0e44..82b0550c6 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -165,6 +165,11 @@ static void buildTypeHierarchy( } } +static llvm::StringRef getCompositeTypeName(const llvm::DICompositeType *Ty) { + auto Name = Ty->getName(); + return Name.empty() ? Ty->getIdentifier() : Name; +} + DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { // -- Find all types { @@ -193,7 +198,9 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { } TypeToVertex.try_emplace(Composite, VertexTypes.size()); VertexTypes.push_back(Composite); - NameToType.try_emplace(Composite->getName(), Composite); + NameToType.try_emplace(getCompositeTypeName(Composite), Composite); + + assert(!getCompositeTypeName(Composite).empty()); } } @@ -218,7 +225,7 @@ stringToDICompositeType(const LLVMProjectIRDB *IRDB, const auto *Module = IRDB->getModule(); DIF.processModule(*Module); - for (const auto &Type : DIF.types()) { + for (const auto *Type : DIF.types()) { if (const auto *DICT = llvm::dyn_cast(Type)) { if (DICT->getName() == DITypeName) { return DICT; @@ -239,7 +246,7 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, const auto *Module = IRDB->getModule(); DIF.processModule(*Module); - for (const auto &Type : DIF.types()) { + for (const auto *Type : DIF.types()) { if (Type) { if (Type->getName() == DITypeName) { if (const auto *DIT = llvm::dyn_cast(Type)) { @@ -253,44 +260,32 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, } DIBasedTypeHierarchy::DIBasedTypeHierarchy( - const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchyData &SerializedData) { - - int Counter = 0; - VertexTypes.reserve(SerializedData.VertexTypes.size()); - - for (const auto &Curr : SerializedData.VertexTypes) { - VertexTypes.push_back(stringToDICompositeType(IRDB, Curr)); - Counter++; - } - - for (const auto &Curr : SerializedData.NameToType) { - NameToType.try_emplace(Curr.getKey(), - stringToDIType(IRDB, Curr.getValue())); - } + const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) + : TransitiveDerivedIndex(SerializedData.TransitiveDerivedIndex) { + VertexTypes.resize(SerializedData.TypeToVertex.size()); + TypeToVertex.reserve(SerializedData.TypeToVertex.size()); for (const auto &Curr : SerializedData.TypeToVertex) { - TypeToVertex.try_emplace(stringToDIType(IRDB, Curr.getKey()), - Curr.getValue()); - } - - for (const auto &Curr : SerializedData.TransitiveDerivedIndex) { - TransitiveDerivedIndex.emplace_back( - std::pair(Curr.first, Curr.second)); + const auto *Ty = stringToDICompositeType(IRDB, Curr.getKey()); + TypeToVertex.try_emplace(Ty, Curr.getValue()); + NameToType.try_emplace(Curr.getKey(), Ty); + VertexTypes.at(Curr.getValue()) = Ty; } + Hierarchy.reserve(SerializedData.Hierarchy.size()); for (const auto &Curr : SerializedData.Hierarchy) { Hierarchy.push_back(stringToDIType(IRDB, Curr)); } for (const auto &Curr : SerializedData.VTables) { - LLVMVFTable CurrVTable = LLVMVFTable(); + std::vector CurrVTable; + CurrVTable.reserve(Curr.size()); for (const auto &FuncName : Curr) { - CurrVTable.VFT.push_back(IRDB->getFunction(FuncName)); + CurrVTable.push_back(IRDB->getFunction(FuncName)); } - VTables.push_back(std::move(CurrVTable)); + VTables.emplace_back(std::move(CurrVTable)); } } @@ -323,6 +318,13 @@ auto DIBasedTypeHierarchy::subTypesOf(ClassType Ty) const noexcept llvm::report_fatal_error("Not implemented"); } +std::string DIBasedTypeHierarchy::getTypeName(ClassType Type) const { + if (const auto *CT = llvm::dyn_cast(Type)) { + return getCompositeTypeName(CT).str(); + } + return Type->getName().str(); +} + [[nodiscard]] bool DIBasedTypeHierarchy::hasVFTable(ClassType Type) const { const auto *StructTy = llvm::dyn_cast(Type); return StructTy && StructTy->getVTableHolder(); @@ -365,34 +367,10 @@ DIBasedTypeHierarchy::getAsJson() const { DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; - for (const auto &Curr : NameToType) { - Data.NameToType.try_emplace(Curr.getKey(), - Curr.getValue()->getName().str()); - } for (const auto &Curr : TypeToVertex) { - Data.TypeToVertex.try_emplace(Curr.getFirst()->getName(), Curr.getSecond()); - } - - Data.VertexTypes.reserve(VertexTypes.size()); - for (const auto &Curr : VertexTypes) { - if (!Curr) { - Data.VertexTypes.emplace_back(""); - llvm::errs() << "VertexType is null\n"; - } - - if (!Curr->getName().empty()) { - Data.VertexTypes.push_back(Curr->getName().str()); - continue; - } - - if (!Curr->getIdentifier().empty()) { - Data.VertexTypes.push_back(Curr->getIdentifier().str()); - continue; - } - - Data.VertexTypes.emplace_back(""); - llvm::errs() << "VertexType has no valid name or identifier\n"; + Data.TypeToVertex.try_emplace(getTypeName(Curr.getFirst()), + Curr.getSecond()); } Data.TransitiveDerivedIndex = TransitiveDerivedIndex; diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index b7eef8f8c..0d6ae0701 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -23,30 +23,15 @@ namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { DIBasedTypeHierarchyData Data; - for (const auto &[Key, Value] : - Json["NameToType"].get()) { - Data.NameToType.try_emplace(Key, Value.get()); - } - - for (const auto &[Key, Value] : - Json["TypeToVertex"].get()) { + for (const auto &[Key, Value] : Json["TypeToVertex"].items()) { Data.TypeToVertex.try_emplace(Key, Value.get()); } - int Counter = 0; - for (const auto &Value : Json["VertexTypes"]) { - Data.VertexTypes.push_back(Value.get()); - Counter++; - } - - for (const auto &CurrPair : Json["TransitiveDerivedIndex"]) { - Data.TransitiveDerivedIndex.emplace_back(CurrPair[0].get(), - CurrPair[1].get()); - } + Data.TransitiveDerivedIndex = + Json["TransitiveDerivedIndex"] + .get>>(); - for (const auto &Value : Json["Hierarchy"]) { - Data.Hierarchy.push_back(Value.get()); - } + Data.Hierarchy = Json["Hierarchy"].get>(); for (const auto &CurrVTable : Json["VTables"]) { auto &DataPos = Data.VTables.emplace_back(); @@ -62,32 +47,18 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json Json; - for (const auto &Curr : NameToType) { - Json["NameToType"][Curr.getKey()] = Curr.getValue(); - } - + auto &JTypeToVertex = Json["TypeToVertex"]; for (const auto &Curr : TypeToVertex) { - Json["TypeToVertex"][Curr.getKey()] = Curr.getValue(); - } - - int Counter = 0; - for (const auto &Curr : VertexTypes) { - Json["VertexTypes"].push_back(Curr); - Counter++; + JTypeToVertex[Curr.getKey()] = Curr.getValue(); } - int Number = 0; - for (const auto &Curr : TransitiveDerivedIndex) { - Json["TransitiveDerivedIndex"][Number].push_back(Curr.first); - Json["TransitiveDerivedIndex"][Number++].push_back(Curr.second); - } + Json["TransitiveDerivedIndex"] = TransitiveDerivedIndex; - for (const auto &Curr : Hierarchy) { - Json["Hierarchy"].push_back(Curr); - } + Json["Hierarchy"] = Hierarchy; + auto &JVTables = Json["VTables"]; for (const auto &CurrVTable : VTables) { - auto &DataPos = Json["VTables"].emplace_back(); + auto &DataPos = JVTables.emplace_back(); for (const auto &CurrVFunc : CurrVTable) { DataPos.push_back(CurrVFunc); diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 86d706bc4..1816a753e 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -28,9 +28,12 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, EXPECT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); EXPECT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); - for (const auto &OrigCurrentType : Orig.getAllTypes()) { - EXPECT_EQ(OrigCurrentType->getName(), - Deser.getType(OrigCurrentType->getName().str())->getName()); + for (const auto *OrigCurrentType : Orig.getAllTypes()) { + + const auto *DeserTy = Deser.getType(Orig.getTypeName(OrigCurrentType)); + EXPECT_EQ(OrigCurrentType, DeserTy) + << "Mismatched types: Orig " << Orig.getTypeName(OrigCurrentType) + << " vs Deser: " << Deser.getTypeName(DeserTy); for (const auto &CurrVFunc : Orig.getVFTable(OrigCurrentType)->getAllFunctions()) {