From a347b7d63d1c20116b150ebd0af5f9214190ebbe Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 10 Apr 2024 12:27:32 +0200 Subject: [PATCH] Final Impls, DIBTH Identifier Impl not working --- include/phasar/ControlFlow/CallGraph.h | 5 - .../Passes/GeneralStatisticsAnalysis.h | 4 +- ... => GeneralStatisticsAnalysisSerializer.h} | 31 +--- .../PhasarLLVM/Pointer/LLVMAliasSetData.h | 3 +- .../TypeHierarchy/LLVMTypeHierarchy.h | 6 + .../TypeHierarchy/LLVMTypeHierarchyData.h | 1 + .../TypeHierarchy/LLVMVFTableData.h | 2 +- include/phasar/Pointer/AliasInfo.h | 11 +- .../Passes/GeneralStatisticsAnalysis.cpp | 54 +++---- .../Passes/GeneralStatisticsAnalysisData.cpp | 138 ------------------ .../GeneralStatisticsAnalysisSerializer.cpp | 43 ++++++ lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp | 12 +- lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp | 2 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 32 +++- .../TypeHierarchy/LLVMTypeHierarchy.cpp | 46 ++++++ lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp | 1 + .../TypeHierarchy/LLVMVFTableData.cpp | 2 +- .../Pointer/LLVMAliasSetSerializationTest.cpp | 10 ++ .../PhasarLLVM/TypeHierarchy/CMakeLists.txt | 1 + .../DIBasedTypeHierarchySerializationTest.cpp | 12 ++ .../LLVMTypeHierarchySerializationTest.cpp | 99 +++++++++++++ 21 files changed, 288 insertions(+), 227 deletions(-) rename include/phasar/PhasarLLVM/Passes/{GeneralStatisticsAnalysisData.h => GeneralStatisticsAnalysisSerializer.h} (54%) delete mode 100644 lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp create mode 100644 lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp create mode 100644 unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 6ae072a53..7751aa963 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -17,15 +17,10 @@ #include "phasar/Utils/StableVector.h" #include "phasar/Utils/Utilities.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Function.h" -#include "llvm/Support/raw_ostream.h" #include "nlohmann/json.hpp" -#include #include #include #include diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index 41b43294b..4f0e943b7 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -176,7 +176,9 @@ struct GeneralStatistics { "instead")]] const std::set & getRetResInstructions() const; - [[nodiscard]] [[deprecated("Please use printAsJson() instead")]] nlohmann::json getAsJson() const; + [[nodiscard]] [[deprecated( + "Please use printAsJson() instead")]] nlohmann::json + getAsJson() const; void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const; }; diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h similarity index 54% rename from include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h rename to include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h index fa4c18df7..f51a1b049 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h @@ -17,55 +17,30 @@ #include namespace psr { -struct GeneralStatisticsAnalysisData { +struct GeneralStatisticsAnalysisSerializer { size_t Functions = 0; size_t ExternalFunctions = 0; size_t FunctionDefinitions = 0; size_t AddressTakenFunctions = 0; size_t Globals = 0; size_t GlobalConsts = 0; - size_t ExternalGlobals = 0; - size_t GlobalsDefinitions = 0; size_t BasicBlocks = 0; - size_t AllocationSites = 0; size_t CallSites = 0; size_t DebugIntrinsics = 0; size_t Instructions = 0; - size_t StoreInstructions = 0; - size_t LoadInstructions = 0; size_t MemIntrinsics = 0; size_t Branches = 0; - size_t Switches = 0; size_t GetElementPtrs = 0; size_t LandingPads = 0; size_t PhiNodes = 0; size_t NumInlineAsm = 0; size_t IndCalls = 0; - size_t TotalNumOperands = 0; - size_t TotalNumUses = 0; - size_t TotalNumPredecessorBBs = 0; - size_t TotalNumSuccessorBBs = 0; - size_t MaxNumOperands = 0; - size_t MaxNumUses = 0; - size_t MaxNumPredecessorBBs = 0; - size_t MaxNumSuccessorBBs = 0; - size_t NumInstWithMultipleUses = 0; - size_t NumInstsUsedOutsideBB = 0; size_t NonVoidInsts = 0; - // const llvm::Type * , serialized with MetadataID - std::set AllocatedTypes; - // const llvm::Instruction * , serialized with MetadataID - std::set AllocaInstructions; - // const llvm::Instruction * , serialized with MetadataID - std::set RetResInstructions; + size_t NumberOfAllocaInstructions = 0; std::string ModuleName{}; - GeneralStatisticsAnalysisData() noexcept = default; + GeneralStatisticsAnalysisSerializer() noexcept = default; void printAsJson(llvm::raw_ostream &OS); - - static GeneralStatisticsAnalysisData deserializeJson(const llvm::Twine &Path); - static GeneralStatisticsAnalysisData - loadJsonString(llvm::StringRef JsonAsString); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h index 41c52eb81..bf924e39c 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h @@ -16,8 +16,7 @@ namespace psr { struct LLVMAliasSetData { - // AliasSets - std::vector AliasSets; + std::vector> AliasSets; std::vector AnalyzedFunctions; LLVMAliasSetData() noexcept = default; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index d3f4b0b8e..b075e427e 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -142,6 +142,8 @@ class LLVMTypeHierarchy * @param IRDB ProjectIRCompiledDB object. */ LLVMTypeHierarchy(LLVMProjectIRDB &IRDB); + LLVMTypeHierarchy(LLVMProjectIRDB &IRDB, + const LLVMTypeHierarchyData &SerializedData); /** * @brief Creates a LLVMStructTypeHierarchy based on the @@ -195,6 +197,10 @@ class LLVMTypeHierarchy [[nodiscard]] bool hasVFTable(const llvm::StructType *Type) const override; + [[nodiscard]] const auto &getAllVTables() const noexcept { + return TypeVFTMap; + } + [[nodiscard]] const LLVMVFTable * getVFTable(const llvm::StructType *Type) const override; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h index b93ebe65e..b9757d0b3 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h @@ -18,6 +18,7 @@ namespace psr { struct LLVMTypeHierarchyData { std::string PhasarConfigJsonTypeHierarchyID; + // key = vertex, value = edges llvm::StringMap> TypeGraph; LLVMTypeHierarchyData() noexcept = default; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h index 66360c248..e3997d9f5 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h @@ -19,7 +19,7 @@ struct LLVMVFTableData { std::vector VFT; LLVMVFTableData() noexcept = default; - void printAsJson(llvm::raw_ostream &OS); + void printAsJson(llvm::raw_ostream &OS) const; static LLVMVFTableData deserializeJson(const llvm::Twine &Path); static LLVMVFTableData loadJsonString(llvm::StringRef JsonAsString); diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index 1d3dc2990..ba9fa480f 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -241,16 +241,7 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { static_cast(AA)->print(OS); }, [](const void *AA) { - /// TODO: - /// durchlesen, wie type traits in c++ funktionieren - /// ->in aliasinfo.h checken ob getAsJson existiert, ansonsten leeres - /// JSON - - if (static_cast(AA)->getAsJson()) { - return static_cast(AA)->getAsJson(); - } - - return nlohmann::json(); + return static_cast(AA)->getAsJson(); }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 67ab2dca5..8c50b63ba 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -9,7 +9,7 @@ #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" -#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h" +#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/PAMMMacros.h" @@ -288,36 +288,30 @@ GeneralStatistics::getRetResInstructions() const { return RetResInstructions; } -/// TODO: Fabian fragen, welche Impl hier zu verwenden ist. -/// Alte Impl: -/* -nlohmann::json GeneralStatistics::getAsJson() const { - nlohmann::json J; - J["ModuleName"] = ModuleName; - J["Instructions"] = Instructions; - J["Functions"] = Functions; - J["ExternalFunctions"] = ExternalFunctions; - J["FunctionDefinitions"] = FunctionDefinitions; - J["AddressTakenFunctions"] = AddressTakenFunctions; - J["AllocaInstructions"] = AllocaInstructions.size(); - J["CallSites"] = CallSites; - J["IndirectCallSites"] = IndCalls; - J["MemoryIntrinsics"] = MemIntrinsics; - J["DebugIntrinsics"] = DebugIntrinsics; - J["InlineAssembly"] = NumInlineAsm; - J["GlobalVariables"] = Globals; - J["Branches"] = Branches; - J["GetElementPtrs"] = GetElementPtrs; - J["BasicBlocks"] = BasicBlocks; - J["PhiNodes"] = PhiNodes; - J["LandingPads"] = LandingPads; - J["GlobalConsts"] = GlobalConsts; - return J; -} -*/ void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { - GeneralStatisticsAnalysisData Data; - Data.printAsJson(OS); + GeneralStatisticsAnalysisSerializer Ser; + + Ser.Functions = Functions; + Ser.ExternalFunctions = ExternalFunctions; + Ser.FunctionDefinitions = FunctionDefinitions; + Ser.AddressTakenFunctions = AddressTakenFunctions; + Ser.Globals = Globals; + Ser.GlobalConsts = GlobalConsts; + Ser.BasicBlocks = BasicBlocks; + Ser.CallSites = CallSites; + Ser.DebugIntrinsics = DebugIntrinsics; + Ser.Instructions = Instructions; + Ser.MemIntrinsics = MemIntrinsics; + Ser.Branches = Branches; + Ser.GetElementPtrs = GetElementPtrs; + Ser.LandingPads = LandingPads; + Ser.PhiNodes = PhiNodes; + Ser.NumInlineAsm = NumInlineAsm; + Ser.IndCalls = IndCalls; + Ser.NumberOfAllocaInstructions = AllocaInstructions.size(); + Ser.ModuleName = ModuleName; + + Ser.printAsJson(OS); } nlohmann::json GeneralStatistics::getAsJson() const { diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp deleted file mode 100644 index 2adad5aba..000000000 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2024 Fabian Schiebel. - * All rights reserved. This program and the accompanying materials are made - * available under the terms of LICENSE.txt. - * - * Contributors: - * Maximilian Leo Huber and others - *****************************************************************************/ - -#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h" - -#include "phasar/Utils/IO.h" -#include "phasar/Utils/NlohmannLogging.h" - -namespace psr { - -static GeneralStatisticsAnalysisData -getDataFromJson(const nlohmann::json &Json) { - GeneralStatisticsAnalysisData Data; - - Data.Functions = Json["Functions"]; - Data.ExternalFunctions = Json["ExternalFunctions"]; - Data.FunctionDefinitions = Json["FunctionDefinitions"]; - Data.AddressTakenFunctions = Json["AddressTakenFunctions"]; - Data.Globals = Json["Globals"]; - Data.GlobalConsts = Json["GlobalConsts"]; - Data.ExternalGlobals = Json["ExternalGlobals"]; - Data.BasicBlocks = Json["BasicBlocks"]; - Data.AllocationSites = Json["AllocationSites"]; - Data.CallSites = Json["CallSites"]; - Data.DebugIntrinsics = Json["DebugIntrinsics"]; - Data.Instructions = Json["Instructions"]; - Data.StoreInstructions = Json["StoreInstructions"]; - Data.LoadInstructions = Json["LoadInstructions"]; - Data.MemIntrinsics = Json["MemIntrinsics"]; - Data.Branches = Json["Branches"]; - Data.Switches = Json["Switches"]; - Data.GetElementPtrs = Json["GetElementPtrs"]; - Data.LandingPads = Json["LandingPads"]; - Data.PhiNodes = Json["PhiNodes"]; - Data.NumInlineAsm = Json["NumInlineAsm"]; - Data.IndCalls = Json["IndCalls"]; - Data.TotalNumOperands = Json["TotalNumOperands"]; - Data.TotalNumUses = Json["TotalNumUses"]; - Data.TotalNumPredecessorBBs = Json["TotalNumPredecessorBBs"]; - Data.TotalNumSuccessorBBs = Json["TotalNumSuccessorBBs"]; - Data.MaxNumOperands = Json["MaxNumOperands"]; - Data.MaxNumUses = Json["MaxNumUses"]; - Data.MaxNumPredecessorBBs = Json["MaxNumPredecessorBBs"]; - Data.MaxNumSuccessorBBs = Json["MaxNumSuccessorBBs"]; - Data.NumInstWithMultipleUses = Json["NumInstWithMultipleUses"]; - Data.NumInstsUsedOutsideBB = Json["NumInstsUsedOutsideBB"]; - Data.NonVoidInsts = Json["NonVoidInsts"]; - - for (const auto &Curr : Json["AllocatedTypes"]) { - Data.AllocatedTypes.insert(Curr.get()); - } - - for (const auto &Curr : Json["AllocaInstructions"]) { - Data.AllocaInstructions.insert(Curr.get()); - } - - for (const auto &Curr : Json["RetResInstructions"]) { - Data.RetResInstructions.insert(Curr.get()); - } - - Data.ModuleName = Json["ModuleName"]; - - return Data; -} - -void GeneralStatisticsAnalysisData::printAsJson(llvm::raw_ostream &OS) { - nlohmann::json Json; - - Json["Functions"] = Functions; - Json["ExternalFunctions"] = ExternalFunctions; - Json["FunctionDefinitions"] = FunctionDefinitions; - Json["AddressTakenFunctions"] = AddressTakenFunctions; - Json["Globals"] = Globals; - Json["GlobalConsts"] = GlobalConsts; - Json["ExternalGlobals"] = ExternalGlobals; - Json["BasicBlocks"] = BasicBlocks; - Json["AllocationSites"] = AllocationSites; - Json["CallSites"] = CallSites; - Json["DebugIntrinsics"] = DebugIntrinsics; - Json["Instructions"] = Instructions; - Json["StoreInstructions"] = StoreInstructions; - Json["LoadInstructions"] = LoadInstructions; - Json["MemIntrinsics"] = MemIntrinsics; - Json["Branches"] = Branches; - Json["Switches"] = Switches; - Json["GetElementPtrs"] = GetElementPtrs; - Json["LandingPads"] = LandingPads; - Json["PhiNodes"] = PhiNodes; - Json["NumInlineAsm"] = NumInlineAsm; - Json["IndCalls"] = IndCalls; - Json["TotalNumOperands"] = TotalNumOperands; - Json["TotalNumUses"] = TotalNumUses; - Json["TotalNumPredecessorBBs"] = TotalNumPredecessorBBs; - Json["TotalNumSuccessorBBs"] = TotalNumSuccessorBBs; - Json["MaxNumOperands"] = MaxNumOperands; - Json["MaxNumUses"] = MaxNumUses; - Json["MaxNumPredecessorBBs"] = MaxNumPredecessorBBs; - Json["MaxNumSuccessorBBs"] = MaxNumSuccessorBBs; - Json["NumInstWithMultipleUses"] = NumInstWithMultipleUses; - Json["NumInstsUsedOutsideBB"] = NumInstsUsedOutsideBB; - Json["NonVoidInsts"] = NonVoidInsts; - - for (const auto &Curr : AllocatedTypes) { - Json["AllocatedTypes"].push_back(Curr); - } - - for (const auto &Curr : AllocaInstructions) { - Json["AllocaInstructions"].push_back(Curr); - } - - for (const auto &Curr : RetResInstructions) { - Json["RetResInstructions"].push_back(Curr); - } - - Json["ModuleName"] = ModuleName; - - OS << Json; -} - -GeneralStatisticsAnalysisData -GeneralStatisticsAnalysisData::deserializeJson(const llvm::Twine &Path) { - return getDataFromJson(readJsonFile(Path)); -} - -GeneralStatisticsAnalysisData -GeneralStatisticsAnalysisData::loadJsonString(llvm::StringRef JsonAsString) { - nlohmann::json Data = - nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); - return getDataFromJson(Data); -} - -} // namespace psr diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp new file mode 100644 index 000000000..ffc971580 --- /dev/null +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp @@ -0,0 +1,43 @@ +/****************************************************************************** + * Copyright (c) 2024 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Maximilian Leo Huber and others + *****************************************************************************/ + +#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h" + +#include "phasar/Utils/IO.h" +#include "phasar/Utils/NlohmannLogging.h" + +namespace psr { + +void GeneralStatisticsAnalysisSerializer::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json Json; + + Json["Functions"] = Functions; + Json["ExternalFunctions"] = ExternalFunctions; + Json["FunctionDefinitions"] = FunctionDefinitions; + Json["AddressTakenFunctions"] = AddressTakenFunctions; + Json["Globals"] = Globals; + Json["GlobalConsts"] = GlobalConsts; + Json["BasicBlocks"] = BasicBlocks; + Json["CallSites"] = CallSites; + Json["DebugIntrinsics"] = DebugIntrinsics; + Json["Instructions"] = Instructions; + Json["MemIntrinsics"] = MemIntrinsics; + Json["Branches"] = Branches; + Json["GetElementPtrs"] = GetElementPtrs; + Json["LandingPads"] = LandingPads; + Json["PhiNodes"] = PhiNodes; + Json["NumInlineAsm"] = NumInlineAsm; + Json["IndCalls"] = IndCalls; + Json["NonVoidInsts"] = NonVoidInsts; + Json["ModuleName"] = ModuleName; + + OS << Json; +} + +} // namespace psr diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp index 850c7cec6..3fad1896d 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -727,10 +727,11 @@ LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { LLVMAliasSetData Data; /// Serialize the AliasSets - auto &Sets = Data.AliasSets; + auto &AliasSetsDataPosition = Data.AliasSets.emplace_back(); for (const AliasSetTy *PTS : Owner.getAllAliasSets()) { - auto PtsJson = nlohmann::json::array(); + + std::vector PtsJson{}; for (const auto *Alias : *PTS) { auto Id = getMetaDataID(Alias); if (Id != "-1") { @@ -738,14 +739,15 @@ LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { } } if (!PtsJson.empty()) { - Sets.push_back(std::move(PtsJson)); + for (const auto &Curr : PtsJson) { + AliasSetsDataPosition.push_back(Curr); + } } } /// Serialize the AnalyzedFunctions - auto &Fns = Data.AnalyzedFunctions; for (const auto *F : AnalyzedFunctions) { - Fns.push_back(F->getName().str()); + Data.AnalyzedFunctions.push_back(F->getName().str()); } return Data; diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp index 37c4280b0..d9831d361 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp @@ -18,7 +18,7 @@ static LLVMAliasSetData getDataFromJson(const nlohmann::json &Json) { LLVMAliasSetData Data; for (const auto &Value : Json["AliasSets"]) { - Data.AliasSets.push_back(Value.get()); + Data.AliasSets.push_back(Value.get>()); } for (const auto &Value : Json["AnalyzedFunctions"]) { diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index d65e9dc82..e1b4934d7 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -204,8 +204,12 @@ stringToDICompositeType(const LLVMProjectIRDB *IRDB, DIF.processModule(*Module); for (const auto &Type : DIF.types()) { - if (Type->getName() == DITypeName) { - if (const auto *DICT = llvm::dyn_cast(Type)) { + if (const auto *DICT = llvm::dyn_cast(Type)) { + if (DICT->getName() == DITypeName) { + return DICT; + } + + if (DICT->getIdentifier() == DITypeName) { return DICT; } } @@ -352,7 +356,6 @@ DIBasedTypeHierarchy::getAsJson() const { DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; - for (const auto &Curr : NameToType) { Data.NameToType.try_emplace(Curr.getKey().str(), Curr.getValue()->getName().str()); @@ -365,8 +368,27 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { int Counter = 0; for (const auto &Curr : VertexTypes) { - Data.VertexTypes.push_back(Curr->getName().str()); - Counter++; + if (!Curr) { + Data.VertexTypes.emplace_back(""); + llvm::errs() << "VertexType is null\n"; + } + + if (!Curr->getName().empty()) { + Data.VertexTypes.push_back(Curr->getName().str()); + Counter++; + llvm::outs() << "NAME: " << Curr->getName() << "\n"; + continue; + } + + if (!Curr->getIdentifier().empty()) { + Data.VertexTypes.push_back(Curr->getIdentifier().str()); + Counter++; + llvm::outs() << "IDENTIFIER: " << Curr->getIdentifier() << "\n"; + continue; + } + + Data.VertexTypes.emplace_back(""); + llvm::errs() << "VertexType has no valid name or identifier\n"; } llvm::outs() << "getTypeHierarchyData: " << Counter << "\n"; llvm::outs().flush(); diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp index 7ae3efc60..fbe3fd506 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp @@ -24,8 +24,10 @@ #include "phasar/Utils/PAMMMacros.h" #include "phasar/Utils/Utilities.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Demangle/Demangle.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/InstIterator.h" @@ -73,6 +75,50 @@ LLVMTypeHierarchy::LLVMTypeHierarchy(LLVMProjectIRDB &IRDB) { buildLLVMTypeHierarchy(*IRDB.getModule()); } +LLVMTypeHierarchy::LLVMTypeHierarchy( + LLVMProjectIRDB &IRDB, const LLVMTypeHierarchyData &SerializedData) { + const auto &IRDBModule = IRDB.getModule(); + + VisitedModules.insert(IRDBModule); + auto StructTypes = IRDBModule->getIdentifiedStructTypes(); + + llvm::StringMap NameToStructType; + for (const auto &SerElement : SerializedData.TypeGraph) { + bool MatchFound = false; + + for (const auto &StructTypeElement : StructTypes) { + if (SerElement.getKey() == StructTypeElement->getName()) { + NameToStructType.try_emplace(SerElement.getKey(), StructTypeElement); + MatchFound = true; + break; + } + } + + if (!MatchFound) { + llvm::errs() << "No matching StructType found for Type with name: " + << SerElement.getKey(); + } + } + + // add all vertices + for (const auto &Curr : NameToStructType) { + const auto &StructType = Curr.getValue(); + auto Vertex = boost::add_vertex(TypeGraph); + TypeGraph[Vertex] = VertexProperties(StructType); + TypeVFTMap[StructType] = getVirtualFunctions(*IRDBModule, *StructType); + } + + // add all edges + for (auto *StructType : StructTypes) { + // use type information to check if it is really a subtype + auto SubTypes = getSubTypes(*IRDBModule, *StructType); + for (const auto *SubType : SubTypes) { + boost::add_edge(TypeVertexMap[SubType], TypeVertexMap[StructType], + TypeGraph); + } + } +} + LLVMTypeHierarchy::LLVMTypeHierarchy(const llvm::Module &M) { PHASAR_LOG_LEVEL_CAT(INFO, "LLVMTypeHierarchy", "Construct type hierarchy"); buildLLVMTypeHierarchy(M); diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp index 547c69a10..6034e2357 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp @@ -56,6 +56,7 @@ nlohmann::json LLVMVFTable::getAsJson() const { LLVMVFTableData Data; for (const auto &Curr : VFT) { + /// TODO: check if Curr null Data.VFT.push_back(Curr->getName().str()); } diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp index 272500dda..65f1095dd 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp @@ -24,7 +24,7 @@ static LLVMVFTableData getDataFromJson(const nlohmann::json &Json) { return Data; } -void LLVMVFTableData::printAsJson(llvm::raw_ostream &OS) { +void LLVMVFTableData::printAsJson(llvm::raw_ostream &OS) const { nlohmann::json JSON; for (const auto &Curr : VFT) { diff --git a/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp b/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp index 1da745937..17d94c767 100644 --- a/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp +++ b/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp @@ -89,6 +89,16 @@ static void analyze(llvm::StringRef File, const GroundTruthTy &Gt, LLVMAliasSet Deser(&IRDB, Ser); checkDeser(*IRDB.getModule(), PTS, Deser); + + // printAsJson serialization + std::string SerString; + llvm::raw_string_ostream StringStream(SerString); + PTS.printAsJson(StringStream); + nlohmann::json PrintAsJsonSer = nlohmann::json::parse(SerString); + checkSer(PrintAsJsonSer, Gt); + + LLVMAliasSet PrintAsJsonDeser(&IRDB, PrintAsJsonSer); + checkDeser(*IRDB.getModule(), PTS, PrintAsJsonDeser); } TEST(LLVMAliasSetSerializationTest, Ser_Intra01) { diff --git a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt index 2432ec447..d4407ecef 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt +++ b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt @@ -1,6 +1,7 @@ set(PointerSources DIBasedTypeHierarchySerializationTest.cpp DIBasedTypeHierarchyTest.cpp + LLVMTypeHierarchySerializationTest.cpp LLVMTypeHierarchyTest.cpp TypeGraphTest.cpp ) diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 871055034..4a5c132ef 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -24,6 +24,18 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { + + llvm::outs() << "Original\n"; + for (const auto &Curr : Orig.getAllTypes()) { + Curr->print(llvm::outs()); + llvm::outs() << "\n"; + } + + llvm::outs() << "Deser\n"; + for (const auto &Curr : Deser.getAllTypes()) { + Curr->print(llvm::outs()); + llvm::outs() << "\n"; + } ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp new file mode 100644 index 000000000..3b3c424e6 --- /dev/null +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -0,0 +1,99 @@ + +#include "phasar/Config/Configuration.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h" +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/Utilities.h" + +#include "llvm/ADT/StringRef.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +using namespace psr; + +/* ============== TEST FIXTURE ============== */ +class LLVMTypeHierarchySerialization + : public ::testing::TestWithParam { +protected: + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("type_hierarchies/"); + const std::vector EntryPoints = {"main"}; + +}; // Test Fixture + +void compareResults(const psr::LLVMTypeHierarchy &Orig, + const psr::LLVMTypeHierarchy &Deser) { + ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); + ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); + + for (const auto &OrigCurrentType : Orig.getAllTypes()) { + EXPECT_EQ(OrigCurrentType, Deser.getType(OrigCurrentType->getName().str())); + + for (const auto &CurrVFunc : + Orig.getVFTable(OrigCurrentType)->getAllFunctions()) { + bool FoundFunction = false; + for (const auto &DeserFunc : + Deser.getVFTable(OrigCurrentType)->getAllFunctions()) { + if (DeserFunc) { + if (CurrVFunc) { + if (DeserFunc->getName() == CurrVFunc->getName()) { + FoundFunction = true; + break; + } + } + } else { + // This case is for a function that has no caller + if (!CurrVFunc) { + FoundFunction = true; + break; + } + } + } + EXPECT_TRUE(FoundFunction); + } + } +} + +TEST_P(LLVMTypeHierarchySerialization, OrigAndDeserEqual) { + using namespace std::string_literals; + + psr::LLVMProjectIRDB IRDB(PathToLlFiles + GetParam()); + psr::LLVMTypeHierarchy TypeHierarchy(IRDB); + + std::string Ser; + llvm::raw_string_ostream StringStream(Ser); + + TypeHierarchy.printAsJson(StringStream); + + psr::LLVMTypeHierarchy DeserializedTypeHierarchy( + IRDB, psr::LLVMTypeHierarchyData::loadJsonString(Ser)); + + compareResults(TypeHierarchy, DeserializedTypeHierarchy); +} + +static constexpr std::string_view TypeHierarchyTestFiles[] = { + "type_hierarchy_1_cpp_dbg.ll", "type_hierarchy_2_cpp_dbg.ll", + "type_hierarchy_3_cpp_dbg.ll", "type_hierarchy_4_cpp_dbg.ll", + "type_hierarchy_5_cpp_dbg.ll", "type_hierarchy_6_cpp_dbg.ll", + "type_hierarchy_7_cpp_dbg.ll", "type_hierarchy_7_b_cpp_dbg.ll", + "type_hierarchy_8_cpp_dbg.ll", "type_hierarchy_9_cpp_dbg.ll", + "type_hierarchy_10_cpp_dbg.ll", "type_hierarchy_11_cpp_dbg.ll", + "type_hierarchy_12_cpp_dbg.ll", "type_hierarchy_12_b_cpp_dbg.ll", + "type_hierarchy_12_c_cpp_dbg.ll", "type_hierarchy_13_cpp_dbg.ll", + "type_hierarchy_14_cpp_dbg.ll", "type_hierarchy_15_cpp_dbg.ll", + "type_hierarchy_16_cpp_dbg.ll", "type_hierarchy_17_cpp_dbg.ll", + "type_hierarchy_18_cpp_dbg.ll", "type_hierarchy_19_cpp_dbg.ll", + "type_hierarchy_20_cpp_dbg.ll", "type_hierarchy_21_cpp_dbg.ll", +}; + +INSTANTIATE_TEST_SUITE_P(LLVMTypeHierarchySerializationTest, + LLVMTypeHierarchySerialization, + ::testing::ValuesIn(TypeHierarchyTestFiles)); + +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + auto Res = RUN_ALL_TESTS(); + return Res; +}