From d3b3172fa16b0144fe0a12640e081d28987da338 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 13 Mar 2024 23:56:10 +0100 Subject: [PATCH 01/42] unresolved ref to F/NToString --- include/phasar/ControlFlow/CallGraph.h | 34 +++ include/phasar/ControlFlow/CallGraphData.h | 32 ++ include/phasar/ControlFlow/ICFGBase.h | 6 + .../ControlFlow/LLVMBasedBackwardICFG.h | 1 + .../PhasarLLVM/ControlFlow/LLVMBasedICFG.h | 1 + lib/ControlFlow/CallGraphData.cpp | 27 ++ .../ControlFlow/LLVMBasedBackwardICFG.cpp | 4 + lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp | 4 + .../PhasarLLVM/ControlFlow/CMakeLists.txt | 1 + .../ControlFlow/LLVMICFGPrintAsJsonTest.cpp | 279 ++++++++++++++++++ 10 files changed, 389 insertions(+) create mode 100644 include/phasar/ControlFlow/CallGraphData.h create mode 100644 lib/ControlFlow/CallGraphData.cpp create mode 100644 unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 590b16964..ffe9d8446 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -11,14 +11,18 @@ #define PHASAR_CONTROLFLOW_CALLGRAPH_H #include "phasar/ControlFlow/CallGraphBase.h" +#include "phasar/ControlFlow/CallGraphData.h" #include "phasar/Utils/ByRef.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/Printer.h" #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" @@ -86,6 +90,36 @@ class CallGraph : public CallGraphBase> { [[nodiscard]] bool empty() const noexcept { return CallersOf.empty(); } + void stringifyFunctionVertexTy(const FunctionVertexTy &FuncVal, + std::vector &Container) const { + for (const auto &Curr : FuncVal) { + Container.push_back(NToString(Curr)); + } + } + + void stringifyCallersOf(CallGraphData &Container) const { + for (const auto &Curr : CallersOf) { + std::string FValueString = (FToString(Curr.first)).str(); + + std::vector FunctionVertexTyString; + stringifyFunctionVertexTy(*Curr.second, FunctionVertexTyString); + + CallersOfData COData; + COData.FToFunctionVertexTy.insert( + {std::move(FValueString), std::move(FunctionVertexTyString)}); + Container.CallersOf.push_back(std::move(COData)); + } + } + + template + void printAsJson(llvm::raw_ostream &OS) const { + CallGraphData CGData; + + stringifyCallersOf(CGData); + + CGData.printAsJson(OS); + } + /// Creates a JSON representation of this call-graph suitable for presistent /// storage. /// Use the ctor taking a json object for deserialization diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h new file mode 100644 index 000000000..c8e54850e --- /dev/null +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H +#define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H + +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +namespace psr { +struct CallersOfData { + CallersOfData() noexcept = default; + std::unordered_map> FToFunctionVertexTy{}; +}; + +struct CallGraphData { + CallGraphData() noexcept = default; + std::vector CallersOf{}; + void printAsJson(llvm::raw_ostream &OS); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H diff --git a/include/phasar/ControlFlow/ICFGBase.h b/include/phasar/ControlFlow/ICFGBase.h index fea37796c..c55306e37 100644 --- a/include/phasar/ControlFlow/ICFGBase.h +++ b/include/phasar/ControlFlow/ICFGBase.h @@ -106,6 +106,12 @@ template class ICFGBase { void print(llvm::raw_ostream &OS = llvm::outs()) const { self().printImpl(OS); } + + /// Prints the underlying call-graph as Json to the given output-stream + void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const { + self().printAsJson(OS); + } + /// Returns the underlying call-graph as JSON [[nodiscard]] nlohmann::json getAsJson() const { return self().getAsJsonImpl(); diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h index 101718a42..7f62e1542 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h @@ -64,6 +64,7 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG, [[nodiscard]] llvm::SmallVector getReturnSitesOfCallAtImpl(n_t Inst) const; void printImpl(llvm::raw_ostream &OS) const; + void printAsJsonImpl() const; [[nodiscard]] nlohmann::json getAsJsonImpl() const; [[nodiscard]] const CallGraph &getCallGraphImpl() const noexcept; diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h index 12bc78493..30e5e08a1 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h @@ -149,6 +149,7 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { [[nodiscard]] llvm::SmallVector getReturnSitesOfCallAtImpl(n_t Inst) const; void printImpl(llvm::raw_ostream &OS) const; + void printAsJsonImpl(llvm::raw_ostream &OS) const; [[nodiscard]] nlohmann::json getAsJsonImpl() const; [[nodiscard]] const CallGraph &getCallGraphImpl() const noexcept { return CG; diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp new file mode 100644 index 000000000..e72cf5594 --- /dev/null +++ b/lib/ControlFlow/CallGraphData.cpp @@ -0,0 +1,27 @@ +/****************************************************************************** + * 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/ControlFlow/CallGraphData.h" +#include "phasar/Utils/NlohmannLogging.h" + +namespace psr { + void CallGraphData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json JSON; + + for (const auto &CurrentCallerOf : CallersOf) { + for (const auto &CurrentElement : CurrentCallerOf.FToFunctionVertexTy) { + for (const auto &NTValString : CurrentElement.second) { + JSON[CurrentElement.first].push_back(NTValString); + } + } + } + + OS << JSON; + } +} // namespace psr diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp index 0ca199d25..09bdfe448 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp @@ -64,6 +64,10 @@ void LLVMBasedBackwardICFG::printImpl(llvm::raw_ostream &OS) const { ForwardICFG->print(OS); } +void LLVMBasedBackwardICFG::printAsJsonImpl() const { + return ForwardICFG->printAsJson(); +} + nlohmann::json LLVMBasedBackwardICFG::getAsJsonImpl() const { return ForwardICFG->getAsJson(); } diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp index 87b2279f2..2ab3708ee 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp @@ -451,6 +451,10 @@ void LLVMBasedICFG::printImpl(llvm::raw_ostream &OS) const { [](n_t CS) { return llvmIRToStableString(CS); }); } +void LLVMBasedICFG::printAsJsonImpl(llvm::raw_ostream &OS) const { + CG.printAsJson(OS); +} + [[nodiscard]] nlohmann::json LLVMBasedICFG::getAsJsonImpl() const { return CG.getAsJson( [](f_t F) { return F->getName().str(); }, diff --git a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt index 656751ae9..63546f47a 100644 --- a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt +++ b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt @@ -10,6 +10,7 @@ set(ControlFlowSources LLVMBasedICFGExportTest.cpp LLVMBasedICFGGlobCtorDtorTest.cpp LLVMBasedICFGSerializationTest.cpp + LLVMICFGPrintAsJsonTest.cpp ) set(LLVM_LINK_COMPONENTS Linker) # The CtorDtorTest needs the linker diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp new file mode 100644 index 000000000..1896fad65 --- /dev/null +++ b/unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp @@ -0,0 +1,279 @@ +#include "phasar/Config/Configuration.h" +#include "phasar/ControlFlow/CallGraphAnalysisType.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" + +#include "llvm/Support/raw_ostream.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +#include +#include + +using namespace std; +using namespace psr; + +template static auto makeSet(T &&Vec) { + using value_type = std::decay_t; + return std::set{Vec.begin(), Vec.end()}; +} + +TEST(LLVMBasedICFGTest, StaticCallSite_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_1_c.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *Foo = IRDB.getFunctionDefinition("foo"); + ASSERT_TRUE(F); + ASSERT_TRUE(Foo); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_2a) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_2_c.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, + Soundness::Soundy, false); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *FOO = IRDB.getFunctionDefinition("foo"); + const llvm::Function *BAR = IRDB.getFunctionDefinition("bar"); + ASSERT_TRUE(F); + ASSERT_TRUE(FOO); + ASSERT_TRUE(BAR); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_2b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_2_c.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *FOO = IRDB.getFunctionDefinition("foo"); + const llvm::Function *BAR = IRDB.getFunctionDefinition("bar"); + const llvm::Function *CTOR = + IRDB.getFunctionDefinition(LLVMBasedICFG::GlobalCRuntimeModelName); + const llvm::Function *DTOR = + IRDB.getFunctionDefinition(LLVMBasedICFG::GlobalCRuntimeDtorModelName); + ASSERT_TRUE(F); + ASSERT_TRUE(FOO); + ASSERT_TRUE(BAR); + ASSERT_TRUE(CTOR); + ASSERT_TRUE(DTOR); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, VirtualCallSite_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/virtual_call_1_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *FooA = IRDB.getFunctionDefinition("_ZN1A3fooEv"); + ASSERT_TRUE(F); + ASSERT_TRUE(FooA); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, FunctionPointer_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/function_pointer_1_c.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *Foo = IRDB.getFunctionDefinition("fptr"); + ASSERT_TRUE(F); + ASSERT_FALSE(Foo); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_3) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_3_c.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *Factorial = IRDB.getFunctionDefinition("factorial"); + ASSERT_TRUE(Factorial); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_4) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_4_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + ASSERT_TRUE(F); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_5) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_5_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *Foo = + IRDB.getFunctionDefinition("_ZN3Foo10getNumFoosEv"); + ASSERT_TRUE(F); + ASSERT_TRUE(Foo); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_6) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_6_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN3Foo1fEv"); + ASSERT_TRUE(F); + ASSERT_TRUE(FooF); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_7) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_7_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *Main = IRDB.getFunctionDefinition("main"); + const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN3Foo1fEv"); + const llvm::Function *F = IRDB.getFunctionDefinition("_Z1fv"); + ASSERT_TRUE(Main); + ASSERT_TRUE(FooF); + ASSERT_TRUE(F); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, StaticCallSite_8) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/static_callsite_8_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); + const llvm::Function *F = IRDB.getFunctionDefinition("main"); + const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN4Foo21fEv"); + ASSERT_TRUE(F); + ASSERT_TRUE(FooF); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, GlobalCtorDtor_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/global_ctor_dtor_1_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, + Soundness::Soundy, true); + + auto *GlobCtorFn = IRDB.getFunction(LLVMBasedICFG::GlobalCRuntimeModelName); + + ASSERT_TRUE(GlobCtorFn); + + // GlobCtorFn->print(llvm::outs()); + + const llvm::Function *Main = IRDB.getFunctionDefinition("main"); + const llvm::Function *BeforeMain = + IRDB.getFunctionDefinition("_Z11before_mainv"); + + ASSERT_TRUE(Main); + ASSERT_TRUE(BeforeMain); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, GlobalCtorDtor_2) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/global_ctor_dtor_2_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, + Soundness::Soundy, true); + const llvm::Function *Main = IRDB.getFunctionDefinition("main"); + const llvm::Function *BeforeMain = + IRDB.getFunctionDefinition("_Z11before_mainv"); + const llvm::Function *AfterMain = + IRDB.getFunctionDefinition("_Z10after_mainv"); + + ASSERT_TRUE(Main); + ASSERT_TRUE(BeforeMain); + ASSERT_TRUE(AfterMain); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, GlobalCtorDtor_3) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/global_ctor_dtor_3_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, + Soundness::Soundy, true); + const llvm::Function *Main = IRDB.getFunctionDefinition("main"); + const llvm::Function *Ctor = IRDB.getFunctionDefinition("_ZN1SC2Ei"); + const llvm::Function *Dtor = IRDB.getFunctionDefinition("_ZN1SD2Ev"); + + ASSERT_TRUE(Main); + ASSERT_TRUE(Ctor); + ASSERT_TRUE(Dtor); + + ICFG.printAsJson(); +} + +TEST(LLVMBasedICFGTest, GlobalCtorDtor_4) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "call_graphs/global_ctor_dtor_4_cpp.ll"); + LLVMTypeHierarchy TH(IRDB); + LLVMAliasSet PT(&IRDB); + LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, + Soundness::Soundy, true); + const llvm::Function *Main = IRDB.getFunctionDefinition("main"); + const llvm::Function *Ctor = IRDB.getFunctionDefinition("_ZN1SC2Ei"); + const llvm::Function *Dtor = IRDB.getFunctionDefinition("_ZN1SD2Ev"); + const llvm::Function *BeforeMain = + IRDB.getFunctionDefinition("_Z11before_mainv"); + const llvm::Function *AfterMain = + IRDB.getFunctionDefinition("_Z10after_mainv"); + + ASSERT_TRUE(Main); + ASSERT_TRUE(Ctor); + ASSERT_TRUE(Dtor); + ASSERT_TRUE(BeforeMain); + ASSERT_TRUE(AfterMain); + + ICFG.printAsJson(); +} + +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + return RUN_ALL_TESTS(); +} From 0912f5c3c09cec3ef6bfa101051fd80e3f4c9259 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 14 Mar 2024 00:38:49 +0100 Subject: [PATCH 02/42] compiles --- include/phasar/ControlFlow/CallGraph.h | 6 ++++-- include/phasar/ControlFlow/CallGraphData.h | 4 +++- include/phasar/ControlFlow/ICFGBase.h | 2 +- .../ControlFlow/LLVMBasedBackwardICFG.h | 4 +++- .../PhasarLLVM/ControlFlow/LLVMBasedICFG.h | 2 ++ lib/ControlFlow/CallGraphData.cpp | 19 ++++++++++--------- .../ControlFlow/LLVMBasedBackwardICFG.cpp | 4 ++-- .../PhasarLLVM/ControlFlow/CMakeLists.txt | 2 +- ...t.cpp => LLVMBasedICFGPrintAsJsonTest.cpp} | 0 9 files changed, 26 insertions(+), 17 deletions(-) rename unittests/PhasarLLVM/ControlFlow/{LLVMICFGPrintAsJsonTest.cpp => LLVMBasedICFGPrintAsJsonTest.cpp} (100%) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index ffe9d8446..93645bdfb 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -90,6 +90,7 @@ class CallGraph : public CallGraphBase> { [[nodiscard]] bool empty() const noexcept { return CallersOf.empty(); } + template void stringifyFunctionVertexTy(const FunctionVertexTy &FuncVal, std::vector &Container) const { for (const auto &Curr : FuncVal) { @@ -97,12 +98,13 @@ class CallGraph : public CallGraphBase> { } } + template void stringifyCallersOf(CallGraphData &Container) const { for (const auto &Curr : CallersOf) { std::string FValueString = (FToString(Curr.first)).str(); std::vector FunctionVertexTyString; - stringifyFunctionVertexTy(*Curr.second, FunctionVertexTyString); + stringifyFunctionVertexTy(*Curr.second, FunctionVertexTyString); CallersOfData COData; COData.FToFunctionVertexTy.insert( @@ -115,7 +117,7 @@ class CallGraph : public CallGraphBase> { void printAsJson(llvm::raw_ostream &OS) const { CallGraphData CGData; - stringifyCallersOf(CGData); + stringifyCallersOf(CGData); CGData.printAsJson(OS); } diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index c8e54850e..defa40b0d 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -11,6 +11,7 @@ #define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H #include "llvm/Support/raw_ostream.h" + #include #include #include @@ -18,7 +19,8 @@ namespace psr { struct CallersOfData { CallersOfData() noexcept = default; - std::unordered_map> FToFunctionVertexTy{}; + std::unordered_map> + FToFunctionVertexTy{}; }; struct CallGraphData { diff --git a/include/phasar/ControlFlow/ICFGBase.h b/include/phasar/ControlFlow/ICFGBase.h index c55306e37..1a57a9341 100644 --- a/include/phasar/ControlFlow/ICFGBase.h +++ b/include/phasar/ControlFlow/ICFGBase.h @@ -109,7 +109,7 @@ template class ICFGBase { /// Prints the underlying call-graph as Json to the given output-stream void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const { - self().printAsJson(OS); + self().printAsJsonImpl(OS); } /// Returns the underlying call-graph as JSON diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h index 7f62e1542..66fa5e34e 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h @@ -44,6 +44,8 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG, using CFGBase::print; using ICFGBase::print; + using ICFGBase::printAsJson; + using CFGBase::getAsJson; using ICFGBase::getAsJson; @@ -64,7 +66,7 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG, [[nodiscard]] llvm::SmallVector getReturnSitesOfCallAtImpl(n_t Inst) const; void printImpl(llvm::raw_ostream &OS) const; - void printAsJsonImpl() const; + void printAsJsonImpl(llvm::raw_ostream &OS) const; [[nodiscard]] nlohmann::json getAsJsonImpl() const; [[nodiscard]] const CallGraph &getCallGraphImpl() const noexcept; diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h index 30e5e08a1..4e3d27bed 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h @@ -135,6 +135,8 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { using CFGBase::print; using ICFGBase::print; + using ICFGBase::printAsJson; + using CFGBase::getAsJson; using ICFGBase::getAsJson; diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index e72cf5594..d6999f4d9 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -8,20 +8,21 @@ *****************************************************************************/ #include "phasar/ControlFlow/CallGraphData.h" + #include "phasar/Utils/NlohmannLogging.h" namespace psr { - void CallGraphData::printAsJson(llvm::raw_ostream &OS) { - nlohmann::json JSON; +void CallGraphData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json JSON; - for (const auto &CurrentCallerOf : CallersOf) { - for (const auto &CurrentElement : CurrentCallerOf.FToFunctionVertexTy) { - for (const auto &NTValString : CurrentElement.second) { - JSON[CurrentElement.first].push_back(NTValString); - } + for (const auto &CurrentCallerOf : CallersOf) { + for (const auto &CurrentElement : CurrentCallerOf.FToFunctionVertexTy) { + for (const auto &NTValString : CurrentElement.second) { + JSON[CurrentElement.first].push_back(NTValString); } } - - OS << JSON; } + + OS << JSON; +} } // namespace psr diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp index 09bdfe448..f029a39d9 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.cpp @@ -64,8 +64,8 @@ void LLVMBasedBackwardICFG::printImpl(llvm::raw_ostream &OS) const { ForwardICFG->print(OS); } -void LLVMBasedBackwardICFG::printAsJsonImpl() const { - return ForwardICFG->printAsJson(); +void LLVMBasedBackwardICFG::printAsJsonImpl(llvm::raw_ostream &OS) const { + ForwardICFG->printAsJson(OS); } nlohmann::json LLVMBasedBackwardICFG::getAsJsonImpl() const { diff --git a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt index 63546f47a..86a0167cd 100644 --- a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt +++ b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt @@ -10,7 +10,7 @@ set(ControlFlowSources LLVMBasedICFGExportTest.cpp LLVMBasedICFGGlobCtorDtorTest.cpp LLVMBasedICFGSerializationTest.cpp - LLVMICFGPrintAsJsonTest.cpp + LLVMBasedICFGPrintAsJsonTest.cpp ) set(LLVM_LINK_COMPONENTS Linker) # The CtorDtorTest needs the linker diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp similarity index 100% rename from unittests/PhasarLLVM/ControlFlow/LLVMICFGPrintAsJsonTest.cpp rename to unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp From 3be40eaf429c31321d2ea1dcc53827750a496393 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 14 Mar 2024 09:02:38 +0100 Subject: [PATCH 03/42] refactored CallGraph::deserialize() --- include/phasar/ControlFlow/CallGraph.h | 19 ++++--------- include/phasar/ControlFlow/CallGraphData.h | 11 ++------ .../PhasarLLVM/ControlFlow/LLVMBasedICFG.h | 4 +-- lib/ControlFlow/CallGraphData.cpp | 28 +++++++++++++++---- lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp | 3 +- 5 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 93645bdfb..fae0a5603 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -62,7 +62,7 @@ class CallGraph : public CallGraphBase> { /// Deserializes a previously computed call-graph template [[nodiscard]] static CallGraph - deserialize(const nlohmann::json &PrecomputedCG, + deserialize(const CallGraphData &PrecomputedCG, FunctionGetter GetFunctionFromName, InstructionGetter GetInstructionFromId); @@ -106,10 +106,8 @@ class CallGraph : public CallGraphBase> { std::vector FunctionVertexTyString; stringifyFunctionVertexTy(*Curr.second, FunctionVertexTyString); - CallersOfData COData; - COData.FToFunctionVertexTy.insert( + Container.FToFunctionVertexTy.insert( {std::move(FValueString), std::move(FunctionVertexTyString)}); - Container.CallersOf.push_back(std::move(COData)); } } @@ -290,18 +288,13 @@ template class CallGraphBuilder { template template [[nodiscard]] CallGraph -CallGraph::deserialize(const nlohmann::json &PrecomputedCG, +CallGraph::deserialize(const CallGraphData &PrecomputedCG, FunctionGetter GetFunctionFromName, InstructionGetter GetInstructionFromId) { - if (!PrecomputedCG.is_object()) { - PHASAR_LOG_LEVEL_CAT(ERROR, "CallGraph", "Invalid Json. Expected object"); - return {}; - } - CallGraphBuilder CGBuilder; - CGBuilder.reserve(PrecomputedCG.size()); + CGBuilder.reserve(PrecomputedCG.FToFunctionVertexTy.size()); - for (const auto &[FunName, CallerIDs] : PrecomputedCG.items()) { + for (const auto &[FunName, CallerIDs] : PrecomputedCG.FToFunctionVertexTy) { const auto &Fun = std::invoke(GetFunctionFromName, FunName); if (!Fun) { PHASAR_LOG_LEVEL_CAT(WARNING, "CallGraph", @@ -313,7 +306,7 @@ CallGraph::deserialize(const nlohmann::json &PrecomputedCG, CEdges->reserve(CallerIDs.size()); for (const auto &JId : CallerIDs) { - auto Id = JId.get(); + auto Id = JId.size(); const auto &CS = std::invoke(GetInstructionFromId, Id); if (!CS) { PHASAR_LOG_LEVEL_CAT(WARNING, "CallGraph", diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index defa40b0d..fbbf002e6 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -17,16 +17,11 @@ #include namespace psr { -struct CallersOfData { - CallersOfData() noexcept = default; - std::unordered_map> - FToFunctionVertexTy{}; -}; - struct CallGraphData { - CallGraphData() noexcept = default; - std::vector CallersOf{}; + CallGraphData() noexcept = default;std::unordered_map> + FToFunctionVertexTy{}; void printAsJson(llvm::raw_ostream &OS); + void deserializeJson(const llvm::Twine &Path); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h index 4e3d27bed..f1c03879a 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h @@ -35,8 +35,6 @@ #include "llvm/IR/Value.h" #include "llvm/Support/raw_ostream.h" -#include "nlohmann/json.hpp" - #include namespace psr { @@ -93,7 +91,7 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { LLVMTypeHierarchy *TH = nullptr); explicit LLVMBasedICFG(LLVMProjectIRDB *IRDB, - const nlohmann::json &SerializedCG, + const CallGraphData &SerializedCG, LLVMTypeHierarchy *TH = nullptr); // Deleter of LLVMTypeHierarchy may be unknown here... diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index d6999f4d9..9e07651ad 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -10,19 +10,37 @@ #include "phasar/ControlFlow/CallGraphData.h" #include "phasar/Utils/NlohmannLogging.h" +#include "llvm/Support/ErrorHandling.h" namespace psr { void CallGraphData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json JSON; - for (const auto &CurrentCallerOf : CallersOf) { - for (const auto &CurrentElement : CurrentCallerOf.FToFunctionVertexTy) { - for (const auto &NTValString : CurrentElement.second) { - JSON[CurrentElement.first].push_back(NTValString); - } + for (const auto &CurrentElement : FToFunctionVertexTy) { + for (const auto &NTValString : CurrentElement.second) { + JSON[CurrentElement.first].push_back(NTValString); } } OS << JSON; } + +void CallGraphData::deserializeJson(const llvm::Twine &Path) { + nlohmann::json JSON(Path.str()); + + if (!JSON.is_object()) { + llvm::report_fatal_error("Invalid Json: not an object!"); + } + // map F to vector of n_t's + + for (const auto &CurrentFVal : JSON.get()) { + std::string FValueString = CurrentFVal.first; + std::vector FunctionVertexTyStrings(CurrentFVal.second.size()); + for (const auto &CurrentFunctionVertexTy : CurrentFVal.second) { + FunctionVertexTyStrings.push_back(CurrentFunctionVertexTy); + } + + FToFunctionVertexTy.insert({FValueString, FunctionVertexTyStrings}); + } +} } // namespace psr diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp index 2ab3708ee..aa4917c4e 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp @@ -12,6 +12,7 @@ #include "phasar/Config/Configuration.h" #include "phasar/ControlFlow/CallGraph.h" #include "phasar/ControlFlow/CallGraphAnalysisType.h" +#include "phasar/ControlFlow/CallGraphData.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" #include "phasar/PhasarLLVM/ControlFlow/Resolver/Resolver.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" @@ -367,7 +368,7 @@ LLVMBasedICFG::LLVMBasedICFG(CallGraph CG, LLVMProjectIRDB *IRDB, } LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *IRDB, - const nlohmann::json &SerializedCG, + const CallGraphData &SerializedCG, LLVMTypeHierarchy *TH) : CG(CallGraph::deserialize( SerializedCG, From 86fc715c590c9a6fa787d645f95cfcdb66196617 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 14 Mar 2024 21:11:55 +0100 Subject: [PATCH 04/42] refactored unittests, all fail --- lib/ControlFlow/CallGraphData.cpp | 8 +- .../PhasarLLVM/ControlFlow/CMakeLists.txt | 1 - .../LLVMBasedICFGPrintAsJsonTest.cpp | 279 ------------------ .../LLVMBasedICFGSerializationTest.cpp | 30 +- 4 files changed, 34 insertions(+), 284 deletions(-) delete mode 100644 unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index 9e07651ad..9fdc02edc 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -11,6 +11,9 @@ #include "phasar/Utils/NlohmannLogging.h" #include "llvm/Support/ErrorHandling.h" +#include +#include +#include namespace psr { void CallGraphData::printAsJson(llvm::raw_ostream &OS) { @@ -26,7 +29,10 @@ void CallGraphData::printAsJson(llvm::raw_ostream &OS) { } void CallGraphData::deserializeJson(const llvm::Twine &Path) { - nlohmann::json JSON(Path.str()); + std::ifstream IFS(Path.str()); + std::string Data((std::istreambuf_iterator(IFS)), + (std::istreambuf_iterator())); + nlohmann::json JSON = nlohmann::json::parse(Data); if (!JSON.is_object()) { llvm::report_fatal_error("Invalid Json: not an object!"); diff --git a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt index 86a0167cd..656751ae9 100644 --- a/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt +++ b/unittests/PhasarLLVM/ControlFlow/CMakeLists.txt @@ -10,7 +10,6 @@ set(ControlFlowSources LLVMBasedICFGExportTest.cpp LLVMBasedICFGGlobCtorDtorTest.cpp LLVMBasedICFGSerializationTest.cpp - LLVMBasedICFGPrintAsJsonTest.cpp ) set(LLVM_LINK_COMPONENTS Linker) # The CtorDtorTest needs the linker diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp deleted file mode 100644 index 1896fad65..000000000 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGPrintAsJsonTest.cpp +++ /dev/null @@ -1,279 +0,0 @@ -#include "phasar/Config/Configuration.h" -#include "phasar/ControlFlow/CallGraphAnalysisType.h" -#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" -#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" -#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" -#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" -#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" - -#include "llvm/Support/raw_ostream.h" - -#include "TestConfig.h" -#include "gtest/gtest.h" - -#include -#include - -using namespace std; -using namespace psr; - -template static auto makeSet(T &&Vec) { - using value_type = std::decay_t; - return std::set{Vec.begin(), Vec.end()}; -} - -TEST(LLVMBasedICFGTest, StaticCallSite_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_1_c.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *Foo = IRDB.getFunctionDefinition("foo"); - ASSERT_TRUE(F); - ASSERT_TRUE(Foo); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_2a) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_2_c.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, - Soundness::Soundy, false); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *FOO = IRDB.getFunctionDefinition("foo"); - const llvm::Function *BAR = IRDB.getFunctionDefinition("bar"); - ASSERT_TRUE(F); - ASSERT_TRUE(FOO); - ASSERT_TRUE(BAR); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_2b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_2_c.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *FOO = IRDB.getFunctionDefinition("foo"); - const llvm::Function *BAR = IRDB.getFunctionDefinition("bar"); - const llvm::Function *CTOR = - IRDB.getFunctionDefinition(LLVMBasedICFG::GlobalCRuntimeModelName); - const llvm::Function *DTOR = - IRDB.getFunctionDefinition(LLVMBasedICFG::GlobalCRuntimeDtorModelName); - ASSERT_TRUE(F); - ASSERT_TRUE(FOO); - ASSERT_TRUE(BAR); - ASSERT_TRUE(CTOR); - ASSERT_TRUE(DTOR); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, VirtualCallSite_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/virtual_call_1_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *FooA = IRDB.getFunctionDefinition("_ZN1A3fooEv"); - ASSERT_TRUE(F); - ASSERT_TRUE(FooA); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, FunctionPointer_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/function_pointer_1_c.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *Foo = IRDB.getFunctionDefinition("fptr"); - ASSERT_TRUE(F); - ASSERT_FALSE(Foo); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_3) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_3_c.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *Factorial = IRDB.getFunctionDefinition("factorial"); - ASSERT_TRUE(Factorial); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_4) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_4_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - ASSERT_TRUE(F); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_5) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_5_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *Foo = - IRDB.getFunctionDefinition("_ZN3Foo10getNumFoosEv"); - ASSERT_TRUE(F); - ASSERT_TRUE(Foo); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_6) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_6_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN3Foo1fEv"); - ASSERT_TRUE(F); - ASSERT_TRUE(FooF); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_7) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_7_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *Main = IRDB.getFunctionDefinition("main"); - const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN3Foo1fEv"); - const llvm::Function *F = IRDB.getFunctionDefinition("_Z1fv"); - ASSERT_TRUE(Main); - ASSERT_TRUE(FooF); - ASSERT_TRUE(F); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, StaticCallSite_8) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/static_callsite_8_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT); - const llvm::Function *F = IRDB.getFunctionDefinition("main"); - const llvm::Function *FooF = IRDB.getFunctionDefinition("_ZN4Foo21fEv"); - ASSERT_TRUE(F); - ASSERT_TRUE(FooF); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, GlobalCtorDtor_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/global_ctor_dtor_1_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, - Soundness::Soundy, true); - - auto *GlobCtorFn = IRDB.getFunction(LLVMBasedICFG::GlobalCRuntimeModelName); - - ASSERT_TRUE(GlobCtorFn); - - // GlobCtorFn->print(llvm::outs()); - - const llvm::Function *Main = IRDB.getFunctionDefinition("main"); - const llvm::Function *BeforeMain = - IRDB.getFunctionDefinition("_Z11before_mainv"); - - ASSERT_TRUE(Main); - ASSERT_TRUE(BeforeMain); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, GlobalCtorDtor_2) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/global_ctor_dtor_2_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, - Soundness::Soundy, true); - const llvm::Function *Main = IRDB.getFunctionDefinition("main"); - const llvm::Function *BeforeMain = - IRDB.getFunctionDefinition("_Z11before_mainv"); - const llvm::Function *AfterMain = - IRDB.getFunctionDefinition("_Z10after_mainv"); - - ASSERT_TRUE(Main); - ASSERT_TRUE(BeforeMain); - ASSERT_TRUE(AfterMain); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, GlobalCtorDtor_3) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/global_ctor_dtor_3_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, - Soundness::Soundy, true); - const llvm::Function *Main = IRDB.getFunctionDefinition("main"); - const llvm::Function *Ctor = IRDB.getFunctionDefinition("_ZN1SC2Ei"); - const llvm::Function *Dtor = IRDB.getFunctionDefinition("_ZN1SD2Ev"); - - ASSERT_TRUE(Main); - ASSERT_TRUE(Ctor); - ASSERT_TRUE(Dtor); - - ICFG.printAsJson(); -} - -TEST(LLVMBasedICFGTest, GlobalCtorDtor_4) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "call_graphs/global_ctor_dtor_4_cpp.ll"); - LLVMTypeHierarchy TH(IRDB); - LLVMAliasSet PT(&IRDB); - LLVMBasedICFG ICFG(&IRDB, CallGraphAnalysisType::CHA, {"main"}, &TH, &PT, - Soundness::Soundy, true); - const llvm::Function *Main = IRDB.getFunctionDefinition("main"); - const llvm::Function *Ctor = IRDB.getFunctionDefinition("_ZN1SC2Ei"); - const llvm::Function *Dtor = IRDB.getFunctionDefinition("_ZN1SD2Ev"); - const llvm::Function *BeforeMain = - IRDB.getFunctionDefinition("_Z11before_mainv"); - const llvm::Function *AfterMain = - IRDB.getFunctionDefinition("_Z10after_mainv"); - - ASSERT_TRUE(Main); - ASSERT_TRUE(Ctor); - ASSERT_TRUE(Dtor); - ASSERT_TRUE(BeforeMain); - ASSERT_TRUE(AfterMain); - - ICFG.printAsJson(); -} - -int main(int Argc, char **Argv) { - ::testing::InitGoogleTest(&Argc, Argv); - return RUN_ALL_TESTS(); -} diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp index 35619ce5a..b6844037e 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp @@ -1,11 +1,16 @@ #include "phasar/ControlFlow/CallGraphAnalysisType.h" +#include "phasar/ControlFlow/CallGraphData.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "TestConfig.h" #include "gtest/gtest.h" +#include class LLVMBasedICFGGSerializationTest : public ::testing::Test { protected: @@ -17,11 +22,30 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { psr::LLVMProjectIRDB IRDB(PathToLLFiles + IRFile); psr::LLVMBasedICFG ICF(&IRDB, psr::CallGraphAnalysisType::OTF, {"main"s}); - auto Ser = ICF.getAsJson(); + + llvm::StringRef PathToJson = "JSONTest.json"; + std::error_code ErrorCode; - psr::LLVMBasedICFG Deser(&IRDB, Ser); + // stream ICF data into a json file using the printAsJson() function + llvm::raw_fd_ostream OutStream(PathToJson, ErrorCode); - compareResults(ICF, Deser); + if (ErrorCode) { + llvm::report_fatal_error(("File could not be opened!\n" + ErrorCode.message()).c_str()); + } + + ICF.printAsJson(OutStream); + OutStream.close(); + + llvm::outs() << "before deserialization\n"; + llvm::outs().flush(); + // deserialize data into CallGraphData object + psr::CallGraphData CGData; + CGData.deserializeJson(PathToJson); + psr::LLVMBasedICFG DeserializedICF(&IRDB, CGData); + + llvm::outs() << "before compare"; + llvm::outs().flush(); + compareResults(ICF, DeserializedICF); } void compareResults(const psr::LLVMBasedICFG &Orig, From 3ecb12a1aee09e6ce31ce91cebca19080846c816 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 18 Mar 2024 20:44:28 +0100 Subject: [PATCH 05/42] all unittests finally pass --- include/phasar/ControlFlow/CallGraph.h | 41 ++++++++++--------- include/phasar/ControlFlow/CallGraphData.h | 4 +- lib/ControlFlow/CMakeLists.txt | 2 + lib/ControlFlow/CallGraphData.cpp | 26 ++++++------ lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp | 4 +- .../LLVMBasedICFGSerializationTest.cpp | 11 ++--- 6 files changed, 46 insertions(+), 42 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index fae0a5603..f5ce3af12 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -27,6 +27,7 @@ #include "nlohmann/json.hpp" #include +#include #include #include @@ -91,35 +92,36 @@ class CallGraph : public CallGraphBase> { [[nodiscard]] bool empty() const noexcept { return CallersOf.empty(); } template - void stringifyFunctionVertexTy(const FunctionVertexTy &FuncVal, - std::vector &Container) const { - for (const auto &Curr : FuncVal) { - Container.push_back(NToString(Curr)); - } - } - - template - void stringifyCallersOf(CallGraphData &Container) const { - for (const auto &Curr : CallersOf) { - std::string FValueString = (FToString(Curr.first)).str(); + void stringifyCallersOf(CallGraphData &Container, + FunctionIdGetter GetFunctionId, + InstIdGetter GetInstructionId) const { + for (const auto &[Fun, Callers] : CallersOf) { + std::string FValueString = GetFunctionId(Fun); - std::vector FunctionVertexTyString; - stringifyFunctionVertexTy(*Curr.second, FunctionVertexTyString); + std::vector FunctionVertexTyVals; + for (const auto &CS : *Callers) { + FunctionVertexTyVals.push_back(std::stoi(NToString(GetInstructionId(CS)))); + } + if (Callers->size() == 0) { + Container.FToFunctionVertexTy.insert( + {FValueString, {0}}); + } Container.FToFunctionVertexTy.insert( - {std::move(FValueString), std::move(FunctionVertexTyString)}); + {std::move(FValueString), std::move(FunctionVertexTyVals)}); } } template - void printAsJson(llvm::raw_ostream &OS) const { + void printAsJson(llvm::raw_ostream &OS, FunctionIdGetter GetFunctionId, + InstIdGetter GetInstructionId) const { CallGraphData CGData; - stringifyCallersOf(CGData); + stringifyCallersOf(CGData, GetFunctionId, GetInstructionId); CGData.printAsJson(OS); } - + /// Creates a JSON representation of this call-graph suitable for presistent /// storage. /// Use the ctor taking a json object for deserialization @@ -306,11 +308,10 @@ CallGraph::deserialize(const CallGraphData &PrecomputedCG, CEdges->reserve(CallerIDs.size()); for (const auto &JId : CallerIDs) { - auto Id = JId.size(); - const auto &CS = std::invoke(GetInstructionFromId, Id); + const auto &CS = std::invoke(GetInstructionFromId, JId); if (!CS) { PHASAR_LOG_LEVEL_CAT(WARNING, "CallGraph", - "Invalid CAll-Instruction Id: " << Id); + "Invalid CAll-Instruction Id: " << JId); } CGBuilder.addCallEdge(CS, Fun); diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index fbbf002e6..53e05be07 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H #define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H +#include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include @@ -18,7 +19,8 @@ namespace psr { struct CallGraphData { - CallGraphData() noexcept = default;std::unordered_map> + CallGraphData() noexcept = default; + std::unordered_map> FToFunctionVertexTy{}; void printAsJson(llvm::raw_ostream &OS); void deserializeJson(const llvm::Twine &Path); diff --git a/lib/ControlFlow/CMakeLists.txt b/lib/ControlFlow/CMakeLists.txt index 39084cd11..d6f91baa6 100644 --- a/lib/ControlFlow/CMakeLists.txt +++ b/lib/ControlFlow/CMakeLists.txt @@ -2,6 +2,8 @@ file(GLOB_RECURSE CONTROLFLOW_SRC *.h *.cpp) add_phasar_library(phasar_controlflow ${CONTROLFLOW_SRC} + LINKS + phasar_utils LLVM_LINK_COMPONENTS Support LINK_PRIVATE nlohmann_json::nlohmann_json ) diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index 9fdc02edc..84528b68d 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -9,19 +9,25 @@ #include "phasar/ControlFlow/CallGraphData.h" +#include "phasar/Utils/IO.h" #include "phasar/Utils/NlohmannLogging.h" + #include "llvm/Support/ErrorHandling.h" + #include #include +#include + #include namespace psr { + void CallGraphData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json JSON; for (const auto &CurrentElement : FToFunctionVertexTy) { - for (const auto &NTValString : CurrentElement.second) { - JSON[CurrentElement.first].push_back(NTValString); + for (const auto &NTVal : CurrentElement.second) { + JSON[CurrentElement.first].push_back(NTVal); } } @@ -29,24 +35,18 @@ void CallGraphData::printAsJson(llvm::raw_ostream &OS) { } void CallGraphData::deserializeJson(const llvm::Twine &Path) { - std::ifstream IFS(Path.str()); - std::string Data((std::istreambuf_iterator(IFS)), - (std::istreambuf_iterator())); - nlohmann::json JSON = nlohmann::json::parse(Data); + nlohmann::json JSON = readJsonFile(Path); - if (!JSON.is_object()) { - llvm::report_fatal_error("Invalid Json: not an object!"); - } // map F to vector of n_t's - for (const auto &CurrentFVal : JSON.get()) { std::string FValueString = CurrentFVal.first; - std::vector FunctionVertexTyStrings(CurrentFVal.second.size()); + std::vector FunctionVertexTyVals(CurrentFVal.second.size()); + for (const auto &CurrentFunctionVertexTy : CurrentFVal.second) { - FunctionVertexTyStrings.push_back(CurrentFunctionVertexTy); + FunctionVertexTyVals.push_back(CurrentFunctionVertexTy); } - FToFunctionVertexTy.insert({FValueString, FunctionVertexTyStrings}); + FToFunctionVertexTy.insert({FValueString, FunctionVertexTyVals}); } } } // namespace psr diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp index aa4917c4e..9d4c5ee20 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp @@ -453,7 +453,9 @@ void LLVMBasedICFG::printImpl(llvm::raw_ostream &OS) const { } void LLVMBasedICFG::printAsJsonImpl(llvm::raw_ostream &OS) const { - CG.printAsJson(OS); + CG.printAsJson( + OS, [](f_t F) { return F->getName().str(); }, + [this](n_t Inst) { return IRDB->getInstructionId(Inst); }); } [[nodiscard]] nlohmann::json LLVMBasedICFG::getAsJsonImpl() const { diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp index b6844037e..b39b05072 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp @@ -6,7 +6,9 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "phasar/Utils/IO.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -20,12 +22,10 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { using namespace std::string_literals; psr::LLVMProjectIRDB IRDB(PathToLLFiles + IRFile); - psr::LLVMBasedICFG ICF(&IRDB, psr::CallGraphAnalysisType::OTF, {"main"s}); llvm::StringRef PathToJson = "JSONTest.json"; std::error_code ErrorCode; - // stream ICF data into a json file using the printAsJson() function llvm::raw_fd_ostream OutStream(PathToJson, ErrorCode); @@ -36,15 +36,12 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { ICF.printAsJson(OutStream); OutStream.close(); - llvm::outs() << "before deserialization\n"; - llvm::outs().flush(); // deserialize data into CallGraphData object psr::CallGraphData CGData; CGData.deserializeJson(PathToJson); + auto Ser = ICF.getAsJson(); psr::LLVMBasedICFG DeserializedICF(&IRDB, CGData); - llvm::outs() << "before compare"; - llvm::outs().flush(); compareResults(ICF, DeserializedICF); } @@ -63,7 +60,7 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { << Fun->getName().str(); } } - + for (const auto *Fun : Orig.getAllVertexFunctions()) { const auto &Calls = Orig.getCallsFromWithin(Fun); From 3664d3f6ae25470c34d1ed67aa4032651cf99311 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 20 Mar 2024 09:12:30 +0100 Subject: [PATCH 06/42] code cleanup --- include/phasar/ControlFlow/CallGraph.h | 16 ++++--- include/phasar/ControlFlow/CallGraphData.h | 4 +- include/phasar/ControlFlow/ICFGBase.h | 2 +- lib/ControlFlow/CallGraphData.cpp | 45 +++++++++++-------- .../LLVMBasedICFGSerializationTest.cpp | 26 ++++------- 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index f5ce3af12..9875bd7e9 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -100,12 +100,14 @@ class CallGraph : public CallGraphBase> { std::vector FunctionVertexTyVals; for (const auto &CS : *Callers) { - FunctionVertexTyVals.push_back(std::stoi(NToString(GetInstructionId(CS)))); + FunctionVertexTyVals.push_back(GetInstructionId(CS)); } + // if a function exists but the callers size is zero, a value of null + // should be inserted, to represent the existance of that function. An + // example of this happening is __psrCRuntimeGlobalCtorsModel if (Callers->size() == 0) { - Container.FToFunctionVertexTy.insert( - {FValueString, {0}}); + Container.FToFunctionVertexTy.insert({FValueString, {0}}); } Container.FToFunctionVertexTy.insert( {std::move(FValueString), std::move(FunctionVertexTyVals)}); @@ -121,13 +123,15 @@ class CallGraph : public CallGraphBase> { CGData.printAsJson(OS); } - + /// Creates a JSON representation of this call-graph suitable for presistent /// storage. /// Use the ctor taking a json object for deserialization template - [[nodiscard]] nlohmann::json getAsJson(FunctionIdGetter GetFunctionId, - InstIdGetter GetInstructionId) const { + [[nodiscard]] [[deprecated( + "please use printAsJson in the future")]] nlohmann::json + getAsJson(FunctionIdGetter GetFunctionId, + InstIdGetter GetInstructionId) const { nlohmann::json J; for (const auto &[Fun, Callers] : CallersOf) { diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index 53e05be07..fa7b7cebe 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -10,7 +10,6 @@ #ifndef PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H #define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H -#include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" #include @@ -23,7 +22,8 @@ struct CallGraphData { std::unordered_map> FToFunctionVertexTy{}; void printAsJson(llvm::raw_ostream &OS); - void deserializeJson(const llvm::Twine &Path); + static CallGraphData deserializeJson(const llvm::Twine &Path); + static CallGraphData loadJsonString(const std::string &JsonAsString); }; } // namespace psr diff --git a/include/phasar/ControlFlow/ICFGBase.h b/include/phasar/ControlFlow/ICFGBase.h index 1a57a9341..879581a0a 100644 --- a/include/phasar/ControlFlow/ICFGBase.h +++ b/include/phasar/ControlFlow/ICFGBase.h @@ -113,7 +113,7 @@ template class ICFGBase { } /// Returns the underlying call-graph as JSON - [[nodiscard]] nlohmann::json getAsJson() const { + [[nodiscard]] [[deprecated("please use printAsJson in the future")]] nlohmann::json getAsJson() const { return self().getAsJsonImpl(); } diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index 84528b68d..b8b28b9b3 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -12,15 +12,27 @@ #include "phasar/Utils/IO.h" #include "phasar/Utils/NlohmannLogging.h" -#include "llvm/Support/ErrorHandling.h" - -#include -#include -#include - #include namespace psr { +static CallGraphData stringifyJson(const nlohmann::json &Json) { + CallGraphData ToReturn; + + // map F to vector of n_t's + for (const auto &CurrentFVal : Json.get()) { + std::string FValueString = CurrentFVal.first; + std::vector FunctionVertexTyVals; + FunctionVertexTyVals.reserve(CurrentFVal.second.size()); + + for (const auto &CurrentFunctionVertexTy : CurrentFVal.second) { + FunctionVertexTyVals.push_back(CurrentFunctionVertexTy); + } + + ToReturn.FToFunctionVertexTy.try_emplace(FValueString, FunctionVertexTyVals); + } + + return ToReturn; +} void CallGraphData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json JSON; @@ -34,19 +46,14 @@ void CallGraphData::printAsJson(llvm::raw_ostream &OS) { OS << JSON; } -void CallGraphData::deserializeJson(const llvm::Twine &Path) { - nlohmann::json JSON = readJsonFile(Path); - - // map F to vector of n_t's - for (const auto &CurrentFVal : JSON.get()) { - std::string FValueString = CurrentFVal.first; - std::vector FunctionVertexTyVals(CurrentFVal.second.size()); - - for (const auto &CurrentFunctionVertexTy : CurrentFVal.second) { - FunctionVertexTyVals.push_back(CurrentFunctionVertexTy); - } +CallGraphData CallGraphData::deserializeJson(const llvm::Twine &Path) { + return stringifyJson(readJsonFile(Path)); +} - FToFunctionVertexTy.insert({FValueString, FunctionVertexTyVals}); - } +CallGraphData CallGraphData::loadJsonString(const std::string &JsonAsString) { + // nlohmann::json::parse needs a std::string, llvm::Twine won't work + nlohmann::json ToStringify = nlohmann::json::parse(JsonAsString); + return stringifyJson(ToStringify); } + } // namespace psr diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp index b39b05072..194872b8d 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp @@ -4,15 +4,15 @@ #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/IO.h" + #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "phasar/Utils/IO.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include class LLVMBasedICFGGSerializationTest : public ::testing::Test { protected: @@ -23,24 +23,16 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { psr::LLVMProjectIRDB IRDB(PathToLLFiles + IRFile); psr::LLVMBasedICFG ICF(&IRDB, psr::CallGraphAnalysisType::OTF, {"main"s}); - - llvm::StringRef PathToJson = "JSONTest.json"; - std::error_code ErrorCode; - // stream ICF data into a json file using the printAsJson() function - llvm::raw_fd_ostream OutStream(PathToJson, ErrorCode); - if (ErrorCode) { - llvm::report_fatal_error(("File could not be opened!\n" + ErrorCode.message()).c_str()); - } + std::string Ser; + // stream ICF data into a json file using the printAsJson() function + llvm::raw_string_ostream StringStream(Ser); - ICF.printAsJson(OutStream); - OutStream.close(); + ICF.printAsJson(StringStream); // deserialize data into CallGraphData object - psr::CallGraphData CGData; - CGData.deserializeJson(PathToJson); - auto Ser = ICF.getAsJson(); - psr::LLVMBasedICFG DeserializedICF(&IRDB, CGData); + psr::LLVMBasedICFG DeserializedICF(&IRDB, + psr::CallGraphData::loadJsonString(Ser)); compareResults(ICF, DeserializedICF); } @@ -60,7 +52,7 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { << Fun->getName().str(); } } - + for (const auto *Fun : Orig.getAllVertexFunctions()) { const auto &Calls = Orig.getCallsFromWithin(Fun); From ef50e02b76cc0171a12a4cf6c845014e086af1ba Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 20 Mar 2024 11:01:56 +0100 Subject: [PATCH 07/42] refactoring --- include/phasar/ControlFlow/CallGraph.h | 6 +++--- include/phasar/ControlFlow/CallGraphData.h | 3 +-- include/phasar/ControlFlow/ICFGBase.h | 2 +- .../phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h | 2 +- include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h | 2 +- .../PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h | 6 ++++++ .../phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h | 7 +++++-- include/phasar/TypeHierarchy/TypeHierarchy.h | 2 ++ lib/ControlFlow/CallGraphData.cpp | 9 +++++---- lib/Controller/AnalysisController.cpp | 2 +- lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp | 8 +++++++- 11 files changed, 33 insertions(+), 16 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 9875bd7e9..7428cff5c 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -109,8 +109,8 @@ class CallGraph : public CallGraphBase> { if (Callers->size() == 0) { Container.FToFunctionVertexTy.insert({FValueString, {0}}); } - Container.FToFunctionVertexTy.insert( - {std::move(FValueString), std::move(FunctionVertexTyVals)}); + Container.FToFunctionVertexTy.try_emplace( + std::move(FValueString), std::move(FunctionVertexTyVals)); } } @@ -129,7 +129,7 @@ class CallGraph : public CallGraphBase> { /// Use the ctor taking a json object for deserialization template [[nodiscard]] [[deprecated( - "please use printAsJson in the future")]] nlohmann::json + "Please use printAsJson() instead")]] nlohmann::json getAsJson(FunctionIdGetter GetFunctionId, InstIdGetter GetInstructionId) const { nlohmann::json J; diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index fa7b7cebe..43e9c98c8 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -19,8 +19,7 @@ namespace psr { struct CallGraphData { CallGraphData() noexcept = default; - std::unordered_map> - FToFunctionVertexTy{}; + std::unordered_map> FToFunctionVertexTy{}; void printAsJson(llvm::raw_ostream &OS); static CallGraphData deserializeJson(const llvm::Twine &Path); static CallGraphData loadJsonString(const std::string &JsonAsString); diff --git a/include/phasar/ControlFlow/ICFGBase.h b/include/phasar/ControlFlow/ICFGBase.h index 879581a0a..952b45e5b 100644 --- a/include/phasar/ControlFlow/ICFGBase.h +++ b/include/phasar/ControlFlow/ICFGBase.h @@ -113,7 +113,7 @@ template class ICFGBase { } /// Returns the underlying call-graph as JSON - [[nodiscard]] [[deprecated("please use printAsJson in the future")]] nlohmann::json getAsJson() const { + [[nodiscard]] [[deprecated("Please use printAsJson() instead")]] nlohmann::json getAsJson() const { return self().getAsJsonImpl(); } diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index a33b6e10d..41b43294b 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -176,7 +176,7 @@ struct GeneralStatistics { "instead")]] const std::set & getRetResInstructions() const; - [[nodiscard]] 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/Pointer/LLVMAliasSet.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h index 0775e98d2..4e7ff668e 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h @@ -95,7 +95,7 @@ class LLVMAliasSet : public AnalysisPropertiesMixin, void print(llvm::raw_ostream &OS = llvm::outs()) const; - [[nodiscard]] 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/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index 0048e2ecf..1cc79d98a 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -95,6 +95,12 @@ class DIBasedTypeHierarchy [[nodiscard]] nlohmann::json getAsJson() const override; + /** + * @brief Prints the class hierarchy to an ostream in json format. + * @param an outputstream + */ + void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const override; + private: [[nodiscard]] llvm::iterator_range subTypesOf(size_t TypeIdx) const noexcept; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index c5b744e12..21191b183 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -21,6 +21,7 @@ #include "phasar/TypeHierarchy/TypeHierarchy.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" #include "boost/graph/adjacency_list.hpp" #include "boost/graph/graph_traits.hpp" @@ -204,7 +205,9 @@ class LLVMTypeHierarchy void print(llvm::raw_ostream &OS = llvm::outs()) const override; - [[nodiscard]] nlohmann::json getAsJson() const override; + [[nodiscard]] [[deprecated( + "Please use printAsJson() instead")]] nlohmann::json + getAsJson() const override; // void mergeWith(LLVMTypeHierarchy &Other); @@ -223,7 +226,7 @@ class LLVMTypeHierarchy * @brief Prints the class hierarchy to an ostream in json format. * @param an outputstream */ - void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const; + void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const override; // void printGraphAsDot(llvm::raw_ostream &out); diff --git a/include/phasar/TypeHierarchy/TypeHierarchy.h b/include/phasar/TypeHierarchy/TypeHierarchy.h index e3f44e879..75ff142f5 100644 --- a/include/phasar/TypeHierarchy/TypeHierarchy.h +++ b/include/phasar/TypeHierarchy/TypeHierarchy.h @@ -52,6 +52,8 @@ template class TypeHierarchy { virtual void print(llvm::raw_ostream &OS = llvm::outs()) const = 0; [[nodiscard]] virtual nlohmann::json getAsJson() const = 0; + + virtual void printAsJson(llvm::raw_ostream &OS) const = 0; }; template diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index b8b28b9b3..c2b2f2976 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -15,7 +15,7 @@ #include namespace psr { -static CallGraphData stringifyJson(const nlohmann::json &Json) { +static CallGraphData getDataFromJson(const nlohmann::json &Json) { CallGraphData ToReturn; // map F to vector of n_t's @@ -28,7 +28,8 @@ static CallGraphData stringifyJson(const nlohmann::json &Json) { FunctionVertexTyVals.push_back(CurrentFunctionVertexTy); } - ToReturn.FToFunctionVertexTy.try_emplace(FValueString, FunctionVertexTyVals); + ToReturn.FToFunctionVertexTy.try_emplace(FValueString, + FunctionVertexTyVals); } return ToReturn; @@ -47,13 +48,13 @@ void CallGraphData::printAsJson(llvm::raw_ostream &OS) { } CallGraphData CallGraphData::deserializeJson(const llvm::Twine &Path) { - return stringifyJson(readJsonFile(Path)); + return getDataFromJson(readJsonFile(Path)); } CallGraphData CallGraphData::loadJsonString(const std::string &JsonAsString) { // nlohmann::json::parse needs a std::string, llvm::Twine won't work nlohmann::json ToStringify = nlohmann::json::parse(JsonAsString); - return stringifyJson(ToStringify); + return getDataFromJson(ToStringify); } } // namespace psr diff --git a/lib/Controller/AnalysisController.cpp b/lib/Controller/AnalysisController.cpp index fd77d2ec5..98f44f609 100644 --- a/lib/Controller/AnalysisController.cpp +++ b/lib/Controller/AnalysisController.cpp @@ -72,7 +72,7 @@ emitRequestedHelperAnalysisResults(AnalysisController::ControllerData &Data) { } if (EmitterOptions & AnalysisControllerEmitterOptions::EmitCGAsJson) { WithResultFileOrStdout("/psr-cg.json", - [&HA](auto &OS) { OS << HA.getICFG().getAsJson(); }); + [&HA](auto &OS) { HA.getICFG().printAsJson(OS); }); } if (EmitterOptions & diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index e84c09f17..ce94ee708 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -252,7 +252,13 @@ void DIBasedTypeHierarchy::print(llvm::raw_ostream &OS) const { } } -[[nodiscard]] nlohmann::json DIBasedTypeHierarchy::getAsJson() const { +[[nodiscard]] [[deprecated("Please use printAsJson() instead")]] nlohmann::json +DIBasedTypeHierarchy::getAsJson() const { + /// TODO: implement + llvm::report_fatal_error("Not implemented"); +} + +void DIBasedTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { /// TODO: implement llvm::report_fatal_error("Not implemented"); } From 36ae5b9fbaabaa8bfb5eabd1791dc6ee60ed5ac8 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 22 Mar 2024 19:23:18 +0100 Subject: [PATCH 08/42] fixed function with no caller not being serialized --- include/phasar/ControlFlow/CallGraph.h | 37 +++++++------------ .../PhasarLLVM/TypeHierarchy/LLVMVFTable.h | 2 + include/phasar/TypeHierarchy/VFTable.h | 2 + lib/ControlFlow/CallGraphData.cpp | 12 +++--- lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp | 6 +++ .../LLVMBasedICFGSerializationTest.cpp | 2 + 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 7428cff5c..043d6956d 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -26,6 +26,7 @@ #include "nlohmann/json.hpp" +#include #include #include #include @@ -91,35 +92,23 @@ class CallGraph : public CallGraphBase> { [[nodiscard]] bool empty() const noexcept { return CallersOf.empty(); } - template - void stringifyCallersOf(CallGraphData &Container, - FunctionIdGetter GetFunctionId, - InstIdGetter GetInstructionId) const { - for (const auto &[Fun, Callers] : CallersOf) { - std::string FValueString = GetFunctionId(Fun); - - std::vector FunctionVertexTyVals; - for (const auto &CS : *Callers) { - FunctionVertexTyVals.push_back(GetInstructionId(CS)); - } - - // if a function exists but the callers size is zero, a value of null - // should be inserted, to represent the existance of that function. An - // example of this happening is __psrCRuntimeGlobalCtorsModel - if (Callers->size() == 0) { - Container.FToFunctionVertexTy.insert({FValueString, {0}}); - } - Container.FToFunctionVertexTy.try_emplace( - std::move(FValueString), std::move(FunctionVertexTyVals)); - } - } - template void printAsJson(llvm::raw_ostream &OS, FunctionIdGetter GetFunctionId, InstIdGetter GetInstructionId) const { CallGraphData CGData; + CGData.FToFunctionVertexTy.reserve(CallersOf.size()); - stringifyCallersOf(CGData, GetFunctionId, GetInstructionId); + for (const auto &[Fun, Callers] : CallersOf) { + auto &JCallers = CGData.FToFunctionVertexTy[std::invoke(GetFunctionId, Fun)]; + + CGData.FToFunctionVertexTy.reserve(Callers->size()); + // set null value to represent a function with no callers + // example: __psrCRuntimeGlobalCtorsModel + //JCallers.push_back(0); + for (const auto &CS : *Callers) { + JCallers.push_back(std::invoke(GetInstructionId, CS)); + } + } CGData.printAsJson(OS); } diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h index fd55a006a..82981f7a4 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h @@ -68,6 +68,8 @@ class LLVMVFTable : public VFTable { [[nodiscard]] nlohmann::json getAsJson() const override; + void printAsJson(llvm::raw_ostream &OS) const override; + [[nodiscard]] std::vector::iterator begin() { return VFT.begin(); } diff --git a/include/phasar/TypeHierarchy/VFTable.h b/include/phasar/TypeHierarchy/VFTable.h index 56334171b..83f354a8f 100644 --- a/include/phasar/TypeHierarchy/VFTable.h +++ b/include/phasar/TypeHierarchy/VFTable.h @@ -39,6 +39,8 @@ template class VFTable { virtual void print(llvm::raw_ostream &OS) const = 0; [[nodiscard]] virtual nlohmann::json getAsJson() const = 0; + + virtual void printAsJson(llvm::raw_ostream &OS) const = 0; }; template diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index c2b2f2976..a6df3772f 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -36,13 +36,15 @@ static CallGraphData getDataFromJson(const nlohmann::json &Json) { } void CallGraphData::printAsJson(llvm::raw_ostream &OS) { - nlohmann::json JSON; + nlohmann::json JSON; - for (const auto &CurrentElement : FToFunctionVertexTy) { - for (const auto &NTVal : CurrentElement.second) { - JSON[CurrentElement.first].push_back(NTVal); + for (const auto &[Fun, Callers] : FToFunctionVertexTy) { + auto &JCallers = JSON[Fun]; + + for (const auto &CS : Callers) { + JCallers.push_back(CS); + } } - } OS << JSON; } diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp index 76c2f7c82..ced61d660 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp @@ -8,6 +8,7 @@ *****************************************************************************/ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h" +#include "phasar/Utils/NlohmannLogging.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" @@ -49,6 +50,11 @@ nlohmann::json LLVMVFTable::getAsJson() const { return J; } +void LLVMVFTable::printAsJson(llvm::raw_ostream &OS) const { + nlohmann::json Json = "{}"_json; + OS << Json; +} + std::vector LLVMVFTable::getVFVectorFromIRVTable(const llvm::ConstantStruct &VT) { std::vector VFS; diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp index 194872b8d..9459ae08e 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp @@ -30,6 +30,8 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { ICF.printAsJson(StringStream); + auto DebugTest = ICF.getAsJson(); + // deserialize data into CallGraphData object psr::LLVMBasedICFG DeserializedICF(&IRDB, psr::CallGraphData::loadJsonString(Ser)); From 7af57e4d23f02d56759eeaaf4f9f5692ae40cc90 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel <52407375+fabianbs96@users.noreply.github.com> Date: Wed, 13 Mar 2024 21:10:10 +0100 Subject: [PATCH 09/42] Fix Dependendency Installation (#707) * Do not install phasar's dependencies to the global namespace anymore * fix for in-tree build * out-factor the inclusion of LLVM and clang to a separate cmake file * Make PHASAR_CONFIG_INSTALL_DIR respect the CMAKE_INSTALL_PREFIX, even if that is not set at configure time * Fix in-tree build --- CMakeLists.txt | 153 ++++++---------------------------- Config.cmake.in | 7 +- cmake/add_llvm.cmake | 96 +++++++++++++++++++++ cmake/add_nlohmann_json.cmake | 54 ++++++++++++ 4 files changed, 180 insertions(+), 130 deletions(-) create mode 100644 cmake/add_llvm.cmake create mode 100644 cmake/add_nlohmann_json.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index d1f44d491..879caeddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,8 +218,8 @@ else() message(STATUS "Dynamic log disabled") endif() -# RPATH if (NOT PHASAR_IN_TREE) + # RPATH set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) if (NOT "${CMAKE_INSTALL_LIBDIR}" STREQUAL "lib") @@ -228,6 +228,13 @@ if (NOT PHASAR_IN_TREE) endif() set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + # Export set + set(PHASAR_DEPS_EXPORT_SET PhasarDepsExports) + set(PHASAR_DEPS_INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/phasar/deps) +else() + # Export set + set(PHASAR_DEPS_EXPORT_SET LLVMExports) endif() # Filesystem @@ -238,9 +245,9 @@ else() endif() # Config -set(PHASAR_CUSTOM_CONFIG_INSTALL_DIR "" CACHE STRING "If set, customizes the directory, where configuration files for PhASAR are installed (default is /usr/local/.phasar-config)") +set(PHASAR_CUSTOM_CONFIG_INSTALL_DIR "" CACHE STRING "If set, customizes the directory, where configuration files for PhASAR are installed (default is ${CMAKE_INSTALL_PREFIX}/.phasar-config)") if ("${PHASAR_CUSTOM_CONFIG_INSTALL_DIR}" STREQUAL "") - set(PHASAR_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/.phasar-config/") + set(PHASAR_CONFIG_INSTALL_DIR ".phasar-config/") else() set(PHASAR_CONFIG_INSTALL_DIR "${PHASAR_CUSTOM_CONFIG_INSTALL_DIR}") endif() @@ -268,31 +275,10 @@ find_package(Boost 1.65.1 COMPONENTS graph REQUIRED) set(CMAKE_CXX_CLANG_TIDY "") # Nlohmann JSON -set(JSON_BuildTests OFF) -set(JSON_Install ON) -set(JSON_SystemInclude ON) -add_subdirectory(external/json EXCLUDE_FROM_ALL) - -# We need to work around the behavior of nlohmann_json_schema_validator and nlohmann_json here -# The validator needs the json part, but if you include it, the library of nlohmann_json_schema_validator -# is not installed, leading to linker error. But just including nlohmann_json is not sufficient, as -# in the installed state the nlohmann_json_schema_validator needs the nlohmann_json package which needs -# to be installed. -# The following workaround may collapse or become unnecessary once the issue is -# changed or fixed in nlohmann_json_schema_validator. - -# Override option of nlohmann_json_schema_validator to not build its tests -set(BUILD_TESTS OFF CACHE BOOL "Build json-schema-validator-tests") - -if (PHASAR_IN_TREE) - set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator) - - set (PHASAR_USE_Z3 OFF) -endif() -# Json Schema Validator -set(JSON_VALIDATOR_INSTALL ON) -add_subdirectory(external/json-schema-validator EXCLUDE_FROM_ALL) +include(add_nlohmann_json) +add_nlohmann_json() +add_json_schema_validator() # Googletest if (NOT PHASAR_IN_TREE) @@ -318,57 +304,14 @@ find_library(SQLITE3_LIBRARY NAMES sqlite3) option(USE_LLVM_FAT_LIB "Link against libLLVM.so instead of the individual LLVM libraries if possible (default is OFF; always on if BUILD_SHARED_LIBS is ON)" OFF) # LLVM -if (NOT PHASAR_IN_TREE) - # Only search for LLVM if we build out of tree - find_package(LLVM 14 REQUIRED CONFIG) - find_library(LLVM_LIBRARY NAMES LLVM PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - - if(USE_LLVM_FAT_LIB AND ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") - message(WARNING "Did not find requested libLLVM.so. Link against individual modules instead") - set(USE_LLVM_FAT_LIB OFF) - elseif(BUILD_SHARED_LIBS AND NOT ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") - message(STATUS "Found consolidated shared LLVM lib ${LLVM_LIBRARY} that will be linked against.") - set(USE_LLVM_FAT_LIB ON) - endif() - - if (NOT USE_LLVM_FAT_LIB) - message(STATUS "Link against individual LLVM modules") - set(LLVM_REQUIRED_LIBRARIES - Core - Support - BitWriter - Analysis - Passes - Demangle - Analysis - IRReader - Linker - ) - foreach(lib ${LLVM_REQUIRED_LIBRARIES}) - find_library(LLVM_SMALL_LIB${lib} NAMES LLVM${lib} PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - if(LLVM_SMALL_LIB${lib} MATCHES "NOTFOUND$") - list(APPEND LLVM_SMALL_LIB_NOTFOUND "LLVM${lib}") - endif() - endforeach() - - if(DEFINED LLVM_SMALL_LIB_NOTFOUND) - if(${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") - message(FATAL_ERROR "Did not find a complete version of LLVM: Did not find the fat lib libLLVM.so, but also did not find the individual modules ${LLVM_SMALL_LIB_NOTFOUND}.") - else() - set(USE_LLVM_FAT_LIB ON) - list(JOIN LLVM_SMALL_LIB_NOTFOUND ", " LLVM_SMALL_LIB_NOTFOUND_PRETTY) - message(WARNING "Did not find the LLVM modules ${LLVM_SMALL_LIB_NOTFOUND_PRETTY}. Fallback to link against ${LLVM_LIBRARY}. To silence this warning, set -DUSE_LLVM_FAT_LIB=ON in the cmake invocation.") - endif() - endif(DEFINED LLVM_SMALL_LIB_NOTFOUND) - endif(NOT USE_LLVM_FAT_LIB) -endif(NOT PHASAR_IN_TREE) - -if(NOT LLVM_ENABLE_RTTI AND NOT PHASAR_IN_TREE) - message(FATAL_ERROR "PhASAR requires a LLVM version that is built with RTTI") -endif() +include(add_llvm) +add_llvm() # Z3 Solver -if(PHASAR_USE_Z3) +if(PHASAR_IN_TREE) + set (PHASAR_USE_Z3 OFF) +endif() +if(PHASAR_USE_Z3 AND NOT PHASAR_IN_TREE) # This z3-version is the same version LLVM requires; however, we cannot just use Z3 via the LLVM interface # as it lacks some functionality (such as z3::expr::simplify()) that we require find_package(Z3 4.7.1 REQUIRED) @@ -380,54 +323,13 @@ if(PHASAR_USE_Z3) set_property(TARGET z3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Z3_INCLUDE_DIR}) endif() -endif(PHASAR_USE_Z3) +endif() # Clang option(BUILD_PHASAR_CLANG "Build the phasar_clang library (default is ON)" ON) - if(BUILD_PHASAR_CLANG) - # The clang-cpp shared library is now the preferred way to link dynamically against libclang if we build out of tree. - if(NOT PHASAR_IN_TREE) - find_library(CLANG_LIBRARY NAMES clang-cpp libclang-cpp HINTS ${LLVM_LIBRARY_DIRS}) - if(${CLANG_LIBRARY} STREQUAL "CLANG_LIBRARY-NOTFOUND") - set(NEED_LIBCLANG_COMPONENT_LIBS on) - endif() - endif() - # As fallback, look for the small clang libraries - if(PHASAR_IN_TREE OR NEED_LIBCLANG_COMPONENT_LIBS) - set(CLANG_LIBRARY - clangTooling - clangFrontendTool - clangFrontend - clangDriver - clangSerialization - clangCodeGen - clangParse - clangSema - clangStaticAnalyzerFrontend - clangStaticAnalyzerCheckers - clangStaticAnalyzerCore - clangAnalysis - clangARCMigrate - clangRewrite - clangRewriteFrontend - clangEdit - clangAST - clangASTMatchers - clangLex - clangBasic - LLVMFrontendOpenMP) - endif() - - if (PHASAR_IN_TREE) - # Phasar needs clang headers, specificaly some that are generated by clangs table-gen - include_directories( - ${CLANG_INCLUDE_DIR} - ${PHASAR_SRC_DIR}/../clang/include - ${PROJECT_BINARY_DIR}/tools/clang/include - ) - endif() -endif(BUILD_PHASAR_CLANG) + add_clang() +endif() # Set up clang-tidy to run during PhASAR's compilation to indicate code smells if (PHASAR_ENABLE_CLANG_TIDY_DURING_BUILD) @@ -529,6 +431,11 @@ if(NOT PHASAR_IN_TREE) NAMESPACE phasar:: DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/phasar" ) + install(EXPORT ${PHASAR_DEPS_EXPORT_SET} + FILE ${PHASAR_DEPS_EXPORT_SET}.cmake + NAMESPACE phasar:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/phasar" + ) else() install(TARGETS phasar_interface EXPORT LLVMExports @@ -536,12 +443,6 @@ else() set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS phasar_interface) endif() -# Install the header only json container ### TODO Fix this! -install(DIRECTORY external/json/single_include/ - DESTINATION include - FILES_MATCHING PATTERN "*.hpp" -) - # Install Phasar utils helper scripts install(DIRECTORY utils/ DESTINATION bin diff --git a/Config.cmake.in b/Config.cmake.in index 305cf04e2..f160d869b 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -5,11 +5,10 @@ set_and_check(PHASAR_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(PHASAR_LIBRARY_DIR "@PACKAGE_LIBRARY_INSTALL_DIR@") include (CMakeFindDependencyMacro) -find_dependency(nlohmann_json) -find_dependency(nlohmann_json_schema_validator) -find_package(Boost 1.65.1 COMPONENTS graph REQUIRED) -find_package(LLVM 14 REQUIRED CONFIG) +include("${CMAKE_CURRENT_LIST_DIR}/PhasarDepsExports.cmake") +find_dependency(Boost 1.65.1 COMPONENTS graph REQUIRED) +find_dependency(LLVM 14 REQUIRED CONFIG) set(PHASAR_USE_LLVM_FAT_LIB @USE_LLVM_FAT_LIB@) set(PHASAR_BUILD_DYNLIB @PHASAR_BUILD_DYNLIB@) diff --git a/cmake/add_llvm.cmake b/cmake/add_llvm.cmake new file mode 100644 index 000000000..7cf3ceb94 --- /dev/null +++ b/cmake/add_llvm.cmake @@ -0,0 +1,96 @@ +macro(add_llvm) + + if (NOT PHASAR_IN_TREE) + # Only search for LLVM if we build out of tree + find_package(LLVM 14 REQUIRED CONFIG) + find_library(LLVM_LIBRARY NAMES LLVM PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + + if(USE_LLVM_FAT_LIB AND ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") + message(WARNING "Did not find requested libLLVM.so. Link against individual modules instead") + set(USE_LLVM_FAT_LIB OFF) + elseif(BUILD_SHARED_LIBS AND NOT ${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") + message(STATUS "Found consolidated shared LLVM lib ${LLVM_LIBRARY} that will be linked against.") + set(USE_LLVM_FAT_LIB ON) + endif() + + if (NOT USE_LLVM_FAT_LIB) + message(STATUS "Link against individual LLVM modules") + set(LLVM_REQUIRED_LIBRARIES + Core + Support + BitWriter + Analysis + Passes + Demangle + Analysis + IRReader + Linker + ) + foreach(lib ${LLVM_REQUIRED_LIBRARIES}) + find_library(LLVM_SMALL_LIB${lib} NAMES LLVM${lib} PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + if(LLVM_SMALL_LIB${lib} MATCHES "NOTFOUND$") + list(APPEND LLVM_SMALL_LIB_NOTFOUND "LLVM${lib}") + endif() + endforeach() + + if(DEFINED LLVM_SMALL_LIB_NOTFOUND) + if(${LLVM_LIBRARY} STREQUAL "LLVM_LIBRARY-NOTFOUND") + message(FATAL_ERROR "Did not find a complete version of LLVM: Did not find the fat lib libLLVM.so, but also did not find the individual modules ${LLVM_SMALL_LIB_NOTFOUND}.") + else() + set(USE_LLVM_FAT_LIB ON) + list(JOIN LLVM_SMALL_LIB_NOTFOUND ", " LLVM_SMALL_LIB_NOTFOUND_PRETTY) + message(WARNING "Did not find the LLVM modules ${LLVM_SMALL_LIB_NOTFOUND_PRETTY}. Fallback to link against ${LLVM_LIBRARY}. To silence this warning, set -DUSE_LLVM_FAT_LIB=ON in the cmake invocation.") + endif() + endif(DEFINED LLVM_SMALL_LIB_NOTFOUND) + endif(NOT USE_LLVM_FAT_LIB) + endif(NOT PHASAR_IN_TREE) + + if(NOT LLVM_ENABLE_RTTI AND NOT PHASAR_IN_TREE) + message(FATAL_ERROR "PhASAR requires a LLVM version that is built with RTTI") + endif() + +endmacro() + +macro(add_clang) + # The clang-cpp shared library is now the preferred way to link dynamically against libclang if we build out of tree. + if(NOT PHASAR_IN_TREE) + find_library(CLANG_LIBRARY NAMES clang-cpp libclang-cpp HINTS ${LLVM_LIBRARY_DIRS}) + if(${CLANG_LIBRARY} STREQUAL "CLANG_LIBRARY-NOTFOUND") + set(NEED_LIBCLANG_COMPONENT_LIBS ON) + endif() + endif() + # As fallback, look for the small clang libraries + if(PHASAR_IN_TREE OR NEED_LIBCLANG_COMPONENT_LIBS) + set(CLANG_LIBRARY + clangTooling + clangFrontendTool + clangFrontend + clangDriver + clangSerialization + clangCodeGen + clangParse + clangSema + clangStaticAnalyzerFrontend + clangStaticAnalyzerCheckers + clangStaticAnalyzerCore + clangAnalysis + clangARCMigrate + clangRewrite + clangRewriteFrontend + clangEdit + clangAST + clangASTMatchers + clangLex + clangBasic + LLVMFrontendOpenMP) + endif() + + if (PHASAR_IN_TREE) + # Phasar needs clang headers, specificaly some that are generated by clangs table-gen + include_directories( + ${CLANG_INCLUDE_DIR} + ${PHASAR_SRC_DIR}/../clang/include + ${PROJECT_BINARY_DIR}/tools/clang/include + ) + endif() +endmacro(add_clang) diff --git a/cmake/add_nlohmann_json.cmake b/cmake/add_nlohmann_json.cmake new file mode 100644 index 000000000..3c3d4a18e --- /dev/null +++ b/cmake/add_nlohmann_json.cmake @@ -0,0 +1,54 @@ + +function(add_nlohmann_json) + set(JSON_BuildTests OFF) + set(JSON_Install OFF) + + if (PHASAR_IN_TREE) + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json) + endif() + + add_subdirectory(external/json EXCLUDE_FROM_ALL) + set_property(TARGET nlohmann_json APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES $ + ) + + install(TARGETS nlohmann_json + EXPORT ${PHASAR_DEPS_EXPORT_SET} + LIBRARY DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/lib + ARCHIVE DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/lib + RUNTIME DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/bin + ) + install(DIRECTORY external/json/include/ + DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/include + ) +endfunction() + +function(add_json_schema_validator) + # We need to work around the behavior of nlohmann_json_schema_validator and nlohmann_json here + # The validator needs the json part, but if you include it, the library of nlohmann_json_schema_validator + # is not installed, leading to linker error. But just including nlohmann_json is not sufficient, as + # in the installed state the nlohmann_json_schema_validator needs the nlohmann_json package which needs + # to be installed. + # The following workaround may collapse or become unnecessary once the issue is + # changed or fixed in nlohmann_json_schema_validator. + if (PHASAR_IN_TREE) + set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS nlohmann_json_schema_validator) + endif() + + set(JSON_VALIDATOR_INSTALL OFF) + + add_subdirectory(external/json-schema-validator EXCLUDE_FROM_ALL) + set_property(TARGET nlohmann_json_schema_validator APPEND PROPERTY + INTERFACE_INCLUDE_DIRECTORIES $ + ) + + install(TARGETS nlohmann_json_schema_validator + EXPORT ${PHASAR_DEPS_EXPORT_SET} + LIBRARY DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/lib + ARCHIVE DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/lib + RUNTIME DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/bin + ) + install(FILES external/json-schema-validator/src/nlohmann/json-schema.hpp + DESTINATION ${PHASAR_DEPS_INSTALL_DESTINATION}/include/nlohmann + ) +endfunction() From a4091ca909a92bdf69f63c88cbdd2c7db89110e1 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 26 Mar 2024 22:39:51 +0100 Subject: [PATCH 10/42] backup DIBTH Data --- .../TypeHierarchy/DIBasedTypeHierarchy.h | 5 + .../TypeHierarchy/DIBasedTypeHierarchyData.h | 44 + include/phasar/Pointer/AliasInfo.h | 6 +- include/phasar/Pointer/AliasInfoBase.h | 5 +- lib/ControlFlow/CallGraphData.cpp | 12 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 53 +- .../DIBasedTypeHierarchyData.cpp | 74 + .../LLVMBasedICFGSerializationTest.cpp | 2 - .../DIBasedTypeHierarchySerializationTest.cpp | 2220 +++++++++++++++++ 9 files changed, 2407 insertions(+), 14 deletions(-) create mode 100644 include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h create mode 100644 lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp create mode 100644 unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index 1cc79d98a..09d438b46 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHY_H #define PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHY_H +#include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h" #include "phasar/TypeHierarchy/TypeHierarchy.h" @@ -32,6 +33,8 @@ class DIBasedTypeHierarchy using f_t = const llvm::Function *; explicit DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB); + explicit DIBasedTypeHierarchy(const LLVMProjectIRDB *IRDB, + const DIBasedTypeHierarchyData &SerializedCG); ~DIBasedTypeHierarchy() override = default; [[nodiscard]] bool hasType(ClassType Type) const override { @@ -101,6 +104,8 @@ class DIBasedTypeHierarchy */ void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const override; + [[nodiscard]] DIBasedTypeHierarchyData stringifyTypeHierarchy() const; + private: [[nodiscard]] llvm::iterator_range subTypesOf(size_t TypeIdx) const noexcept; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h new file mode 100644 index 000000000..4361a4dc1 --- /dev/null +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHYDATA_H +#define PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHYDATA_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/raw_ostream.h" + +#include + +namespace psr { +struct DIBasedTypeHierarchyData { + DIBasedTypeHierarchyData() noexcept = default; + + // StringMap of ClassType as string + llvm::StringMap NameToType; + // DenseMap of ClassType as string and according size_t + llvm::DenseMap TypeToVertex; + // Vector of llvm::DICompositeType as string + std::vector VertexTypes; + // Vector of pairs of uint32_ts + std::vector> TransitiveDerivedIndex; + // Vector of ClassType as string + std::vector Hierarchy; + // Deque of LLVMVFTable (std::vector) as string + std::deque> VTables; + + void printAsJson(llvm::raw_ostream &OS); + static DIBasedTypeHierarchyData deserializeJson(const llvm::Twine &Path); + static DIBasedTypeHierarchyData + loadJsonString(const std::string &JsonAsString); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHYDATA_H diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index ba9fa480f..9f38a4f3c 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -241,7 +241,11 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { static_cast(AA)->print(OS); }, [](const void *AA) { - return static_cast(AA)->getAsJson(); + if (static_cast(AA)->getAsJson()) { + return static_cast(AA)->getAsJson(); + } + + return nlohmann::json(); }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); diff --git a/include/phasar/Pointer/AliasInfoBase.h b/include/phasar/Pointer/AliasInfoBase.h index b3bb828c1..4639c4a51 100644 --- a/include/phasar/Pointer/AliasInfoBase.h +++ b/include/phasar/Pointer/AliasInfoBase.h @@ -48,7 +48,7 @@ auto testAliasInfo( CAI.isInterProcedural(), CAI.getAliasAnalysisType(), AI.alias(*VT, *VT, *NT), AI.getAliasSet(*VT, *NT), AI.getReachableAllocationSites(*VT, true, *NT), - AI.isInReachableAllocationSites(*VT, *VT, true, *NT), CAI.getAsJson(), + AI.isInReachableAllocationSites(*VT, *VT, true, *NT), CAI.getAnalysisProperties(), CAI.isContextSensitive(), CAI.isFieldSensitive(), CAI.isFlowSensitive())); template @@ -67,8 +67,7 @@ struct IsAliasInfo< std::enable_if_t::AliasSetPtrTy, - typename AliasInfoTraits::AllocationSiteSetPtrTy, bool, - nlohmann::json, AnalysisProperties, bool, bool, bool>, + typename AliasInfoTraits::AllocationSiteSetPtrTy, bool, AnalysisProperties, bool, bool, bool>, decltype(testAliasInfo(std::declval(), std::declval()))>>> : std::true_type { }; diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index a6df3772f..352da02e0 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -36,15 +36,15 @@ static CallGraphData getDataFromJson(const nlohmann::json &Json) { } void CallGraphData::printAsJson(llvm::raw_ostream &OS) { - nlohmann::json JSON; + nlohmann::json JSON; - for (const auto &[Fun, Callers] : FToFunctionVertexTy) { - auto &JCallers = JSON[Fun]; + for (const auto &[Fun, Callers] : FToFunctionVertexTy) { + auto &JCallers = JSON[Fun]; - for (const auto &CS : Callers) { - JCallers.push_back(CS); - } + for (const auto &CS : Callers) { + JCallers.push_back(CS); } + } OS << JSON; } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index ce94ee708..60e7ec0ed 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -10,6 +10,7 @@ #include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/Utilities.h" @@ -29,6 +30,9 @@ #include "llvm/Support/raw_ostream.h" #include +#include +#include +#include namespace psr { using ClassType = DIBasedTypeHierarchy::ClassType; @@ -189,6 +193,11 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { buildTypeHierarchy(TG, VertexTypes, TransitiveDerivedIndex, Hierarchy); } +DIBasedTypeHierarchy::DIBasedTypeHierarchy( + const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedCG) { + /// TODO: implement +} + auto DIBasedTypeHierarchy::subTypesOf(size_t TypeIdx) const noexcept -> llvm::iterator_range { const auto *Data = Hierarchy.data(); @@ -258,9 +267,49 @@ DIBasedTypeHierarchy::getAsJson() const { llvm::report_fatal_error("Not implemented"); } +DIBasedTypeHierarchyData DIBasedTypeHierarchy::stringifyTypeHierarchy() 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().str(), + Curr.getSecond()); + } + + for (const auto &Curr : VertexTypes) { + Data.VertexTypes.push_back(Curr->getName().str()); + } + + for (const auto &Curr : TransitiveDerivedIndex) { + Data.TransitiveDerivedIndex.emplace_back( + std::pair(Curr.first, Curr.second)); + } + + for (const auto &Curr : Hierarchy) { + Data.Hierarchy.push_back(Curr->getName().str()); + } + + for (const auto &Curr : VTables) { + std::vector CurrVTableAsString; + CurrVTableAsString.reserve(Curr.getAllFunctions().size()); + + for (const auto &Func : Curr.getAllFunctions()) { + CurrVTableAsString.push_back(Func->getName().str()); + } + + Data.VTables.emplace_back(std::move(CurrVTableAsString)); + } + + return Data; +} + void DIBasedTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { - /// TODO: implement - llvm::report_fatal_error("Not implemented"); + DIBasedTypeHierarchyData Data = stringifyTypeHierarchy(); + Data.printAsJson(OS); } void DIBasedTypeHierarchy::printAsDot(llvm::raw_ostream &OS) const { diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp new file mode 100644 index 000000000..bd29a705d --- /dev/null +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -0,0 +1,74 @@ +/****************************************************************************** + * 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/TypeHierarchy/DIBasedTypeHierarchyData.h" + +#include "phasar/Utils/IO.h" +#include "phasar/Utils/NlohmannLogging.h" + +#include + +namespace psr { + +static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { + DIBasedTypeHierarchyData ToReturn; + + return ToReturn; +} + +void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json JSON; + + for (const auto &Curr : NameToType) { + JSON["NameToType"][Curr.first()] = Curr.second; + } + + for (const auto &Curr : TypeToVertex) { + JSON["TypeToVertex"][Curr.first] = Curr.second; + } + + for (const auto &Curr : VertexTypes) { + JSON["VertexTypes"].push_back(Curr); + } + + for (const auto &Curr : TransitiveDerivedIndex) { + JSON["TransitiveDerivedIndex"][Curr.first] = Curr.second; + } + + for (const auto &Curr : Hierarchy) { + JSON["Hierarchy"].push_back(Curr); + } + + for (const auto &CurrVTable : VTables) { + std::vector ToAdd; + ToAdd.reserve(CurrVTable.size()); + + for (const auto &Curr : CurrVTable) { + ToAdd.push_back(Curr); + } + + JSON["VTables"].push_back(ToAdd); + } + + OS << JSON; +} + +DIBasedTypeHierarchyData +DIBasedTypeHierarchyData::deserializeJson(const llvm::Twine &Path) { + return getDataFromJson(readJsonFile(Path)); +} + +DIBasedTypeHierarchyData +DIBasedTypeHierarchyData::loadJsonString(const std::string &JsonAsString) { + // nlohmann::json::parse needs a std::string, llvm::Twine won't work + nlohmann::json ToStringify = nlohmann::json::parse(JsonAsString); + return getDataFromJson(ToStringify); +} + +} // namespace psr diff --git a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp index 9459ae08e..194872b8d 100644 --- a/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp +++ b/unittests/PhasarLLVM/ControlFlow/LLVMBasedICFGSerializationTest.cpp @@ -30,8 +30,6 @@ class LLVMBasedICFGGSerializationTest : public ::testing::Test { ICF.printAsJson(StringStream); - auto DebugTest = ICF.getAsJson(); - // deserialize data into CallGraphData object psr::LLVMBasedICFG DeserializedICF(&IRDB, psr::CallGraphData::loadJsonString(Ser)); diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp new file mode 100644 index 000000000..55024d2bd --- /dev/null +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -0,0 +1,2220 @@ + +#include "phasar/Config/Configuration.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/Utilities.h" + +#include "TestConfig.h" +#include "gtest/gtest.h" + +namespace psr { + +void serAndDeser(const llvm::Twine &IRFile) { + // +} + +void compareResults(const psr::DIBasedTypeHierarchy &Orig, + const psr::DIBasedTypeHierarchy &Deser) { + // +} + +/* +--------------------------- +BasicTHReconstruction Tests +--------------------------- +*/ + +TEST(DBTHTest, BasicTHReconstruction_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + std::string Ser; + // stream ICF data into a json file using the printAsJson() function + llvm::raw_string_ostream StringStream(Ser); + + DBTH.printAsJson(StringStream); + + auto DebugTest = DBTH.getAsJson(); + + // deserialize data into CallGraphData object + psr::DIBasedTypeHierarchy DeserializedTypeHierarchy( + &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); + + compareResults(DBTH, DeserializedTypeHierarchy); +} + +TEST(DBTHTest, BasicTHReconstruction_2) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_3) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_4) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_5) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 3U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &OtherBaseType = DBTH.getType("OtherBase"); + ASSERT_NE(nullptr, OtherBaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(OtherBaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypesBase = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypesBase.find(ChildType) != SubTypesBase.end()); + const auto &SubTypesOtherBase = DBTH.getSubTypes(OtherBaseType); + EXPECT_TRUE(SubTypesOtherBase.find(ChildType) != SubTypesOtherBase.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_6) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_7) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 7U); + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &BType = DBTH.getType("B"); + ASSERT_NE(nullptr, BType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &DType = DBTH.getType("D"); + ASSERT_NE(nullptr, DType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + + EXPECT_TRUE(DBTH.hasType(AType)); + EXPECT_TRUE(DBTH.hasType(BType)); + EXPECT_TRUE(DBTH.hasType(CType)); + EXPECT_TRUE(DBTH.hasType(DType)); + EXPECT_TRUE(DBTH.hasType(XType)); + EXPECT_TRUE(DBTH.hasType(YType)); + EXPECT_TRUE(DBTH.hasType(ZType)); + + // check for all subtypes + + // struct B : A {}; + // struct C : A {}; + const auto &SubTypesA = DBTH.getSubTypes(AType); + EXPECT_TRUE(SubTypesA.find(BType) != SubTypesA.end()); + EXPECT_TRUE(SubTypesA.find(CType) != SubTypesA.end()); + // struct D : B {}; + const auto &SubTypesB = DBTH.getSubTypes(BType); + EXPECT_TRUE(SubTypesB.find(DType) != SubTypesB.end()); + // struct Z : C, Y {}; + const auto &SubTypesC = DBTH.getSubTypes(CType); + EXPECT_TRUE(SubTypesC.find(ZType) != SubTypesC.end()); + // struct Y : X {}; + const auto &SubTypesX = DBTH.getSubTypes(XType); + EXPECT_TRUE(SubTypesX.find(YType) != SubTypesX.end()); + // struct Z : C, Y {}; + const auto &SubTypesY = DBTH.getSubTypes(YType); + EXPECT_TRUE(SubTypesY.find(ZType) != SubTypesY.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_7_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 6U); + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + const auto &OmegaType = DBTH.getType("Omega"); + ASSERT_NE(nullptr, OmegaType); + + EXPECT_TRUE(DBTH.hasType(AType)); + EXPECT_TRUE(DBTH.hasType(CType)); + EXPECT_TRUE(DBTH.hasType(XType)); + EXPECT_TRUE(DBTH.hasType(YType)); + EXPECT_TRUE(DBTH.hasType(ZType)); + EXPECT_TRUE(DBTH.hasType(OmegaType)); + + // check for all subtypes + + // struct C : A {}; + const auto &SubTypesA = DBTH.getSubTypes(AType); + EXPECT_TRUE(SubTypesA.find(CType) != SubTypesA.end()); + // struct Z : C, Y {}; + const auto &SubTypesC = DBTH.getSubTypes(CType); + EXPECT_TRUE(SubTypesC.find(ZType) != SubTypesC.end()); + // struct Y : X {}; + const auto &SubTypesX = DBTH.getSubTypes(XType); + EXPECT_TRUE(SubTypesX.find(YType) != SubTypesX.end()); + // struct Z : C, Y {}; + const auto &SubTypesY = DBTH.getSubTypes(YType); + EXPECT_TRUE(SubTypesY.find(ZType) != SubTypesY.end()); + + // class Omega : Z { + const auto &SubTypesZ = DBTH.getSubTypes(ZType); + EXPECT_TRUE(SubTypesZ.find(OmegaType) != SubTypesZ.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_8) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 4U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + EXPECT_NE(nullptr, NonvirtualClassType); + const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + EXPECT_NE(nullptr, NonvirtualStructType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + EXPECT_TRUE(DBTH.hasType(NonvirtualClassType)); + EXPECT_TRUE(DBTH.hasType(NonvirtualStructType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_9) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_10) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_11) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_12) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_12_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 3U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + EXPECT_TRUE(DBTH.hasType(ChildsChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + EXPECT_TRUE(SubTypesChild.find(ChildsChildType) != SubTypesChild.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_12_c) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + EXPECT_TRUE(DBTH.hasType(ChildType)); + EXPECT_TRUE(DBTH.hasType(ChildsChildType)); + + // check for all subtypes + const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + EXPECT_TRUE(SubTypesChild.find(ChildsChildType) != SubTypesChild.end()); +} + +/* +TEST(DBTHTest, BasicTHReconstruction_13) { + Test file 13 has no types +} +*/ + +TEST(DBTHTest, BasicTHReconstruction_14) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 1U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + + // there are no subtypes here +} + +TEST(DBTHTest, BasicTHReconstruction_15) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 2U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_16) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 5U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // Since ChildsChild is never used, it is optimized out + // const auto &ChildsChildType = DBTH.getType("ChildsChild"); + // ASSERT_EQ(nullptr, ChildsChildType); + const auto &BaseTwoType = DBTH.getType("BaseTwo"); + ASSERT_NE(nullptr, BaseTwoType); + const auto &ChildTwoType = DBTH.getType("ChildTwo"); + ASSERT_NE(nullptr, ChildTwoType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + // Since ChildsChild is never used, it is optimized out + // EXPECT_FALSE(DBTH.hasType(ChildsChildType)); + EXPECT_TRUE(DBTH.hasType(BaseTwoType)); + EXPECT_TRUE(DBTH.hasType(ChildTwoType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + // Since ChildsChild is never used, it is optimized out + // EXPECT_TRUE(SubTypesChild.find(ChildsChildType) == SubTypesChild.end()); + const auto &SubTypesTwo = DBTH.getSubTypes(BaseTwoType); + EXPECT_TRUE(SubTypesTwo.find(ChildTwoType) != SubTypesTwo.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_17) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + // EXPECT_EQ(DBTH.getAllTypes().size(), 5U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // const auto &Child2Type = DBTH.getType("Child2"); + // Since Child2Type is never used, it is optimized out + // ASSERT_EQ(nullptr, Child2Type); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &KidType = DBTH.getType("Kid"); + ASSERT_NE(nullptr, KidType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + // Since ChildsChild is never used, it is optimized out + // EXPECT_FALSE(DBTH.hasType(Child2Type)); + EXPECT_TRUE(DBTH.hasType(Base2Type)); + EXPECT_TRUE(DBTH.hasType(KidType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + // Since ChildsChild is never used, it is optimized out + // EXPECT_TRUE(SubTypesChild.find(Child2Type) == SubTypesChild.end()); + const auto &SubTypesBase2 = DBTH.getSubTypes(Base2Type); + EXPECT_TRUE(SubTypesBase2.find(KidType) != SubTypesBase2.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_18) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 4U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // const auto &Child_2Type = DBTH.getType("Child_2"); + // Since Child2Type is never used, it is optimized out + // ASSERT_EQ(nullptr, Child2Type); + const auto &Child3Type = DBTH.getType("Child_3"); + ASSERT_NE(nullptr, Child3Type); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + // Since Child2 is never used, it is optimized out + // EXPECT_FALSE(DBTH.hasType(Child2Type)); + EXPECT_TRUE(DBTH.hasType(Child3Type)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + // Since Child2 is never used, it is optimized out + // EXPECT_TRUE(SubTypesChild.find(Child2Type) == SubTypesChild.end()); + const auto &SubTypesChild2 = DBTH.getSubTypes(Child3Type); + EXPECT_TRUE(SubTypesChild2.find(Child3Type) != SubTypesChild2.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_19) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 6U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &FooType = DBTH.getType("Foo"); + ASSERT_NE(nullptr, FooType); + const auto &BarType = DBTH.getType("Bar"); + ASSERT_NE(nullptr, BarType); + const auto &LoremType = DBTH.getType("Lorem"); + ASSERT_NE(nullptr, LoremType); + const auto &ImpsumType = DBTH.getType("Impsum"); + ASSERT_NE(nullptr, ImpsumType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + EXPECT_TRUE(DBTH.hasType(FooType)); + EXPECT_TRUE(DBTH.hasType(BarType)); + EXPECT_TRUE(DBTH.hasType(LoremType)); + EXPECT_TRUE(DBTH.hasType(ImpsumType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + const auto &SubTypesFoo = DBTH.getSubTypes(FooType); + EXPECT_TRUE(SubTypesFoo.find(BarType) != SubTypesFoo.end()); + const auto &SubTypesLorem = DBTH.getSubTypes(LoremType); + EXPECT_TRUE(SubTypesLorem.find(ImpsumType) != SubTypesLorem.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_20) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 3U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(Base2Type)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + const auto &SubTypes2 = DBTH.getSubTypes(Base2Type); + EXPECT_TRUE(SubTypes2.find(ChildType) != SubTypes2.end()); +} + +TEST(DBTHTest, BasicTHReconstruction_21) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + EXPECT_EQ(DBTH.getAllTypes().size(), 5U); + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &Base3Type = DBTH.getType("Base3"); + ASSERT_NE(nullptr, Base3Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &Child2Type = DBTH.getType("Child2"); + ASSERT_NE(nullptr, Child2Type); + + EXPECT_TRUE(DBTH.hasType(BaseType)); + EXPECT_TRUE(DBTH.hasType(Base2Type)); + EXPECT_TRUE(DBTH.hasType(Base3Type)); + EXPECT_TRUE(DBTH.hasType(ChildType)); + EXPECT_TRUE(DBTH.hasType(Child2Type)); + + // check for all subtypes + const auto &SubTypes = DBTH.getSubTypes(BaseType); + EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); + const auto &SubTypesBase2 = DBTH.getSubTypes(Base2Type); + EXPECT_TRUE(SubTypesBase2.find(ChildType) != SubTypesBase2.end()); + const auto &SubTypesChild = DBTH.getSubTypes(ChildType); + EXPECT_TRUE(SubTypesChild.find(Child2Type) != SubTypesChild.end()); + const auto &SubTypesBase3 = DBTH.getSubTypes(Base3Type); + EXPECT_TRUE(SubTypesBase3.find(Child2Type) != SubTypesBase3.end()); +} + +/* +------------------------ +VTableConstruction Tests +------------------------ +*/ + +TEST(DBTHTest, VTableConstruction_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + ASSERT_TRUE(DBTH.hasVFTable(BaseType)); + ASSERT_TRUE(DBTH.hasVFTable(ChildType)); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_2) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + ASSERT_TRUE(DBTH.hasVFTable(BaseType)); + ASSERT_TRUE(DBTH.hasVFTable(ChildType)); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_3) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + ASSERT_TRUE(DBTH.hasVFTable(BaseType)); + ASSERT_TRUE(DBTH.hasVFTable(ChildType)); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_4) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + ASSERT_TRUE(DBTH.hasVFTable(BaseType)); + ASSERT_TRUE(DBTH.hasVFTable(ChildType)); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3tarEv"); +} + +TEST(DBTHTest, VTableConstruction_5) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &OtherBaseType = DBTH.getType("OtherBase"); + ASSERT_NE(nullptr, OtherBaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + ASSERT_TRUE(DBTH.hasVFTable(BaseType)); + ASSERT_TRUE(DBTH.hasVFTable(OtherBaseType)); + ASSERT_TRUE(DBTH.hasVFTable(ChildType)); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForOtherBase = DBTH.getVFTable(OtherBaseType); + ASSERT_NE(nullptr, VTableForOtherBase); + ASSERT_NE(nullptr, VTableForOtherBase->getFunction(0)); + EXPECT_EQ(VTableForOtherBase->getFunction(0)->getName(), + "_ZN9OtherBase3bazEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + ASSERT_NE(nullptr, VTableForChild->getFunction(3)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); + EXPECT_EQ(VTableForChild->getFunction(3)->getName(), "_ZN5Child3tarEv"); +} + +TEST(DBTHTest, VTableConstruction_6) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3tarEv"); +} + +TEST(DBTHTest, VTableConstruction_7) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &BType = DBTH.getType("B"); + ASSERT_NE(nullptr, BType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &DType = DBTH.getType("D"); + ASSERT_NE(nullptr, DType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + + const auto &VTableForAType = DBTH.getVFTable(AType); + ASSERT_NE(nullptr, VTableForAType); + ASSERT_NE(nullptr, VTableForAType->getFunction(0)); + EXPECT_EQ(VTableForAType->getFunction(0)->getName(), "_ZN1A1fEv"); + const auto &VTableForBType = DBTH.getVFTable(BType); + ASSERT_NE(nullptr, VTableForBType); + EXPECT_EQ(VTableForBType->getFunction(0), nullptr); + const auto &VTableForCType = DBTH.getVFTable(CType); + ASSERT_NE(nullptr, VTableForCType); + EXPECT_EQ(VTableForCType->getFunction(0), nullptr); + const auto &VTableForDType = DBTH.getVFTable(DType); + ASSERT_NE(nullptr, VTableForDType); + EXPECT_EQ(VTableForDType->getFunction(0), nullptr); + const auto &VTableForXType = DBTH.getVFTable(XType); + ASSERT_NE(nullptr, VTableForXType); + ASSERT_NE(nullptr, VTableForXType->getFunction(0)); + EXPECT_EQ(VTableForXType->getFunction(0)->getName(), "_ZN1X1gEv"); + const auto &VTableForYType = DBTH.getVFTable(YType); + ASSERT_NE(nullptr, VTableForYType); + EXPECT_EQ(VTableForYType->getFunction(0), nullptr); + const auto &VTableForZType = DBTH.getVFTable(ZType); + ASSERT_NE(nullptr, VTableForZType); + EXPECT_EQ(VTableForZType->getFunction(0), nullptr); +} + +TEST(DBTHTest, VTableConstruction_7_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + const auto &OmegaType = DBTH.getType("Omega"); + ASSERT_NE(nullptr, OmegaType); + + const auto &VTableForAType = DBTH.getVFTable(AType); + ASSERT_NE(nullptr, VTableForAType); + ASSERT_NE(nullptr, VTableForAType->getFunction(0)); + EXPECT_EQ(VTableForAType->getFunction(0)->getName(), "_ZN1A1fEv"); + const auto &VTableForCType = DBTH.getVFTable(CType); + ASSERT_NE(nullptr, VTableForCType); + EXPECT_EQ(VTableForCType->getFunction(0), nullptr); + const auto &VTableForXType = DBTH.getVFTable(XType); + ASSERT_NE(nullptr, VTableForXType); + ASSERT_NE(nullptr, VTableForXType->getFunction(0)); + EXPECT_EQ(VTableForXType->getFunction(0)->getName(), "_ZN1X1gEv"); + const auto &VTableForYType = DBTH.getVFTable(YType); + ASSERT_NE(nullptr, VTableForYType); + EXPECT_EQ(VTableForYType->getFunction(0), nullptr); + const auto &VTableForZType = DBTH.getVFTable(ZType); + ASSERT_NE(nullptr, VTableForZType); + EXPECT_EQ(VTableForZType->getFunction(0), nullptr); + const auto &VTableForOmegaType = DBTH.getVFTable(OmegaType); + ASSERT_NE(nullptr, VTableForOmegaType); + ASSERT_NE(nullptr, VTableForOmegaType->getFunction(0)); + EXPECT_EQ(VTableForOmegaType->getFunction(0)->getName(), "_ZN5Omega1fEv"); +} + +TEST(DBTHTest, VTableConstruction_8) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + EXPECT_NE(nullptr, NonvirtualClassType); + const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + EXPECT_NE(nullptr, NonvirtualStructType); + + const auto &VTableForBaseType = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBaseType); + ASSERT_NE(nullptr, VTableForBaseType->getFunction(0)); + ASSERT_NE(nullptr, VTableForBaseType->getFunction(1)); + EXPECT_EQ(VTableForBaseType->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBaseType->getFunction(1)->getName(), "_ZN4Base3barEv"); + const auto &VTableForChildType = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChildType); + ASSERT_NE(nullptr, VTableForChildType->getFunction(0)); + EXPECT_EQ(VTableForChildType->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForChildType->getFunction(2)); + EXPECT_EQ(VTableForChildType->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChildType->getFunction(2)->getName(), "_ZN5Child3bazEv"); + + const auto &VTableForNonvirtualClassType = + DBTH.getVFTable(NonvirtualClassType); + ASSERT_NE(nullptr, VTableForNonvirtualClassType); + EXPECT_EQ(VTableForNonvirtualClassType->getFunction(0), nullptr); + const auto &VTableForNonvirtualStructType = + DBTH.getVFTable(NonvirtualStructType); + ASSERT_NE(nullptr, VTableForNonvirtualStructType); + EXPECT_EQ(VTableForNonvirtualStructType->getFunction(0), nullptr); +} + +TEST(DBTHTest, VTableConstruction_9) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); +} + +TEST(DBTHTest, VTableConstruction_10) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); +} + +TEST(DBTHTest, VTableConstruction_11) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_12) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_12_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + EXPECT_EQ(VTableForChild->getFunction(0), nullptr); + + const auto &VTableForChildsChild = DBTH.getVFTable(ChildsChildType); + ASSERT_NE(nullptr, VTableForChildsChild); + ASSERT_NE(nullptr, VTableForChildsChild->getFunction(0)); + EXPECT_EQ(VTableForChildsChild->getFunction(0)->getName(), + "_ZN11ChildsChild3fooEv"); +} + +TEST(DBTHTest, VTableConstruction_12_c) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + + const auto &VTableForChildsChild = DBTH.getVFTable(ChildsChildType); + ASSERT_NE(nullptr, VTableForChildsChild); + EXPECT_EQ(VTableForChildsChild->getFunction(0), nullptr); +} + +/* +TEST(DBTHTest, VTableConstruction_13) { + Test file 13 has no types +} +*/ + +TEST(DBTHTest, VTableConstruction_14) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base4testEv"); +} + +TEST(DBTHTest, VTableConstruction_15) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base4testEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + EXPECT_EQ(VTableForChild->getFunction(0), nullptr); +} + +TEST(DBTHTest, VTableConstruction_16) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildOfChildType = DBTH.getType("ChildOfChild"); + ASSERT_NE(nullptr, ChildOfChildType); + const auto &BaseTwoType = DBTH.getType("BaseTwo"); + ASSERT_NE(nullptr, BaseTwoType); + const auto &ChildTwoType = DBTH.getType("ChildTwo"); + ASSERT_NE(nullptr, ChildTwoType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + + const auto &VTableForChildOfChild = DBTH.getVFTable(ChildOfChildType); + ASSERT_NE(nullptr, VTableForChildOfChild); + EXPECT_EQ(VTableForChildOfChild->getFunction(0), nullptr); + + const auto &VTableForBaseTwo = DBTH.getVFTable(BaseTwoType); + ASSERT_NE(nullptr, VTableForBaseTwo); + ASSERT_NE(nullptr, VTableForBaseTwo->getFunction(0)); + EXPECT_EQ(VTableForBaseTwo->getFunction(0)->getName(), + "_ZN7BaseTwo6foobarEv"); + + const auto &VTableForChildTwo = DBTH.getVFTable(ChildTwoType); + ASSERT_NE(nullptr, VTableForChildTwo); + ASSERT_NE(nullptr, VTableForChildTwo->getFunction(0)); + EXPECT_EQ(VTableForChildTwo->getFunction(0)->getName(), + "_ZN8ChildTwo6foobarEv"); +} + +TEST(DBTHTest, VTableConstruction_17) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // Since Child2 is never used, it is sometimes optimized out by the compiler + // const auto &Child2Type = DBTH.getType("Child2"); + // ASSERT_NE(nullptr, Child2Type); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &KidType = DBTH.getType("Kid"); + ASSERT_NE(nullptr, KidType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); + + const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); + ASSERT_NE(nullptr, VTableForBase2); + EXPECT_EQ(VTableForBase2->getFunction(0), nullptr); + ASSERT_NE(nullptr, VTableForBase2->getFunction(1)); + EXPECT_EQ(VTableForBase2->getFunction(2), nullptr); + ASSERT_NE(nullptr, VTableForBase2->getFunction(3)); + EXPECT_EQ(VTableForBase2->getFunction(1)->getName(), "_ZN5Base23barEv"); + EXPECT_EQ(VTableForBase2->getFunction(3)->getName(), "_ZN5Base26foobarEv"); + + const auto &VTableForKid = DBTH.getVFTable(KidType); + ASSERT_NE(nullptr, VTableForKid); + ASSERT_NE(nullptr, VTableForKid->getFunction(0)); + EXPECT_EQ(VTableForKid->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForKid->getFunction(2)); + EXPECT_EQ(VTableForKid->getFunction(3), nullptr); + ASSERT_NE(nullptr, VTableForKid->getFunction(4)); + EXPECT_EQ(VTableForKid->getFunction(0)->getName(), "_ZN3Kid3fooEv"); + EXPECT_EQ(VTableForKid->getFunction(2)->getName(), "_ZN3Kid6barfooEv"); + EXPECT_EQ(VTableForKid->getFunction(4)->getName(), "_ZN3Kid3bauEv"); +} + +TEST(DBTHTest, VTableConstruction_18) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &Child2Type = DBTH.getType("Child_2"); + ASSERT_NE(nullptr, Child2Type); + const auto &Child3Type = DBTH.getType("Child_3"); + ASSERT_NE(nullptr, Child3Type); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + + const auto &VTableForChild2 = DBTH.getVFTable(Child2Type); + ASSERT_NE(nullptr, VTableForChild2); + EXPECT_EQ(VTableForChild2->getFunction(0), nullptr); + EXPECT_EQ(VTableForChild2->getFunction(1), nullptr); + // Test + // ASSERT_NE(nullptr, VTableForBase->getFunction(2)); + EXPECT_EQ(VTableForChild2->getFunction(2)->getName(), "_ZN7Child_26foobarEv"); + + const auto &VTableForChild3 = DBTH.getVFTable(Child3Type); + ASSERT_NE(nullptr, VTableForChild3); + EXPECT_EQ(VTableForChild3->getFunction(0), nullptr); + EXPECT_EQ(VTableForChild3->getFunction(1), nullptr); + EXPECT_EQ(VTableForChild3->getFunction(2), nullptr); + ASSERT_NE(nullptr, VTableForChild3->getFunction(3)); + EXPECT_EQ(VTableForChild3->getFunction(3)->getName(), "_ZN7Child_36barfooEv"); +} + +TEST(DBTHTest, VTableConstruction_19) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &FooType = DBTH.getType("Foo"); + ASSERT_NE(nullptr, FooType); + const auto &BarType = DBTH.getType("Bar"); + ASSERT_NE(nullptr, BarType); + const auto &LoremType = DBTH.getType("Lorem"); + ASSERT_NE(nullptr, LoremType); + const auto &ImpsumType = DBTH.getType("Impsum"); + ASSERT_NE(nullptr, ImpsumType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + ASSERT_NE(nullptr, VTableForBase->getFunction(0)); + EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base10publicbaseEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), + "_ZN5Child10publicbaseEv"); + + const auto &VTableForBar = DBTH.getVFTable(BarType); + ASSERT_NE(nullptr, VTableForBar); + ASSERT_NE(nullptr, VTableForBar->getFunction(0)); + EXPECT_EQ(VTableForBar->getFunction(0)->getName(), "_ZN3Bar12protectedfooEv"); + + const auto &VTableForFoo = DBTH.getVFTable(FooType); + ASSERT_NE(nullptr, VTableForFoo); + ASSERT_NE(nullptr, VTableForFoo->getFunction(0)); + EXPECT_EQ(VTableForFoo->getFunction(0)->getName(), "_ZN3Foo12protectedfooEv"); + + const auto &VTableForLorem = DBTH.getVFTable(LoremType); + ASSERT_NE(nullptr, VTableForLorem); + ASSERT_NE(nullptr, VTableForLorem->getFunction(0)); + EXPECT_EQ(VTableForLorem->getFunction(0)->getName(), + "_ZN5Lorem12privateloremEv"); + + const auto &VTableForImpsum = DBTH.getVFTable(ImpsumType); + ASSERT_NE(nullptr, VTableForImpsum); + ASSERT_NE(nullptr, VTableForImpsum->getFunction(0)); + EXPECT_EQ(VTableForImpsum->getFunction(0)->getName(), + "_ZN6Impsum12privateloremEv"); +} + +TEST(DBTHTest, VTableConstruction_20) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + ASSERT_NE(nullptr, VTableForBase->getFunction(1)); + EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + ASSERT_NE(nullptr, VTableForChild->getFunction(0)); + EXPECT_EQ(VTableForChild->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child4bar2Ev"); + + const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); + ASSERT_NE(nullptr, VTableForBase2); + ASSERT_NE(nullptr, VTableForBase2->getFunction(0)); + EXPECT_EQ(VTableForBase2->getFunction(0)->getName(), "_ZN5Base24foo2Ev"); +} + +TEST(DBTHTest, VTableConstruction_21) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &Base3Type = DBTH.getType("Base3"); + ASSERT_NE(nullptr, Base3Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &Child2Type = DBTH.getType("Child2"); + ASSERT_NE(nullptr, Child2Type); + + const auto &VTableForBase = DBTH.getVFTable(BaseType); + ASSERT_NE(nullptr, VTableForBase); + EXPECT_EQ(VTableForBase->getFunction(0), nullptr); + EXPECT_EQ(VTableForBase->getFunction(1), nullptr); + EXPECT_EQ(VTableForBase->getFunction(2), nullptr); + // Test + // ASSERT_NE(nullptr, VTableForBase->getFunction(3)); + EXPECT_EQ(VTableForBase->getFunction(3)->getName(), "_ZN4Base3barEv"); + + const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); + ASSERT_NE(nullptr, VTableForBase2); + EXPECT_EQ(VTableForBase2->getFunction(0), nullptr); + EXPECT_EQ(VTableForBase2->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForBase2->getFunction(2)); + EXPECT_EQ(VTableForBase2->getFunction(2)->getName(), "_ZN5Base24foo2Ev"); + + const auto &VTableForBase3 = DBTH.getVFTable(Base3Type); + ASSERT_NE(nullptr, VTableForBase3); + EXPECT_EQ(nullptr, VTableForBase->getFunction(0)); + + const auto &VTableForChild = DBTH.getVFTable(ChildType); + ASSERT_NE(nullptr, VTableForChild); + EXPECT_EQ(VTableForChild->getFunction(0), nullptr); + EXPECT_EQ(VTableForChild->getFunction(1), nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(2)); + EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3fooEv"); + EXPECT_EQ(VTableForChild->getFunction(3), nullptr); + ASSERT_NE(nullptr, VTableForChild->getFunction(4)); + EXPECT_EQ(VTableForChild->getFunction(4)->getName(), "_ZN5Child4bar2Ev"); + + const auto &VTableForChild2 = DBTH.getVFTable(Child2Type); + ASSERT_NE(nullptr, VTableForChild2); + EXPECT_EQ(VTableForChild2->getFunction(0), nullptr); + EXPECT_EQ(VTableForChild2->getFunction(1), nullptr); + EXPECT_EQ(VTableForChild2->getFunction(2), nullptr); + EXPECT_EQ(VTableForChild2->getFunction(3), nullptr); + EXPECT_EQ(VTableForChild2->getFunction(4), nullptr); + ASSERT_NE(nullptr, VTableForChild2->getFunction(5)); + EXPECT_EQ(VTableForChild2->getFunction(5)->getName(), "_ZN6Child26foobarEv"); +} + +/* +-------------------------------- +TransitivelyReachableTypes Tests +-------------------------------- +*/ + +TEST(DBTHTest, TransitivelyReachableTypes_1) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_2) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_3) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_4) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_5) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &OtherBaseType = DBTH.getType("OtherBase"); + ASSERT_NE(nullptr, OtherBaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesOtherBase = DBTH.getSubTypes(OtherBaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesOtherBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_TRUE(ReachableTypesOtherBase.count(OtherBaseType)); + EXPECT_TRUE(ReachableTypesOtherBase.count(ChildType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_FALSE(ReachableTypesChild.count(OtherBaseType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_6) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_7) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &BType = DBTH.getType("B"); + ASSERT_NE(nullptr, BType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &DType = DBTH.getType("D"); + ASSERT_NE(nullptr, DType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + + auto ReachableTypesA = DBTH.getSubTypes(AType); + auto ReachableTypesB = DBTH.getSubTypes(BType); + auto ReachableTypesC = DBTH.getSubTypes(CType); + auto ReachableTypesD = DBTH.getSubTypes(DType); + auto ReachableTypesX = DBTH.getSubTypes(XType); + auto ReachableTypesY = DBTH.getSubTypes(YType); + auto ReachableTypesZ = DBTH.getSubTypes(ZType); + + EXPECT_EQ(ReachableTypesA.size(), 5U); + EXPECT_EQ(ReachableTypesB.size(), 2U); + EXPECT_EQ(ReachableTypesC.size(), 2U); + EXPECT_EQ(ReachableTypesD.size(), 1U); + EXPECT_EQ(ReachableTypesX.size(), 3U); + EXPECT_EQ(ReachableTypesY.size(), 2U); + EXPECT_EQ(ReachableTypesZ.size(), 1U); + + EXPECT_TRUE(ReachableTypesA.count(AType)); + EXPECT_TRUE(ReachableTypesA.count(BType)); + EXPECT_TRUE(ReachableTypesA.count(CType)); + EXPECT_TRUE(ReachableTypesA.count(DType)); + EXPECT_FALSE(ReachableTypesA.count(XType)); + EXPECT_FALSE(ReachableTypesA.count(YType)); + EXPECT_TRUE(ReachableTypesA.count(ZType)); + + EXPECT_FALSE(ReachableTypesB.count(AType)); + EXPECT_TRUE(ReachableTypesB.count(BType)); + EXPECT_FALSE(ReachableTypesB.count(CType)); + EXPECT_TRUE(ReachableTypesB.count(DType)); + EXPECT_FALSE(ReachableTypesB.count(XType)); + EXPECT_FALSE(ReachableTypesB.count(YType)); + EXPECT_FALSE(ReachableTypesB.count(ZType)); + + EXPECT_FALSE(ReachableTypesC.count(AType)); + EXPECT_FALSE(ReachableTypesC.count(BType)); + EXPECT_TRUE(ReachableTypesC.count(CType)); + EXPECT_FALSE(ReachableTypesC.count(DType)); + EXPECT_FALSE(ReachableTypesC.count(XType)); + EXPECT_FALSE(ReachableTypesC.count(YType)); + EXPECT_TRUE(ReachableTypesC.count(ZType)); + + EXPECT_FALSE(ReachableTypesD.count(AType)); + EXPECT_FALSE(ReachableTypesD.count(BType)); + EXPECT_FALSE(ReachableTypesD.count(CType)); + EXPECT_TRUE(ReachableTypesD.count(DType)); + EXPECT_FALSE(ReachableTypesD.count(XType)); + EXPECT_FALSE(ReachableTypesD.count(YType)); + EXPECT_FALSE(ReachableTypesD.count(ZType)); + + EXPECT_FALSE(ReachableTypesX.count(AType)); + EXPECT_FALSE(ReachableTypesX.count(BType)); + EXPECT_FALSE(ReachableTypesX.count(CType)); + EXPECT_FALSE(ReachableTypesX.count(DType)); + EXPECT_TRUE(ReachableTypesX.count(XType)); + EXPECT_TRUE(ReachableTypesX.count(YType)); + EXPECT_TRUE(ReachableTypesX.count(ZType)); + + EXPECT_FALSE(ReachableTypesY.count(AType)); + EXPECT_FALSE(ReachableTypesY.count(BType)); + EXPECT_FALSE(ReachableTypesY.count(CType)); + EXPECT_FALSE(ReachableTypesY.count(DType)); + EXPECT_FALSE(ReachableTypesY.count(XType)); + EXPECT_TRUE(ReachableTypesY.count(YType)); + EXPECT_TRUE(ReachableTypesY.count(ZType)); + + EXPECT_FALSE(ReachableTypesZ.count(AType)); + EXPECT_FALSE(ReachableTypesZ.count(BType)); + EXPECT_FALSE(ReachableTypesZ.count(CType)); + EXPECT_FALSE(ReachableTypesZ.count(DType)); + EXPECT_FALSE(ReachableTypesZ.count(XType)); + EXPECT_FALSE(ReachableTypesZ.count(YType)); + EXPECT_TRUE(ReachableTypesZ.count(ZType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_7_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &AType = DBTH.getType("A"); + ASSERT_NE(nullptr, AType); + const auto &CType = DBTH.getType("C"); + ASSERT_NE(nullptr, CType); + const auto &XType = DBTH.getType("X"); + ASSERT_NE(nullptr, XType); + const auto &YType = DBTH.getType("Y"); + ASSERT_NE(nullptr, YType); + const auto &ZType = DBTH.getType("Z"); + ASSERT_NE(nullptr, ZType); + const auto &OmegaType = DBTH.getType("Omega"); + ASSERT_NE(nullptr, OmegaType); + + auto ReachableTypesA = DBTH.getSubTypes(AType); + auto ReachableTypesC = DBTH.getSubTypes(CType); + auto ReachableTypesX = DBTH.getSubTypes(XType); + auto ReachableTypesY = DBTH.getSubTypes(YType); + auto ReachableTypesZ = DBTH.getSubTypes(ZType); + auto ReachableTypesOmega = DBTH.getSubTypes(OmegaType); + + EXPECT_EQ(ReachableTypesA.size(), 4U); + EXPECT_EQ(ReachableTypesC.size(), 3U); + EXPECT_EQ(ReachableTypesX.size(), 4U); + EXPECT_EQ(ReachableTypesY.size(), 3U); + EXPECT_EQ(ReachableTypesZ.size(), 2U); + EXPECT_EQ(ReachableTypesOmega.size(), 1U); + + EXPECT_TRUE(ReachableTypesA.count(AType)); + EXPECT_TRUE(ReachableTypesA.count(CType)); + EXPECT_FALSE(ReachableTypesA.count(XType)); + EXPECT_FALSE(ReachableTypesA.count(YType)); + EXPECT_TRUE(ReachableTypesA.count(ZType)); + EXPECT_TRUE(ReachableTypesA.count(OmegaType)); + + EXPECT_FALSE(ReachableTypesC.count(AType)); + EXPECT_TRUE(ReachableTypesC.count(CType)); + EXPECT_FALSE(ReachableTypesC.count(XType)); + EXPECT_FALSE(ReachableTypesC.count(YType)); + EXPECT_TRUE(ReachableTypesC.count(ZType)); + EXPECT_TRUE(ReachableTypesC.count(OmegaType)); + + EXPECT_FALSE(ReachableTypesX.count(AType)); + EXPECT_FALSE(ReachableTypesX.count(CType)); + EXPECT_TRUE(ReachableTypesX.count(XType)); + EXPECT_TRUE(ReachableTypesX.count(YType)); + EXPECT_TRUE(ReachableTypesX.count(ZType)); + EXPECT_TRUE(ReachableTypesX.count(OmegaType)); + + EXPECT_FALSE(ReachableTypesY.count(AType)); + EXPECT_FALSE(ReachableTypesY.count(CType)); + EXPECT_FALSE(ReachableTypesY.count(XType)); + EXPECT_TRUE(ReachableTypesY.count(YType)); + EXPECT_TRUE(ReachableTypesY.count(ZType)); + EXPECT_TRUE(ReachableTypesY.count(OmegaType)); + + EXPECT_FALSE(ReachableTypesZ.count(AType)); + EXPECT_FALSE(ReachableTypesZ.count(CType)); + EXPECT_FALSE(ReachableTypesZ.count(XType)); + EXPECT_FALSE(ReachableTypesZ.count(YType)); + EXPECT_TRUE(ReachableTypesZ.count(ZType)); + EXPECT_TRUE(ReachableTypesZ.count(OmegaType)); + + EXPECT_FALSE(ReachableTypesOmega.count(AType)); + EXPECT_FALSE(ReachableTypesOmega.count(CType)); + EXPECT_FALSE(ReachableTypesOmega.count(XType)); + EXPECT_FALSE(ReachableTypesOmega.count(YType)); + EXPECT_FALSE(ReachableTypesOmega.count(ZType)); + EXPECT_TRUE(ReachableTypesOmega.count(OmegaType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_8) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + ASSERT_NE(nullptr, NonvirtualClassType); + const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + ASSERT_NE(nullptr, NonvirtualStructType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesNonvirtualClass = DBTH.getSubTypes(NonvirtualClassType); + auto ReachableTypesNonvirtualStruct = DBTH.getSubTypes(NonvirtualStructType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_EQ(ReachableTypesNonvirtualClass.size(), 1U); + EXPECT_EQ(ReachableTypesNonvirtualStruct.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesBase.count(NonvirtualClassType)); + EXPECT_FALSE(ReachableTypesBase.count(NonvirtualStructType)); + + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(NonvirtualClassType)); + EXPECT_FALSE(ReachableTypesChild.count(NonvirtualStructType)); + + EXPECT_FALSE(ReachableTypesNonvirtualClass.count(BaseType)); + EXPECT_FALSE(ReachableTypesNonvirtualClass.count(ChildType)); + EXPECT_TRUE(ReachableTypesNonvirtualClass.count(NonvirtualClassType)); + EXPECT_FALSE(ReachableTypesNonvirtualClass.count(NonvirtualStructType)); + + EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(BaseType)); + EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(ChildType)); + EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(NonvirtualClassType)); + EXPECT_TRUE(ReachableTypesNonvirtualStruct.count(NonvirtualStructType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_9) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_10) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_11) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_12) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_12_b) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 3U); + EXPECT_EQ(ReachableTypesChild.size(), 2U); + EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildsChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); + EXPECT_FALSE(ReachableTypesChildsChild.count(BaseType)); + EXPECT_FALSE(ReachableTypesChildsChild.count(ChildType)); + EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_12_c) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &ChildsChildType = DBTH.getType("ChildsChild"); + ASSERT_NE(nullptr, ChildsChildType); + + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); + + EXPECT_EQ(ReachableTypesChild.size(), 2U); + EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); + EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); +} + +/* +TEST(DBTHTest, BasicTHReconstruction_13) { + Test file 13 has no types +} +*/ + +TEST(DBTHTest, TransitivelyReachableTypes_14) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + + EXPECT_EQ(ReachableTypesBase.size(), 1U); + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_15) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_FALSE(ReachableTypesChild.count(BaseType)); + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_16) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // const auto &ChildsChildType = DBTH.getType("ChildsChild"); + // Since ChildsChild is never used, it is optimized out + // ASSERT_EQ(nullptr, ChildsChildType); + const auto &BaseTwoType = DBTH.getType("BaseTwo"); + ASSERT_NE(nullptr, BaseTwoType); + const auto &ChildTwoType = DBTH.getType("ChildTwo"); + ASSERT_NE(nullptr, ChildTwoType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + // Since ChildsChild is never used, it is optimized out + // auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); + auto ReachableTypesBaseTwo = DBTH.getSubTypes(BaseTwoType); + auto ReachableTypesChildTwo = DBTH.getSubTypes(ChildTwoType); + + EXPECT_EQ(ReachableTypesBase.size(), 3U); + EXPECT_EQ(ReachableTypesChild.size(), 2U); + // EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); + EXPECT_EQ(ReachableTypesBaseTwo.size(), 2U); + EXPECT_EQ(ReachableTypesChildTwo.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + // EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); + + // EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); + + EXPECT_TRUE(ReachableTypesBaseTwo.count(BaseTwoType)); + EXPECT_TRUE(ReachableTypesBaseTwo.count(ChildTwoType)); + + EXPECT_TRUE(ReachableTypesChildTwo.count(ChildTwoType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_17) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + // const auto &Child2Type = DBTH.getType("Child2"); + // Since Child2 is never used, it is optimized out + // ASSERT_EQ(nullptr, Child2Type); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &KidType = DBTH.getType("Kid"); + ASSERT_NE(nullptr, KidType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + // Since Child2 is never used, it is optimized out + // auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); + auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); + auto ReachableTypesKid = DBTH.getSubTypes(KidType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + // EXPECT_EQ(ReachableTypesChild2.size(), 1U); + EXPECT_EQ(ReachableTypesBase2.size(), 2U); + EXPECT_EQ(ReachableTypesKid.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + // EXPECT_TRUE(ReachableTypesChild.count(Child2Type)); + + // EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); + + EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); + // EXPECT_TRUE(ReachableTypesBase2.count(Child2Type)); + + EXPECT_TRUE(ReachableTypesKid.count(KidType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_18) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &Child2Type = DBTH.getType("Child_2"); + ASSERT_NE(nullptr, Child2Type); + const auto &Child3Type = DBTH.getType("Child_3"); + ASSERT_NE(nullptr, Child3Type); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); + auto ReachableTypesChild3 = DBTH.getSubTypes(Child3Type); + + EXPECT_EQ(ReachableTypesBase.size(), 4U); + EXPECT_EQ(ReachableTypesChild.size(), 3U); + EXPECT_EQ(ReachableTypesChild2.size(), 2U); + EXPECT_EQ(ReachableTypesChild3.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + EXPECT_TRUE(ReachableTypesBase.count(Child2Type)); + EXPECT_TRUE(ReachableTypesBase.count(Child3Type)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + EXPECT_TRUE(ReachableTypesChild.count(Child2Type)); + EXPECT_TRUE(ReachableTypesChild.count(Child3Type)); + + EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); + EXPECT_TRUE(ReachableTypesChild3.count(Child3Type)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_19) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &FooType = DBTH.getType("Foo"); + ASSERT_NE(nullptr, FooType); + const auto &BarType = DBTH.getType("Bar"); + ASSERT_NE(nullptr, BarType); + const auto &LoremType = DBTH.getType("Lorem"); + ASSERT_NE(nullptr, LoremType); + const auto &ImpsumType = DBTH.getType("Impsum"); + ASSERT_NE(nullptr, ImpsumType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesFoo = DBTH.getSubTypes(FooType); + auto ReachableTypesBar = DBTH.getSubTypes(BarType); + auto ReachableTypesLorem = DBTH.getSubTypes(LoremType); + auto ReachableTypesImpsum = DBTH.getSubTypes(ImpsumType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + EXPECT_EQ(ReachableTypesFoo.size(), 2U); + EXPECT_EQ(ReachableTypesBar.size(), 1U); + EXPECT_EQ(ReachableTypesLorem.size(), 2U); + EXPECT_EQ(ReachableTypesImpsum.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + + EXPECT_TRUE(ReachableTypesFoo.count(FooType)); + EXPECT_TRUE(ReachableTypesFoo.count(BarType)); + + EXPECT_TRUE(ReachableTypesBar.count(BarType)); + + EXPECT_TRUE(ReachableTypesLorem.count(LoremType)); + EXPECT_TRUE(ReachableTypesLorem.count(ImpsumType)); + + EXPECT_TRUE(ReachableTypesImpsum.count(ImpsumType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_20) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + + EXPECT_EQ(ReachableTypesBase.size(), 2U); + EXPECT_EQ(ReachableTypesBase2.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + + EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); + EXPECT_TRUE(ReachableTypesBase2.count(ChildType)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); +} + +TEST(DBTHTest, TransitivelyReachableTypes_21) { + LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + + "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); + DIBasedTypeHierarchy DBTH(IRDB); + + // check for all types + const auto &BaseType = DBTH.getType("Base"); + ASSERT_NE(nullptr, BaseType); + const auto &Base2Type = DBTH.getType("Base2"); + ASSERT_NE(nullptr, Base2Type); + const auto &Base3Type = DBTH.getType("Base3"); + ASSERT_NE(nullptr, Base3Type); + const auto &ChildType = DBTH.getType("Child"); + ASSERT_NE(nullptr, ChildType); + const auto &Child2Type = DBTH.getType("Child2"); + ASSERT_NE(nullptr, Child2Type); + + auto ReachableTypesBase = DBTH.getSubTypes(BaseType); + auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); + auto ReachableTypesBase3 = DBTH.getSubTypes(Base3Type); + auto ReachableTypesChild = DBTH.getSubTypes(ChildType); + auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); + + EXPECT_EQ(ReachableTypesBase.size(), 3U); + EXPECT_EQ(ReachableTypesBase2.size(), 3U); + EXPECT_EQ(ReachableTypesBase3.size(), 2U); + EXPECT_EQ(ReachableTypesChild.size(), 2U); + EXPECT_EQ(ReachableTypesChild2.size(), 1U); + + EXPECT_TRUE(ReachableTypesBase.count(BaseType)); + EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + + EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); + EXPECT_TRUE(ReachableTypesBase2.count(ChildType)); + + EXPECT_TRUE(ReachableTypesBase3.count(Base3Type)); + EXPECT_TRUE(ReachableTypesBase3.count(Child2Type)); + + EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + + EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); +} + +} // namespace psr + +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + auto Res = RUN_ALL_TESTS(); + return Res; +} From 1d9ea9bb815fcc5f116e627175b161e9c55f0a37 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 27 Mar 2024 20:42:23 +0100 Subject: [PATCH 11/42] DIBTH serialization code, untested --- include/phasar/ControlFlow/CallGraph.h | 9 +- include/phasar/ControlFlow/CallGraphData.h | 7 +- .../TypeHierarchy/DIBasedTypeHierarchy.h | 3 +- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 19 +- include/phasar/Pointer/AliasInfo.h | 7 +- lib/ControlFlow/CallGraphData.cpp | 22 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 89 +- .../DIBasedTypeHierarchyData.cpp | 18 +- .../DIBasedTypeHierarchySerializationTest.cpp | 2233 +---------------- 9 files changed, 153 insertions(+), 2254 deletions(-) diff --git a/include/phasar/ControlFlow/CallGraph.h b/include/phasar/ControlFlow/CallGraph.h index 043d6956d..6ae072a53 100644 --- a/include/phasar/ControlFlow/CallGraph.h +++ b/include/phasar/ControlFlow/CallGraph.h @@ -14,7 +14,6 @@ #include "phasar/ControlFlow/CallGraphData.h" #include "phasar/Utils/ByRef.h" #include "phasar/Utils/Logger.h" -#include "phasar/Utils/Printer.h" #include "phasar/Utils/StableVector.h" #include "phasar/Utils/Utilities.h" @@ -99,12 +98,10 @@ class CallGraph : public CallGraphBase> { CGData.FToFunctionVertexTy.reserve(CallersOf.size()); for (const auto &[Fun, Callers] : CallersOf) { - auto &JCallers = CGData.FToFunctionVertexTy[std::invoke(GetFunctionId, Fun)]; - + auto &JCallers = + CGData.FToFunctionVertexTy[std::invoke(GetFunctionId, Fun)]; + CGData.FToFunctionVertexTy.reserve(Callers->size()); - // set null value to represent a function with no callers - // example: __psrCRuntimeGlobalCtorsModel - //JCallers.push_back(0); for (const auto &CS : *Callers) { JCallers.push_back(std::invoke(GetInstructionId, CS)); } diff --git a/include/phasar/ControlFlow/CallGraphData.h b/include/phasar/ControlFlow/CallGraphData.h index 43e9c98c8..4321d7cea 100644 --- a/include/phasar/ControlFlow/CallGraphData.h +++ b/include/phasar/ControlFlow/CallGraphData.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H #define PHASAR_PHASARLLVM_CONTROLFLOW_CALLGRAPHDATA_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" #include @@ -18,11 +19,13 @@ namespace psr { struct CallGraphData { - CallGraphData() noexcept = default; std::unordered_map> FToFunctionVertexTy{}; + + CallGraphData() noexcept = default; void printAsJson(llvm::raw_ostream &OS); + static CallGraphData deserializeJson(const llvm::Twine &Path); - static CallGraphData loadJsonString(const std::string &JsonAsString); + static CallGraphData loadJsonString(llvm::StringRef JsonAsString); }; } // namespace psr diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index 09d438b46..fa8cfd12c 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -104,9 +104,8 @@ class DIBasedTypeHierarchy */ void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const override; - [[nodiscard]] DIBasedTypeHierarchyData stringifyTypeHierarchy() const; - private: + [[nodiscard]] DIBasedTypeHierarchyData getTypeHierarchyData() const; [[nodiscard]] llvm::iterator_range subTypesOf(size_t TypeIdx) const noexcept; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index 4361a4dc1..061086c9b 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -18,25 +18,18 @@ namespace psr { struct DIBasedTypeHierarchyData { - DIBasedTypeHierarchyData() noexcept = default; - - // StringMap of ClassType as string - llvm::StringMap NameToType; - // DenseMap of ClassType as string and according size_t + llvm::StringMap NameToType; llvm::DenseMap TypeToVertex; - // Vector of llvm::DICompositeType as string - std::vector VertexTypes; - // Vector of pairs of uint32_ts + std::vector VertexTypes; std::vector> TransitiveDerivedIndex; - // Vector of ClassType as string std::vector Hierarchy; - // Deque of LLVMVFTable (std::vector) as string - std::deque> VTables; + std::deque> VTables; + DIBasedTypeHierarchyData() noexcept = default; void printAsJson(llvm::raw_ostream &OS); + static DIBasedTypeHierarchyData deserializeJson(const llvm::Twine &Path); - static DIBasedTypeHierarchyData - loadJsonString(const std::string &JsonAsString); + static DIBasedTypeHierarchyData loadJsonString(llvm::StringRef JsonAsString); }; } // namespace psr diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index 9f38a4f3c..1d3dc2990 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -241,10 +241,15 @@ 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(); }, [](const void *AA, llvm::raw_ostream &OS) { diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index 352da02e0..e7b59ba65 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -12,24 +12,18 @@ #include "phasar/Utils/IO.h" #include "phasar/Utils/NlohmannLogging.h" -#include - namespace psr { static CallGraphData getDataFromJson(const nlohmann::json &Json) { CallGraphData ToReturn; // map F to vector of n_t's - for (const auto &CurrentFVal : Json.get()) { - std::string FValueString = CurrentFVal.first; - std::vector FunctionVertexTyVals; - FunctionVertexTyVals.reserve(CurrentFVal.second.size()); + for (const auto &[FVal, FunctionVertexTyVals] : + Json.get()) { + ToReturn.FToFunctionVertexTy.reserve(FunctionVertexTyVals.size()); - for (const auto &CurrentFunctionVertexTy : CurrentFVal.second) { - FunctionVertexTyVals.push_back(CurrentFunctionVertexTy); + for (const auto &Curr : FunctionVertexTyVals) { + ToReturn.FToFunctionVertexTy[FVal].push_back(Curr); } - - ToReturn.FToFunctionVertexTy.try_emplace(FValueString, - FunctionVertexTyVals); } return ToReturn; @@ -53,9 +47,9 @@ CallGraphData CallGraphData::deserializeJson(const llvm::Twine &Path) { return getDataFromJson(readJsonFile(Path)); } -CallGraphData CallGraphData::loadJsonString(const std::string &JsonAsString) { - // nlohmann::json::parse needs a std::string, llvm::Twine won't work - nlohmann::json ToStringify = nlohmann::json::parse(JsonAsString); +CallGraphData CallGraphData::loadJsonString(llvm::StringRef JsonAsString) { + auto ToStringify = + nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); return getDataFromJson(ToStringify); } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 60e7ec0ed..b8515b13c 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -193,9 +193,88 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { buildTypeHierarchy(TG, VertexTypes, TransitiveDerivedIndex, Hierarchy); } +static llvm::SmallVector +findAllFunctionDefs(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { + llvm::SmallVector FnDefs; + llvm::DebugInfoFinder DIF; + const auto *Mod = IRDB.getModule(); + + DIF.processModule(*Mod); + for (const auto &SubProgram : DIF.subprograms()) { + if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && + (SubProgram->getName() == Name || + SubProgram->getLinkageName() == Name)) { + FnDefs.push_back(IRDB.getFunction(SubProgram->getLinkageName())); + } + } + DIF.reset(); + + if (FnDefs.empty()) { + const auto *F = IRDB.getFunction(Name); + if (F) { + FnDefs.push_back(F); + } + } else if (FnDefs.size() > 1) { + llvm::errs() << "The function name '" << Name + << "' is ambiguous. Possible candidates are:\n"; + for (const auto *F : FnDefs) { + llvm::errs() << "> " << F->getName() << "\n"; + } + llvm::errs() << "Please further specify the function's name, such that it " + "becomes unambiguous\n"; + } + + return FnDefs; +} + DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedCG) { - /// TODO: implement + for (const auto &Curr : SerializedCG.NameToType) { + NameToType.try_emplace(Curr.first(), Curr.second); + } + + llvm::DebugInfoFinder DIF; + const auto *Mod = IRDB->getModule(); + DIF.processModule(*Mod); + + for (const auto &Curr : SerializedCG.TypeToVertex) { + llvm::SmallVector FnDefs; + for (const auto &SubProgram : DIF.subprograms()) { + if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && + (SubProgram->getName() == Curr.getFirst() || + SubProgram->getLinkageName() == Curr.getFirst())) { + FnDefs.push_back(IRDB->getFunction(SubProgram->getLinkageName())); + } + } + + DIF.reset(); + FnDefs = findAllFunctionDefs(*IRDB, Curr.getFirst()); + + if (FnDefs.empty()) { + llvm::errs() << "WARNING: Cannot retrieve function " << Curr.getFirst() + << "\n"; + continue; + } + + const auto *Fun = FnDefs[0]; + TypeToVertex.try_emplace(Fun, Curr.getSecond()); + } + + for (const auto &Curr : SerializedCG.VertexTypes) { + VertexTypes.emplace_back(Curr); + } + + for (const auto &Curr : SerializedCG.TransitiveDerivedIndex) { + TransitiveDerivedIndex.emplace_back(Curr); + } + + for (const auto &Curr : SerializedCG.Hierarchy) { + Hierarchy.emplace_back(); + } + + for (const auto &Curr : SerializedCG.VTables) { + VTables.emplace_back(); + } } auto DIBasedTypeHierarchy::subTypesOf(size_t TypeIdx) const noexcept @@ -267,12 +346,12 @@ DIBasedTypeHierarchy::getAsJson() const { llvm::report_fatal_error("Not implemented"); } -DIBasedTypeHierarchyData DIBasedTypeHierarchy::stringifyTypeHierarchy() const { +DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; for (const auto &Curr : NameToType) { Data.NameToType.try_emplace(Curr.getKey(), - Curr.getValue()->getName().str()); + Curr.getValue()->getMetadataID()); } for (const auto &Curr : TypeToVertex) { @@ -281,7 +360,7 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::stringifyTypeHierarchy() const { } for (const auto &Curr : VertexTypes) { - Data.VertexTypes.push_back(Curr->getName().str()); + Data.VertexTypes.push_back(Curr->getMetadataID()); } for (const auto &Curr : TransitiveDerivedIndex) { @@ -308,7 +387,7 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::stringifyTypeHierarchy() const { } void DIBasedTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { - DIBasedTypeHierarchyData Data = stringifyTypeHierarchy(); + DIBasedTypeHierarchyData Data = getTypeHierarchyData(); Data.printAsJson(OS); } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index bd29a705d..19d060d7a 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -12,13 +12,15 @@ #include "phasar/Utils/IO.h" #include "phasar/Utils/NlohmannLogging.h" -#include +#include "llvm/ADT/StringRef.h" namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { DIBasedTypeHierarchyData ToReturn; + /// TODO: + return ToReturn; } @@ -46,14 +48,7 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { } for (const auto &CurrVTable : VTables) { - std::vector ToAdd; - ToAdd.reserve(CurrVTable.size()); - - for (const auto &Curr : CurrVTable) { - ToAdd.push_back(Curr); - } - - JSON["VTables"].push_back(ToAdd); + JSON["VTables"].push_back(CurrVTable); } OS << JSON; @@ -65,9 +60,10 @@ DIBasedTypeHierarchyData::deserializeJson(const llvm::Twine &Path) { } DIBasedTypeHierarchyData -DIBasedTypeHierarchyData::loadJsonString(const std::string &JsonAsString) { +DIBasedTypeHierarchyData::loadJsonString(llvm::StringRef JsonAsString) { // nlohmann::json::parse needs a std::string, llvm::Twine won't work - nlohmann::json ToStringify = nlohmann::json::parse(JsonAsString); + nlohmann::json ToStringify = + nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); return getDataFromJson(ToStringify); } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 55024d2bd..0c28e8a18 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -5,2216 +5,49 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Utilities.h" +#include "llvm/ADT/StringRef.h" + #include "TestConfig.h" #include "gtest/gtest.h" -namespace psr { - -void serAndDeser(const llvm::Twine &IRFile) { - // -} - -void compareResults(const psr::DIBasedTypeHierarchy &Orig, - const psr::DIBasedTypeHierarchy &Deser) { - // -} - -/* ---------------------------- -BasicTHReconstruction Tests ---------------------------- -*/ - -TEST(DBTHTest, BasicTHReconstruction_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - std::string Ser; - // stream ICF data into a json file using the printAsJson() function - llvm::raw_string_ostream StringStream(Ser); - - DBTH.printAsJson(StringStream); - - auto DebugTest = DBTH.getAsJson(); - - // deserialize data into CallGraphData object - psr::DIBasedTypeHierarchy DeserializedTypeHierarchy( - &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); - - compareResults(DBTH, DeserializedTypeHierarchy); -} - -TEST(DBTHTest, BasicTHReconstruction_2) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_3) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_4) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_5) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 3U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); - ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(OtherBaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypesBase = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypesBase.find(ChildType) != SubTypesBase.end()); - const auto &SubTypesOtherBase = DBTH.getSubTypes(OtherBaseType); - EXPECT_TRUE(SubTypesOtherBase.find(ChildType) != SubTypesOtherBase.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_6) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_7) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 7U); - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); - ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); - ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - - EXPECT_TRUE(DBTH.hasType(AType)); - EXPECT_TRUE(DBTH.hasType(BType)); - EXPECT_TRUE(DBTH.hasType(CType)); - EXPECT_TRUE(DBTH.hasType(DType)); - EXPECT_TRUE(DBTH.hasType(XType)); - EXPECT_TRUE(DBTH.hasType(YType)); - EXPECT_TRUE(DBTH.hasType(ZType)); - - // check for all subtypes - - // struct B : A {}; - // struct C : A {}; - const auto &SubTypesA = DBTH.getSubTypes(AType); - EXPECT_TRUE(SubTypesA.find(BType) != SubTypesA.end()); - EXPECT_TRUE(SubTypesA.find(CType) != SubTypesA.end()); - // struct D : B {}; - const auto &SubTypesB = DBTH.getSubTypes(BType); - EXPECT_TRUE(SubTypesB.find(DType) != SubTypesB.end()); - // struct Z : C, Y {}; - const auto &SubTypesC = DBTH.getSubTypes(CType); - EXPECT_TRUE(SubTypesC.find(ZType) != SubTypesC.end()); - // struct Y : X {}; - const auto &SubTypesX = DBTH.getSubTypes(XType); - EXPECT_TRUE(SubTypesX.find(YType) != SubTypesX.end()); - // struct Z : C, Y {}; - const auto &SubTypesY = DBTH.getSubTypes(YType); - EXPECT_TRUE(SubTypesY.find(ZType) != SubTypesY.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_7_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 6U); - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); - ASSERT_NE(nullptr, OmegaType); - - EXPECT_TRUE(DBTH.hasType(AType)); - EXPECT_TRUE(DBTH.hasType(CType)); - EXPECT_TRUE(DBTH.hasType(XType)); - EXPECT_TRUE(DBTH.hasType(YType)); - EXPECT_TRUE(DBTH.hasType(ZType)); - EXPECT_TRUE(DBTH.hasType(OmegaType)); - - // check for all subtypes - - // struct C : A {}; - const auto &SubTypesA = DBTH.getSubTypes(AType); - EXPECT_TRUE(SubTypesA.find(CType) != SubTypesA.end()); - // struct Z : C, Y {}; - const auto &SubTypesC = DBTH.getSubTypes(CType); - EXPECT_TRUE(SubTypesC.find(ZType) != SubTypesC.end()); - // struct Y : X {}; - const auto &SubTypesX = DBTH.getSubTypes(XType); - EXPECT_TRUE(SubTypesX.find(YType) != SubTypesX.end()); - // struct Z : C, Y {}; - const auto &SubTypesY = DBTH.getSubTypes(YType); - EXPECT_TRUE(SubTypesY.find(ZType) != SubTypesY.end()); - - // class Omega : Z { - const auto &SubTypesZ = DBTH.getSubTypes(ZType); - EXPECT_TRUE(SubTypesZ.find(OmegaType) != SubTypesZ.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_8) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 4U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); - EXPECT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); - EXPECT_NE(nullptr, NonvirtualStructType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - EXPECT_TRUE(DBTH.hasType(NonvirtualClassType)); - EXPECT_TRUE(DBTH.hasType(NonvirtualStructType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_9) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_10) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_11) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_12) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_12_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 3U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - EXPECT_TRUE(DBTH.hasType(ChildsChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - EXPECT_TRUE(SubTypesChild.find(ChildsChildType) != SubTypesChild.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_12_c) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - EXPECT_TRUE(DBTH.hasType(ChildType)); - EXPECT_TRUE(DBTH.hasType(ChildsChildType)); - - // check for all subtypes - const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - EXPECT_TRUE(SubTypesChild.find(ChildsChildType) != SubTypesChild.end()); -} - -/* -TEST(DBTHTest, BasicTHReconstruction_13) { - Test file 13 has no types -} -*/ - -TEST(DBTHTest, BasicTHReconstruction_14) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 1U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - - // there are no subtypes here -} - -TEST(DBTHTest, BasicTHReconstruction_15) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_16) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // Since ChildsChild is never used, it is optimized out - // const auto &ChildsChildType = DBTH.getType("ChildsChild"); - // ASSERT_EQ(nullptr, ChildsChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); - ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); - ASSERT_NE(nullptr, ChildTwoType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - // Since ChildsChild is never used, it is optimized out - // EXPECT_FALSE(DBTH.hasType(ChildsChildType)); - EXPECT_TRUE(DBTH.hasType(BaseTwoType)); - EXPECT_TRUE(DBTH.hasType(ChildTwoType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - // Since ChildsChild is never used, it is optimized out - // EXPECT_TRUE(SubTypesChild.find(ChildsChildType) == SubTypesChild.end()); - const auto &SubTypesTwo = DBTH.getSubTypes(BaseTwoType); - EXPECT_TRUE(SubTypesTwo.find(ChildTwoType) != SubTypesTwo.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_17) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - // EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // const auto &Child2Type = DBTH.getType("Child2"); - // Since Child2Type is never used, it is optimized out - // ASSERT_EQ(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); - ASSERT_NE(nullptr, KidType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - // Since ChildsChild is never used, it is optimized out - // EXPECT_FALSE(DBTH.hasType(Child2Type)); - EXPECT_TRUE(DBTH.hasType(Base2Type)); - EXPECT_TRUE(DBTH.hasType(KidType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - // Since ChildsChild is never used, it is optimized out - // EXPECT_TRUE(SubTypesChild.find(Child2Type) == SubTypesChild.end()); - const auto &SubTypesBase2 = DBTH.getSubTypes(Base2Type); - EXPECT_TRUE(SubTypesBase2.find(KidType) != SubTypesBase2.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_18) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 4U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // const auto &Child_2Type = DBTH.getType("Child_2"); - // Since Child2Type is never used, it is optimized out - // ASSERT_EQ(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); - ASSERT_NE(nullptr, Child3Type); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - // Since Child2 is never used, it is optimized out - // EXPECT_FALSE(DBTH.hasType(Child2Type)); - EXPECT_TRUE(DBTH.hasType(Child3Type)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - // const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - // Since Child2 is never used, it is optimized out - // EXPECT_TRUE(SubTypesChild.find(Child2Type) == SubTypesChild.end()); - const auto &SubTypesChild2 = DBTH.getSubTypes(Child3Type); - EXPECT_TRUE(SubTypesChild2.find(Child3Type) != SubTypesChild2.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_19) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 6U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); - ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); - ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); - ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); - ASSERT_NE(nullptr, ImpsumType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - EXPECT_TRUE(DBTH.hasType(FooType)); - EXPECT_TRUE(DBTH.hasType(BarType)); - EXPECT_TRUE(DBTH.hasType(LoremType)); - EXPECT_TRUE(DBTH.hasType(ImpsumType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - const auto &SubTypesFoo = DBTH.getSubTypes(FooType); - EXPECT_TRUE(SubTypesFoo.find(BarType) != SubTypesFoo.end()); - const auto &SubTypesLorem = DBTH.getSubTypes(LoremType); - EXPECT_TRUE(SubTypesLorem.find(ImpsumType) != SubTypesLorem.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_20) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 3U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(Base2Type)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - const auto &SubTypes2 = DBTH.getSubTypes(Base2Type); - EXPECT_TRUE(SubTypes2.find(ChildType) != SubTypes2.end()); -} - -TEST(DBTHTest, BasicTHReconstruction_21) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); - ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); - ASSERT_NE(nullptr, Child2Type); - - EXPECT_TRUE(DBTH.hasType(BaseType)); - EXPECT_TRUE(DBTH.hasType(Base2Type)); - EXPECT_TRUE(DBTH.hasType(Base3Type)); - EXPECT_TRUE(DBTH.hasType(ChildType)); - EXPECT_TRUE(DBTH.hasType(Child2Type)); - - // check for all subtypes - const auto &SubTypes = DBTH.getSubTypes(BaseType); - EXPECT_TRUE(SubTypes.find(ChildType) != SubTypes.end()); - const auto &SubTypesBase2 = DBTH.getSubTypes(Base2Type); - EXPECT_TRUE(SubTypesBase2.find(ChildType) != SubTypesBase2.end()); - const auto &SubTypesChild = DBTH.getSubTypes(ChildType); - EXPECT_TRUE(SubTypesChild.find(Child2Type) != SubTypesChild.end()); - const auto &SubTypesBase3 = DBTH.getSubTypes(Base3Type); - EXPECT_TRUE(SubTypesBase3.find(Child2Type) != SubTypesBase3.end()); -} - -/* ------------------------- -VTableConstruction Tests ------------------------- -*/ - -TEST(DBTHTest, VTableConstruction_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - ASSERT_TRUE(DBTH.hasVFTable(BaseType)); - ASSERT_TRUE(DBTH.hasVFTable(ChildType)); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_2) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - ASSERT_TRUE(DBTH.hasVFTable(BaseType)); - ASSERT_TRUE(DBTH.hasVFTable(ChildType)); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_3) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - ASSERT_TRUE(DBTH.hasVFTable(BaseType)); - ASSERT_TRUE(DBTH.hasVFTable(ChildType)); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_4) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - ASSERT_TRUE(DBTH.hasVFTable(BaseType)); - ASSERT_TRUE(DBTH.hasVFTable(ChildType)); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3tarEv"); -} - -TEST(DBTHTest, VTableConstruction_5) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); - ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - ASSERT_TRUE(DBTH.hasVFTable(BaseType)); - ASSERT_TRUE(DBTH.hasVFTable(OtherBaseType)); - ASSERT_TRUE(DBTH.hasVFTable(ChildType)); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForOtherBase = DBTH.getVFTable(OtherBaseType); - ASSERT_NE(nullptr, VTableForOtherBase); - ASSERT_NE(nullptr, VTableForOtherBase->getFunction(0)); - EXPECT_EQ(VTableForOtherBase->getFunction(0)->getName(), - "_ZN9OtherBase3bazEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - ASSERT_NE(nullptr, VTableForChild->getFunction(3)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); - EXPECT_EQ(VTableForChild->getFunction(3)->getName(), "_ZN5Child3tarEv"); -} - -TEST(DBTHTest, VTableConstruction_6) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3tarEv"); -} - -TEST(DBTHTest, VTableConstruction_7) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); - ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); - ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - - const auto &VTableForAType = DBTH.getVFTable(AType); - ASSERT_NE(nullptr, VTableForAType); - ASSERT_NE(nullptr, VTableForAType->getFunction(0)); - EXPECT_EQ(VTableForAType->getFunction(0)->getName(), "_ZN1A1fEv"); - const auto &VTableForBType = DBTH.getVFTable(BType); - ASSERT_NE(nullptr, VTableForBType); - EXPECT_EQ(VTableForBType->getFunction(0), nullptr); - const auto &VTableForCType = DBTH.getVFTable(CType); - ASSERT_NE(nullptr, VTableForCType); - EXPECT_EQ(VTableForCType->getFunction(0), nullptr); - const auto &VTableForDType = DBTH.getVFTable(DType); - ASSERT_NE(nullptr, VTableForDType); - EXPECT_EQ(VTableForDType->getFunction(0), nullptr); - const auto &VTableForXType = DBTH.getVFTable(XType); - ASSERT_NE(nullptr, VTableForXType); - ASSERT_NE(nullptr, VTableForXType->getFunction(0)); - EXPECT_EQ(VTableForXType->getFunction(0)->getName(), "_ZN1X1gEv"); - const auto &VTableForYType = DBTH.getVFTable(YType); - ASSERT_NE(nullptr, VTableForYType); - EXPECT_EQ(VTableForYType->getFunction(0), nullptr); - const auto &VTableForZType = DBTH.getVFTable(ZType); - ASSERT_NE(nullptr, VTableForZType); - EXPECT_EQ(VTableForZType->getFunction(0), nullptr); -} - -TEST(DBTHTest, VTableConstruction_7_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); - ASSERT_NE(nullptr, OmegaType); - - const auto &VTableForAType = DBTH.getVFTable(AType); - ASSERT_NE(nullptr, VTableForAType); - ASSERT_NE(nullptr, VTableForAType->getFunction(0)); - EXPECT_EQ(VTableForAType->getFunction(0)->getName(), "_ZN1A1fEv"); - const auto &VTableForCType = DBTH.getVFTable(CType); - ASSERT_NE(nullptr, VTableForCType); - EXPECT_EQ(VTableForCType->getFunction(0), nullptr); - const auto &VTableForXType = DBTH.getVFTable(XType); - ASSERT_NE(nullptr, VTableForXType); - ASSERT_NE(nullptr, VTableForXType->getFunction(0)); - EXPECT_EQ(VTableForXType->getFunction(0)->getName(), "_ZN1X1gEv"); - const auto &VTableForYType = DBTH.getVFTable(YType); - ASSERT_NE(nullptr, VTableForYType); - EXPECT_EQ(VTableForYType->getFunction(0), nullptr); - const auto &VTableForZType = DBTH.getVFTable(ZType); - ASSERT_NE(nullptr, VTableForZType); - EXPECT_EQ(VTableForZType->getFunction(0), nullptr); - const auto &VTableForOmegaType = DBTH.getVFTable(OmegaType); - ASSERT_NE(nullptr, VTableForOmegaType); - ASSERT_NE(nullptr, VTableForOmegaType->getFunction(0)); - EXPECT_EQ(VTableForOmegaType->getFunction(0)->getName(), "_ZN5Omega1fEv"); -} - -TEST(DBTHTest, VTableConstruction_8) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); - EXPECT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); - EXPECT_NE(nullptr, NonvirtualStructType); - - const auto &VTableForBaseType = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBaseType); - ASSERT_NE(nullptr, VTableForBaseType->getFunction(0)); - ASSERT_NE(nullptr, VTableForBaseType->getFunction(1)); - EXPECT_EQ(VTableForBaseType->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBaseType->getFunction(1)->getName(), "_ZN4Base3barEv"); - const auto &VTableForChildType = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChildType); - ASSERT_NE(nullptr, VTableForChildType->getFunction(0)); - EXPECT_EQ(VTableForChildType->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForChildType->getFunction(2)); - EXPECT_EQ(VTableForChildType->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChildType->getFunction(2)->getName(), "_ZN5Child3bazEv"); - - const auto &VTableForNonvirtualClassType = - DBTH.getVFTable(NonvirtualClassType); - ASSERT_NE(nullptr, VTableForNonvirtualClassType); - EXPECT_EQ(VTableForNonvirtualClassType->getFunction(0), nullptr); - const auto &VTableForNonvirtualStructType = - DBTH.getVFTable(NonvirtualStructType); - ASSERT_NE(nullptr, VTableForNonvirtualStructType); - EXPECT_EQ(VTableForNonvirtualStructType->getFunction(0), nullptr); -} - -TEST(DBTHTest, VTableConstruction_9) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); -} - -TEST(DBTHTest, VTableConstruction_10) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_TRUE(VTableForChild->getFunction(1) == nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); -} - -TEST(DBTHTest, VTableConstruction_11) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_12) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_12_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - EXPECT_EQ(VTableForChild->getFunction(0), nullptr); - - const auto &VTableForChildsChild = DBTH.getVFTable(ChildsChildType); - ASSERT_NE(nullptr, VTableForChildsChild); - ASSERT_NE(nullptr, VTableForChildsChild->getFunction(0)); - EXPECT_EQ(VTableForChildsChild->getFunction(0)->getName(), - "_ZN11ChildsChild3fooEv"); -} - -TEST(DBTHTest, VTableConstruction_12_c) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - - const auto &VTableForChildsChild = DBTH.getVFTable(ChildsChildType); - ASSERT_NE(nullptr, VTableForChildsChild); - EXPECT_EQ(VTableForChildsChild->getFunction(0), nullptr); -} - -/* -TEST(DBTHTest, VTableConstruction_13) { - Test file 13 has no types -} -*/ - -TEST(DBTHTest, VTableConstruction_14) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base4testEv"); -} - -TEST(DBTHTest, VTableConstruction_15) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base4testEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - EXPECT_EQ(VTableForChild->getFunction(0), nullptr); -} - -TEST(DBTHTest, VTableConstruction_16) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildOfChildType = DBTH.getType("ChildOfChild"); - ASSERT_NE(nullptr, ChildOfChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); - ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); - ASSERT_NE(nullptr, ChildTwoType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base3fooEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - - const auto &VTableForChildOfChild = DBTH.getVFTable(ChildOfChildType); - ASSERT_NE(nullptr, VTableForChildOfChild); - EXPECT_EQ(VTableForChildOfChild->getFunction(0), nullptr); - - const auto &VTableForBaseTwo = DBTH.getVFTable(BaseTwoType); - ASSERT_NE(nullptr, VTableForBaseTwo); - ASSERT_NE(nullptr, VTableForBaseTwo->getFunction(0)); - EXPECT_EQ(VTableForBaseTwo->getFunction(0)->getName(), - "_ZN7BaseTwo6foobarEv"); - - const auto &VTableForChildTwo = DBTH.getVFTable(ChildTwoType); - ASSERT_NE(nullptr, VTableForChildTwo); - ASSERT_NE(nullptr, VTableForChildTwo->getFunction(0)); - EXPECT_EQ(VTableForChildTwo->getFunction(0)->getName(), - "_ZN8ChildTwo6foobarEv"); -} - -TEST(DBTHTest, VTableConstruction_17) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // Since Child2 is never used, it is sometimes optimized out by the compiler - // const auto &Child2Type = DBTH.getType("Child2"); - // ASSERT_NE(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); - ASSERT_NE(nullptr, KidType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3bazEv"); - - const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); - ASSERT_NE(nullptr, VTableForBase2); - EXPECT_EQ(VTableForBase2->getFunction(0), nullptr); - ASSERT_NE(nullptr, VTableForBase2->getFunction(1)); - EXPECT_EQ(VTableForBase2->getFunction(2), nullptr); - ASSERT_NE(nullptr, VTableForBase2->getFunction(3)); - EXPECT_EQ(VTableForBase2->getFunction(1)->getName(), "_ZN5Base23barEv"); - EXPECT_EQ(VTableForBase2->getFunction(3)->getName(), "_ZN5Base26foobarEv"); - - const auto &VTableForKid = DBTH.getVFTable(KidType); - ASSERT_NE(nullptr, VTableForKid); - ASSERT_NE(nullptr, VTableForKid->getFunction(0)); - EXPECT_EQ(VTableForKid->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForKid->getFunction(2)); - EXPECT_EQ(VTableForKid->getFunction(3), nullptr); - ASSERT_NE(nullptr, VTableForKid->getFunction(4)); - EXPECT_EQ(VTableForKid->getFunction(0)->getName(), "_ZN3Kid3fooEv"); - EXPECT_EQ(VTableForKid->getFunction(2)->getName(), "_ZN3Kid6barfooEv"); - EXPECT_EQ(VTableForKid->getFunction(4)->getName(), "_ZN3Kid3bauEv"); -} - -TEST(DBTHTest, VTableConstruction_18) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child_2"); - ASSERT_NE(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); - ASSERT_NE(nullptr, Child3Type); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - - const auto &VTableForChild2 = DBTH.getVFTable(Child2Type); - ASSERT_NE(nullptr, VTableForChild2); - EXPECT_EQ(VTableForChild2->getFunction(0), nullptr); - EXPECT_EQ(VTableForChild2->getFunction(1), nullptr); - // Test - // ASSERT_NE(nullptr, VTableForBase->getFunction(2)); - EXPECT_EQ(VTableForChild2->getFunction(2)->getName(), "_ZN7Child_26foobarEv"); - - const auto &VTableForChild3 = DBTH.getVFTable(Child3Type); - ASSERT_NE(nullptr, VTableForChild3); - EXPECT_EQ(VTableForChild3->getFunction(0), nullptr); - EXPECT_EQ(VTableForChild3->getFunction(1), nullptr); - EXPECT_EQ(VTableForChild3->getFunction(2), nullptr); - ASSERT_NE(nullptr, VTableForChild3->getFunction(3)); - EXPECT_EQ(VTableForChild3->getFunction(3)->getName(), "_ZN7Child_36barfooEv"); -} - -TEST(DBTHTest, VTableConstruction_19) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); - ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); - ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); - ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); - ASSERT_NE(nullptr, ImpsumType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - ASSERT_NE(nullptr, VTableForBase->getFunction(0)); - EXPECT_EQ(VTableForBase->getFunction(0)->getName(), "_ZN4Base10publicbaseEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), - "_ZN5Child10publicbaseEv"); - - const auto &VTableForBar = DBTH.getVFTable(BarType); - ASSERT_NE(nullptr, VTableForBar); - ASSERT_NE(nullptr, VTableForBar->getFunction(0)); - EXPECT_EQ(VTableForBar->getFunction(0)->getName(), "_ZN3Bar12protectedfooEv"); - - const auto &VTableForFoo = DBTH.getVFTable(FooType); - ASSERT_NE(nullptr, VTableForFoo); - ASSERT_NE(nullptr, VTableForFoo->getFunction(0)); - EXPECT_EQ(VTableForFoo->getFunction(0)->getName(), "_ZN3Foo12protectedfooEv"); - - const auto &VTableForLorem = DBTH.getVFTable(LoremType); - ASSERT_NE(nullptr, VTableForLorem); - ASSERT_NE(nullptr, VTableForLorem->getFunction(0)); - EXPECT_EQ(VTableForLorem->getFunction(0)->getName(), - "_ZN5Lorem12privateloremEv"); - - const auto &VTableForImpsum = DBTH.getVFTable(ImpsumType); - ASSERT_NE(nullptr, VTableForImpsum); - ASSERT_NE(nullptr, VTableForImpsum->getFunction(0)); - EXPECT_EQ(VTableForImpsum->getFunction(0)->getName(), - "_ZN6Impsum12privateloremEv"); -} - -TEST(DBTHTest, VTableConstruction_20) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - ASSERT_NE(nullptr, VTableForBase->getFunction(1)); - EXPECT_EQ(VTableForBase->getFunction(1)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - ASSERT_NE(nullptr, VTableForChild->getFunction(0)); - EXPECT_EQ(VTableForChild->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(0)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child4bar2Ev"); - - const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); - ASSERT_NE(nullptr, VTableForBase2); - ASSERT_NE(nullptr, VTableForBase2->getFunction(0)); - EXPECT_EQ(VTableForBase2->getFunction(0)->getName(), "_ZN5Base24foo2Ev"); -} - -TEST(DBTHTest, VTableConstruction_21) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); - ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); - ASSERT_NE(nullptr, Child2Type); - - const auto &VTableForBase = DBTH.getVFTable(BaseType); - ASSERT_NE(nullptr, VTableForBase); - EXPECT_EQ(VTableForBase->getFunction(0), nullptr); - EXPECT_EQ(VTableForBase->getFunction(1), nullptr); - EXPECT_EQ(VTableForBase->getFunction(2), nullptr); - // Test - // ASSERT_NE(nullptr, VTableForBase->getFunction(3)); - EXPECT_EQ(VTableForBase->getFunction(3)->getName(), "_ZN4Base3barEv"); - - const auto &VTableForBase2 = DBTH.getVFTable(Base2Type); - ASSERT_NE(nullptr, VTableForBase2); - EXPECT_EQ(VTableForBase2->getFunction(0), nullptr); - EXPECT_EQ(VTableForBase2->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForBase2->getFunction(2)); - EXPECT_EQ(VTableForBase2->getFunction(2)->getName(), "_ZN5Base24foo2Ev"); - - const auto &VTableForBase3 = DBTH.getVFTable(Base3Type); - ASSERT_NE(nullptr, VTableForBase3); - EXPECT_EQ(nullptr, VTableForBase->getFunction(0)); - - const auto &VTableForChild = DBTH.getVFTable(ChildType); - ASSERT_NE(nullptr, VTableForChild); - EXPECT_EQ(VTableForChild->getFunction(0), nullptr); - EXPECT_EQ(VTableForChild->getFunction(1), nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(2)); - EXPECT_EQ(VTableForChild->getFunction(2)->getName(), "_ZN5Child3fooEv"); - EXPECT_EQ(VTableForChild->getFunction(3), nullptr); - ASSERT_NE(nullptr, VTableForChild->getFunction(4)); - EXPECT_EQ(VTableForChild->getFunction(4)->getName(), "_ZN5Child4bar2Ev"); - - const auto &VTableForChild2 = DBTH.getVFTable(Child2Type); - ASSERT_NE(nullptr, VTableForChild2); - EXPECT_EQ(VTableForChild2->getFunction(0), nullptr); - EXPECT_EQ(VTableForChild2->getFunction(1), nullptr); - EXPECT_EQ(VTableForChild2->getFunction(2), nullptr); - EXPECT_EQ(VTableForChild2->getFunction(3), nullptr); - EXPECT_EQ(VTableForChild2->getFunction(4), nullptr); - ASSERT_NE(nullptr, VTableForChild2->getFunction(5)); - EXPECT_EQ(VTableForChild2->getFunction(5)->getName(), "_ZN6Child26foobarEv"); -} - -/* --------------------------------- -TransitivelyReachableTypes Tests --------------------------------- -*/ - -TEST(DBTHTest, TransitivelyReachableTypes_1) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_1_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_2) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_2_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_3) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_3_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_4) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_4_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_5) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_5_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); - ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesOtherBase = DBTH.getSubTypes(OtherBaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesOtherBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_TRUE(ReachableTypesOtherBase.count(OtherBaseType)); - EXPECT_TRUE(ReachableTypesOtherBase.count(ChildType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_FALSE(ReachableTypesChild.count(OtherBaseType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_6) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_7) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); - ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); - ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - - auto ReachableTypesA = DBTH.getSubTypes(AType); - auto ReachableTypesB = DBTH.getSubTypes(BType); - auto ReachableTypesC = DBTH.getSubTypes(CType); - auto ReachableTypesD = DBTH.getSubTypes(DType); - auto ReachableTypesX = DBTH.getSubTypes(XType); - auto ReachableTypesY = DBTH.getSubTypes(YType); - auto ReachableTypesZ = DBTH.getSubTypes(ZType); - - EXPECT_EQ(ReachableTypesA.size(), 5U); - EXPECT_EQ(ReachableTypesB.size(), 2U); - EXPECT_EQ(ReachableTypesC.size(), 2U); - EXPECT_EQ(ReachableTypesD.size(), 1U); - EXPECT_EQ(ReachableTypesX.size(), 3U); - EXPECT_EQ(ReachableTypesY.size(), 2U); - EXPECT_EQ(ReachableTypesZ.size(), 1U); - - EXPECT_TRUE(ReachableTypesA.count(AType)); - EXPECT_TRUE(ReachableTypesA.count(BType)); - EXPECT_TRUE(ReachableTypesA.count(CType)); - EXPECT_TRUE(ReachableTypesA.count(DType)); - EXPECT_FALSE(ReachableTypesA.count(XType)); - EXPECT_FALSE(ReachableTypesA.count(YType)); - EXPECT_TRUE(ReachableTypesA.count(ZType)); - - EXPECT_FALSE(ReachableTypesB.count(AType)); - EXPECT_TRUE(ReachableTypesB.count(BType)); - EXPECT_FALSE(ReachableTypesB.count(CType)); - EXPECT_TRUE(ReachableTypesB.count(DType)); - EXPECT_FALSE(ReachableTypesB.count(XType)); - EXPECT_FALSE(ReachableTypesB.count(YType)); - EXPECT_FALSE(ReachableTypesB.count(ZType)); - - EXPECT_FALSE(ReachableTypesC.count(AType)); - EXPECT_FALSE(ReachableTypesC.count(BType)); - EXPECT_TRUE(ReachableTypesC.count(CType)); - EXPECT_FALSE(ReachableTypesC.count(DType)); - EXPECT_FALSE(ReachableTypesC.count(XType)); - EXPECT_FALSE(ReachableTypesC.count(YType)); - EXPECT_TRUE(ReachableTypesC.count(ZType)); - - EXPECT_FALSE(ReachableTypesD.count(AType)); - EXPECT_FALSE(ReachableTypesD.count(BType)); - EXPECT_FALSE(ReachableTypesD.count(CType)); - EXPECT_TRUE(ReachableTypesD.count(DType)); - EXPECT_FALSE(ReachableTypesD.count(XType)); - EXPECT_FALSE(ReachableTypesD.count(YType)); - EXPECT_FALSE(ReachableTypesD.count(ZType)); - - EXPECT_FALSE(ReachableTypesX.count(AType)); - EXPECT_FALSE(ReachableTypesX.count(BType)); - EXPECT_FALSE(ReachableTypesX.count(CType)); - EXPECT_FALSE(ReachableTypesX.count(DType)); - EXPECT_TRUE(ReachableTypesX.count(XType)); - EXPECT_TRUE(ReachableTypesX.count(YType)); - EXPECT_TRUE(ReachableTypesX.count(ZType)); - - EXPECT_FALSE(ReachableTypesY.count(AType)); - EXPECT_FALSE(ReachableTypesY.count(BType)); - EXPECT_FALSE(ReachableTypesY.count(CType)); - EXPECT_FALSE(ReachableTypesY.count(DType)); - EXPECT_FALSE(ReachableTypesY.count(XType)); - EXPECT_TRUE(ReachableTypesY.count(YType)); - EXPECT_TRUE(ReachableTypesY.count(ZType)); - - EXPECT_FALSE(ReachableTypesZ.count(AType)); - EXPECT_FALSE(ReachableTypesZ.count(BType)); - EXPECT_FALSE(ReachableTypesZ.count(CType)); - EXPECT_FALSE(ReachableTypesZ.count(DType)); - EXPECT_FALSE(ReachableTypesZ.count(XType)); - EXPECT_FALSE(ReachableTypesZ.count(YType)); - EXPECT_TRUE(ReachableTypesZ.count(ZType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_7_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_7_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &AType = DBTH.getType("A"); - ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); - ASSERT_NE(nullptr, CType); - const auto &XType = DBTH.getType("X"); - ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); - ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); - ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); - ASSERT_NE(nullptr, OmegaType); - - auto ReachableTypesA = DBTH.getSubTypes(AType); - auto ReachableTypesC = DBTH.getSubTypes(CType); - auto ReachableTypesX = DBTH.getSubTypes(XType); - auto ReachableTypesY = DBTH.getSubTypes(YType); - auto ReachableTypesZ = DBTH.getSubTypes(ZType); - auto ReachableTypesOmega = DBTH.getSubTypes(OmegaType); - - EXPECT_EQ(ReachableTypesA.size(), 4U); - EXPECT_EQ(ReachableTypesC.size(), 3U); - EXPECT_EQ(ReachableTypesX.size(), 4U); - EXPECT_EQ(ReachableTypesY.size(), 3U); - EXPECT_EQ(ReachableTypesZ.size(), 2U); - EXPECT_EQ(ReachableTypesOmega.size(), 1U); - - EXPECT_TRUE(ReachableTypesA.count(AType)); - EXPECT_TRUE(ReachableTypesA.count(CType)); - EXPECT_FALSE(ReachableTypesA.count(XType)); - EXPECT_FALSE(ReachableTypesA.count(YType)); - EXPECT_TRUE(ReachableTypesA.count(ZType)); - EXPECT_TRUE(ReachableTypesA.count(OmegaType)); - - EXPECT_FALSE(ReachableTypesC.count(AType)); - EXPECT_TRUE(ReachableTypesC.count(CType)); - EXPECT_FALSE(ReachableTypesC.count(XType)); - EXPECT_FALSE(ReachableTypesC.count(YType)); - EXPECT_TRUE(ReachableTypesC.count(ZType)); - EXPECT_TRUE(ReachableTypesC.count(OmegaType)); - - EXPECT_FALSE(ReachableTypesX.count(AType)); - EXPECT_FALSE(ReachableTypesX.count(CType)); - EXPECT_TRUE(ReachableTypesX.count(XType)); - EXPECT_TRUE(ReachableTypesX.count(YType)); - EXPECT_TRUE(ReachableTypesX.count(ZType)); - EXPECT_TRUE(ReachableTypesX.count(OmegaType)); - - EXPECT_FALSE(ReachableTypesY.count(AType)); - EXPECT_FALSE(ReachableTypesY.count(CType)); - EXPECT_FALSE(ReachableTypesY.count(XType)); - EXPECT_TRUE(ReachableTypesY.count(YType)); - EXPECT_TRUE(ReachableTypesY.count(ZType)); - EXPECT_TRUE(ReachableTypesY.count(OmegaType)); - - EXPECT_FALSE(ReachableTypesZ.count(AType)); - EXPECT_FALSE(ReachableTypesZ.count(CType)); - EXPECT_FALSE(ReachableTypesZ.count(XType)); - EXPECT_FALSE(ReachableTypesZ.count(YType)); - EXPECT_TRUE(ReachableTypesZ.count(ZType)); - EXPECT_TRUE(ReachableTypesZ.count(OmegaType)); - - EXPECT_FALSE(ReachableTypesOmega.count(AType)); - EXPECT_FALSE(ReachableTypesOmega.count(CType)); - EXPECT_FALSE(ReachableTypesOmega.count(XType)); - EXPECT_FALSE(ReachableTypesOmega.count(YType)); - EXPECT_FALSE(ReachableTypesOmega.count(ZType)); - EXPECT_TRUE(ReachableTypesOmega.count(OmegaType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_8) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_8_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); - ASSERT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); - ASSERT_NE(nullptr, NonvirtualStructType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesNonvirtualClass = DBTH.getSubTypes(NonvirtualClassType); - auto ReachableTypesNonvirtualStruct = DBTH.getSubTypes(NonvirtualStructType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_EQ(ReachableTypesNonvirtualClass.size(), 1U); - EXPECT_EQ(ReachableTypesNonvirtualStruct.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesBase.count(NonvirtualClassType)); - EXPECT_FALSE(ReachableTypesBase.count(NonvirtualStructType)); - - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(NonvirtualClassType)); - EXPECT_FALSE(ReachableTypesChild.count(NonvirtualStructType)); - - EXPECT_FALSE(ReachableTypesNonvirtualClass.count(BaseType)); - EXPECT_FALSE(ReachableTypesNonvirtualClass.count(ChildType)); - EXPECT_TRUE(ReachableTypesNonvirtualClass.count(NonvirtualClassType)); - EXPECT_FALSE(ReachableTypesNonvirtualClass.count(NonvirtualStructType)); - - EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(BaseType)); - EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(ChildType)); - EXPECT_FALSE(ReachableTypesNonvirtualStruct.count(NonvirtualClassType)); - EXPECT_TRUE(ReachableTypesNonvirtualStruct.count(NonvirtualStructType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_9) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_10) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_10_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_11) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_11_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_12) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_12_b) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_b_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 3U); - EXPECT_EQ(ReachableTypesChild.size(), 2U); - EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildsChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); - EXPECT_FALSE(ReachableTypesChildsChild.count(BaseType)); - EXPECT_FALSE(ReachableTypesChildsChild.count(ChildType)); - EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_12_c) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_12_c_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); - ASSERT_NE(nullptr, ChildsChildType); - - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); - - EXPECT_EQ(ReachableTypesChild.size(), 2U); - EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); - EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); -} - -/* -TEST(DBTHTest, BasicTHReconstruction_13) { - Test file 13 has no types -} -*/ - -TEST(DBTHTest, TransitivelyReachableTypes_14) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_14_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - - EXPECT_EQ(ReachableTypesBase.size(), 1U); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_15) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_15_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_FALSE(ReachableTypesChild.count(BaseType)); - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_16) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // const auto &ChildsChildType = DBTH.getType("ChildsChild"); - // Since ChildsChild is never used, it is optimized out - // ASSERT_EQ(nullptr, ChildsChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); - ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); - ASSERT_NE(nullptr, ChildTwoType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - // Since ChildsChild is never used, it is optimized out - // auto ReachableTypesChildsChild = DBTH.getSubTypes(ChildsChildType); - auto ReachableTypesBaseTwo = DBTH.getSubTypes(BaseTwoType); - auto ReachableTypesChildTwo = DBTH.getSubTypes(ChildTwoType); - - EXPECT_EQ(ReachableTypesBase.size(), 3U); - EXPECT_EQ(ReachableTypesChild.size(), 2U); - // EXPECT_EQ(ReachableTypesChildsChild.size(), 1U); - EXPECT_EQ(ReachableTypesBaseTwo.size(), 2U); - EXPECT_EQ(ReachableTypesChildTwo.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - // EXPECT_TRUE(ReachableTypesChild.count(ChildsChildType)); - - // EXPECT_TRUE(ReachableTypesChildsChild.count(ChildsChildType)); - - EXPECT_TRUE(ReachableTypesBaseTwo.count(BaseTwoType)); - EXPECT_TRUE(ReachableTypesBaseTwo.count(ChildTwoType)); - - EXPECT_TRUE(ReachableTypesChildTwo.count(ChildTwoType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_17) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_17_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - // const auto &Child2Type = DBTH.getType("Child2"); - // Since Child2 is never used, it is optimized out - // ASSERT_EQ(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); - ASSERT_NE(nullptr, KidType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - // Since Child2 is never used, it is optimized out - // auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); - auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); - auto ReachableTypesKid = DBTH.getSubTypes(KidType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - // EXPECT_EQ(ReachableTypesChild2.size(), 1U); - EXPECT_EQ(ReachableTypesBase2.size(), 2U); - EXPECT_EQ(ReachableTypesKid.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - // EXPECT_TRUE(ReachableTypesChild.count(Child2Type)); - - // EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); - - EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); - // EXPECT_TRUE(ReachableTypesBase2.count(Child2Type)); - - EXPECT_TRUE(ReachableTypesKid.count(KidType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_18) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_18_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child_2"); - ASSERT_NE(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); - ASSERT_NE(nullptr, Child3Type); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); - auto ReachableTypesChild3 = DBTH.getSubTypes(Child3Type); - - EXPECT_EQ(ReachableTypesBase.size(), 4U); - EXPECT_EQ(ReachableTypesChild.size(), 3U); - EXPECT_EQ(ReachableTypesChild2.size(), 2U); - EXPECT_EQ(ReachableTypesChild3.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - EXPECT_TRUE(ReachableTypesBase.count(Child2Type)); - EXPECT_TRUE(ReachableTypesBase.count(Child3Type)); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - EXPECT_TRUE(ReachableTypesChild.count(Child2Type)); - EXPECT_TRUE(ReachableTypesChild.count(Child3Type)); - - EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); - EXPECT_TRUE(ReachableTypesChild3.count(Child3Type)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_19) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_19_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); - ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); - ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); - ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); - ASSERT_NE(nullptr, ImpsumType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesFoo = DBTH.getSubTypes(FooType); - auto ReachableTypesBar = DBTH.getSubTypes(BarType); - auto ReachableTypesLorem = DBTH.getSubTypes(LoremType); - auto ReachableTypesImpsum = DBTH.getSubTypes(ImpsumType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - EXPECT_EQ(ReachableTypesFoo.size(), 2U); - EXPECT_EQ(ReachableTypesBar.size(), 1U); - EXPECT_EQ(ReachableTypesLorem.size(), 2U); - EXPECT_EQ(ReachableTypesImpsum.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); - - EXPECT_TRUE(ReachableTypesFoo.count(FooType)); - EXPECT_TRUE(ReachableTypesFoo.count(BarType)); - - EXPECT_TRUE(ReachableTypesBar.count(BarType)); - - EXPECT_TRUE(ReachableTypesLorem.count(LoremType)); - EXPECT_TRUE(ReachableTypesLorem.count(ImpsumType)); - - EXPECT_TRUE(ReachableTypesImpsum.count(ImpsumType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_20) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_20_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); - - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - - EXPECT_EQ(ReachableTypesBase.size(), 2U); - EXPECT_EQ(ReachableTypesBase2.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 1U); - - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); - - EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); - EXPECT_TRUE(ReachableTypesBase2.count(ChildType)); - - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); -} - -TEST(DBTHTest, TransitivelyReachableTypes_21) { - LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + - "type_hierarchies/type_hierarchy_21_cpp_dbg.ll"); - DIBasedTypeHierarchy DBTH(IRDB); +class LLVMBasedICFGGSerializationTest : public ::testing::Test { + void serAndDeser(const llvm::Twine &IRFile) { + using namespace std::string_literals; - // check for all types - const auto &BaseType = DBTH.getType("Base"); - ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); - ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); - ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); - ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); - ASSERT_NE(nullptr, Child2Type); + /// TODO: add all IRFiles in an array and run tests over these files - auto ReachableTypesBase = DBTH.getSubTypes(BaseType); - auto ReachableTypesBase2 = DBTH.getSubTypes(Base2Type); - auto ReachableTypesBase3 = DBTH.getSubTypes(Base3Type); - auto ReachableTypesChild = DBTH.getSubTypes(ChildType); - auto ReachableTypesChild2 = DBTH.getSubTypes(Child2Type); + psr::LLVMProjectIRDB IRDB(IRFile); + psr::DIBasedTypeHierarchy DIBTH(IRDB); - EXPECT_EQ(ReachableTypesBase.size(), 3U); - EXPECT_EQ(ReachableTypesBase2.size(), 3U); - EXPECT_EQ(ReachableTypesBase3.size(), 2U); - EXPECT_EQ(ReachableTypesChild.size(), 2U); - EXPECT_EQ(ReachableTypesChild2.size(), 1U); + std::string Ser; + // stream data into a json file using the printAsJson() function + llvm::raw_string_ostream StringStream(Ser); - EXPECT_TRUE(ReachableTypesBase.count(BaseType)); - EXPECT_TRUE(ReachableTypesBase.count(ChildType)); + DIBTH.printAsJson(StringStream); - EXPECT_TRUE(ReachableTypesBase2.count(Base2Type)); - EXPECT_TRUE(ReachableTypesBase2.count(ChildType)); + psr::DIBasedTypeHierarchy DeserializedDIBTH( + &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); - EXPECT_TRUE(ReachableTypesBase3.count(Base3Type)); - EXPECT_TRUE(ReachableTypesBase3.count(Child2Type)); + compareResults(DIBTH, DeserializedDIBTH); + } - EXPECT_TRUE(ReachableTypesChild.count(ChildType)); + void compareResults(const psr::DIBasedTypeHierarchy &Orig, + const psr::DIBasedTypeHierarchy &Deser) { - EXPECT_TRUE(ReachableTypesChild2.count(Child2Type)); -} + ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); + ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); -} // namespace psr + for (const auto &OrigCurrentType : Orig.getAllTypes()) { + EXPECT_EQ(OrigCurrentType, + Deser.getType(OrigCurrentType->getName().str())); + EXPECT_EQ(Orig.getVFTable(OrigCurrentType), + Deser.getVFTable(OrigCurrentType)); + } + } -int main(int Argc, char **Argv) { - ::testing::InitGoogleTest(&Argc, Argv); - auto Res = RUN_ALL_TESTS(); - return Res; -} + int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + auto Res = RUN_ALL_TESTS(); + return Res; + } +}; \ No newline at end of file From 1cb334511106d576c6f3c3910981b846352a10c5 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 28 Mar 2024 12:32:31 +0100 Subject: [PATCH 12/42] DIBTHData getDataFromJson Impl --- .../DIBasedTypeHierarchyData.cpp | 37 ++++++++- .../DIBasedTypeHierarchySerializationTest.cpp | 75 +++++++++++-------- 2 files changed, 78 insertions(+), 34 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index 19d060d7a..abdabde6c 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -17,11 +17,42 @@ namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { - DIBasedTypeHierarchyData ToReturn; + DIBasedTypeHierarchyData Data; - /// TODO: + // NameToType + for (const auto &[Key, Value] : + Json["NameToType"].get()) { + Data.NameToType.try_emplace(Key, Value); + } + + // TypeToVertex + for (const auto &[Key, Value] : + Json["TypeToVertex"].get()) { + Data.TypeToVertex.try_emplace(Key, Value); + } + + // VertexTypes + for (const auto &Value : Json["VertexTypes"]) { + Data.VertexTypes.push_back(Value); + } + + // TransitiveDerivedIndex + for (const auto &[First, Second] : + Json["TransitiveDerivedIndex"].get()) { + Data.TransitiveDerivedIndex.emplace_back(First, Second); + } + // Hierarchy + for (const auto &Value : Json["Hierarchy"]) { + Data.Hierarchy.push_back(Value); + } + // VTables + for (const auto &CurrVTable : Json["VTables"]) { + for (const auto &CurrVFunc : CurrVTable) { + /// TODO: find out how to deserialize this + } + } - return ToReturn; + return Data; } void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 0c28e8a18..863ad5067 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -10,44 +10,57 @@ #include "TestConfig.h" #include "gtest/gtest.h" -class LLVMBasedICFGGSerializationTest : public ::testing::Test { - void serAndDeser(const llvm::Twine &IRFile) { - using namespace std::string_literals; +using namespace psr; - /// TODO: add all IRFiles in an array and run tests over these files +/* ============== TEST FIXTURE ============== */ +class TypeHierarchySerialization + : public ::testing::TestWithParam { +protected: + static constexpr auto PathToLlFiles = + PHASAR_BUILD_SUBFOLDER("type_hierarchies/"); + const std::vector EntryPoints = {"main"}; - psr::LLVMProjectIRDB IRDB(IRFile); - psr::DIBasedTypeHierarchy DIBTH(IRDB); +}; // Test Fixture - std::string Ser; - // stream data into a json file using the printAsJson() function - llvm::raw_string_ostream StringStream(Ser); +void compareResults(const psr::DIBasedTypeHierarchy &Orig, + const psr::DIBasedTypeHierarchy &Deser) { + ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); + ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); - DIBTH.printAsJson(StringStream); + for (const auto &OrigCurrentType : Orig.getAllTypes()) { + EXPECT_EQ(OrigCurrentType, Deser.getType(OrigCurrentType->getName().str())); + EXPECT_EQ(Orig.getVFTable(OrigCurrentType), + Deser.getVFTable(OrigCurrentType)); + } +} - psr::DIBasedTypeHierarchy DeserializedDIBTH( - &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); +TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { + using namespace std::string_literals; - compareResults(DIBTH, DeserializedDIBTH); - } + psr::LLVMProjectIRDB IRDB(psr::unittest::PathToLLTestFiles + GetParam()); + psr::DIBasedTypeHierarchy DIBTH(IRDB); - void compareResults(const psr::DIBasedTypeHierarchy &Orig, - const psr::DIBasedTypeHierarchy &Deser) { + std::string Ser; + // stream data into a json file using the printAsJson() function + llvm::raw_string_ostream StringStream(Ser); - ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); - ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); + DIBTH.printAsJson(StringStream); - for (const auto &OrigCurrentType : Orig.getAllTypes()) { - EXPECT_EQ(OrigCurrentType, - Deser.getType(OrigCurrentType->getName().str())); - EXPECT_EQ(Orig.getVFTable(OrigCurrentType), - Deser.getVFTable(OrigCurrentType)); - } - } + psr::DIBasedTypeHierarchy DeserializedDIBTH( + &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); - int main(int Argc, char **Argv) { - ::testing::InitGoogleTest(&Argc, Argv); - auto Res = RUN_ALL_TESTS(); - return Res; - } -}; \ No newline at end of file + compareResults(DIBTH, DeserializedDIBTH); +} + +static constexpr std::string_view TypeHierarchyTestFiles[] = { + "type_hierarchy_1_cpp_dbg.ll", "type_hierarchy_2_cpp_dbg.ll"}; + +INSTANTIATE_TEST_SUITE_P(TypeHierarchySerializationTest, + TypeHierarchySerialization, + ::testing::ValuesIn(TypeHierarchyTestFiles)); + +int main(int Argc, char **Argv) { + ::testing::InitGoogleTest(&Argc, Argv); + auto Res = RUN_ALL_TESTS(); + return Res; +} From d8285660c6c750c6b6652cded2a6eb1a442b28fe Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 29 Mar 2024 16:40:19 +0100 Subject: [PATCH 13/42] improved de-/serialization impl w/o TypeToVertex --- .../TypeHierarchy/DIBasedTypeHierarchy.h | 2 +- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 23 +++- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 113 +++++++++++------- .../DIBasedTypeHierarchyData.cpp | 39 ++++-- 4 files changed, 117 insertions(+), 60 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index fa8cfd12c..4c73b5f02 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -34,7 +34,7 @@ class DIBasedTypeHierarchy explicit DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB); explicit DIBasedTypeHierarchy(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchyData &SerializedCG); + const DIBasedTypeHierarchyData &SerializedData); ~DIBasedTypeHierarchy() override = default; [[nodiscard]] bool hasType(ClassType Type) const override { diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index 061086c9b..991b39fdb 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -14,16 +14,31 @@ #include "llvm/ADT/StringMap.h" #include "llvm/Support/raw_ostream.h" +#include #include namespace psr { struct DIBasedTypeHierarchyData { - llvm::StringMap NameToType; - llvm::DenseMap TypeToVertex; - std::vector VertexTypes; + // DITypes and llvm::Function * are serialized by serializing their names and + // using the DebugInfoFinder to deserialize them + + // llvm::StringMap NameToType + // using ClassType = const llvm::DIType * + llvm::StringMap NameToType; + // llvm::DenseMap TypeToVertex + // using ClassType = const llvm::DIType * + /// TODO: llvm::DenseMap TypeToVertex; + // std::vector VertexTypes + std::vector VertexTypes; + // std::vector> TransitiveDerivedIndex std::vector> TransitiveDerivedIndex; + // std::vector Hierarchy + // using ClassType = const llvm::DIType * std::vector Hierarchy; - std::deque> VTables; + // std::deque VTables + // Relevant data of LLVMVFTable: + // std::vector VFT; + std::deque> VTables; DIBasedTypeHierarchyData() noexcept = default; void printAsJson(llvm::raw_ostream &OS); diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index b8515b13c..eb1a1e963 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -18,8 +18,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -33,6 +35,7 @@ #include #include #include +#include namespace psr { using ClassType = DIBasedTypeHierarchy::ClassType; @@ -194,7 +197,9 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { } static llvm::SmallVector -findAllFunctionDefs(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { +findAllDITypes(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { + /// TODO: umschreiben, so dass diese Funktion alle DITypes mithilfe des Debug + /// Info Finders findet llvm::SmallVector FnDefs; llvm::DebugInfoFinder DIF; const auto *Mod = IRDB.getModule(); @@ -207,6 +212,7 @@ findAllFunctionDefs(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { FnDefs.push_back(IRDB.getFunction(SubProgram->getLinkageName())); } } + DIF.reset(); if (FnDefs.empty()) { @@ -227,53 +233,69 @@ findAllFunctionDefs(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { return FnDefs; } -DIBasedTypeHierarchy::DIBasedTypeHierarchy( - const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedCG) { - for (const auto &Curr : SerializedCG.NameToType) { - NameToType.try_emplace(Curr.first(), Curr.second); - } - +static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, + const llvm::StringRef DITypeName) { llvm::DebugInfoFinder DIF; - const auto *Mod = IRDB->getModule(); - DIF.processModule(*Mod); + const auto *Module = IRDB->getModule(); + DIF.processModule(*Module); - for (const auto &Curr : SerializedCG.TypeToVertex) { - llvm::SmallVector FnDefs; - for (const auto &SubProgram : DIF.subprograms()) { - if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && - (SubProgram->getName() == Curr.getFirst() || - SubProgram->getLinkageName() == Curr.getFirst())) { - FnDefs.push_back(IRDB->getFunction(SubProgram->getLinkageName())); + for (const auto &SubProgram : DIF.subprograms()) { + if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && + (SubProgram->getName() == DITypeName || + SubProgram->getLinkageName() == DITypeName)) { + if (const auto *DIT = llvm::dyn_cast(SubProgram)) { + return DIT; } - } - - DIF.reset(); - FnDefs = findAllFunctionDefs(*IRDB, Curr.getFirst()); - if (FnDefs.empty()) { - llvm::errs() << "WARNING: Cannot retrieve function " << Curr.getFirst() - << "\n"; - continue; + llvm::report_fatal_error("Subprogram with DITypeName isn't a DIType"); } - - const auto *Fun = FnDefs[0]; - TypeToVertex.try_emplace(Fun, Curr.getSecond()); } - for (const auto &Curr : SerializedCG.VertexTypes) { - VertexTypes.emplace_back(Curr); + llvm::report_fatal_error("DIType doesn't exist"); +} + +static const llvm::Function * +stringToFunction(const LLVMProjectIRDB *IRDB, + const llvm::StringRef FunctionName) { + if (const auto *Func = llvm::dyn_cast( + psr::fromMetaDataId(*IRDB, FunctionName))) { + return Func; } - for (const auto &Curr : SerializedCG.TransitiveDerivedIndex) { - TransitiveDerivedIndex.emplace_back(Curr); + llvm::report_fatal_error("Function doesn't exist"); +} + +DIBasedTypeHierarchy::DIBasedTypeHierarchy( + const LLVMProjectIRDB *IRDB, + const DIBasedTypeHierarchyData &SerializedData) { + for (const auto &Curr : SerializedData.NameToType) { + NameToType.try_emplace(Curr.getKey(), + stringToDIType(IRDB, Curr.getValue())); + } + /// TODO: + /* + for (const auto &Curr : SerializedData.TypeToVertex) { + TypeToVertex.try_emplace(stringToDIType(IRDB, Curr.getFirst()), + Curr.getSecond()); + } + */ + for (const auto &Curr : SerializedData.TransitiveDerivedIndex) { + TransitiveDerivedIndex.emplace_back( + std::pair(Curr.first, Curr.second)); } - for (const auto &Curr : SerializedCG.Hierarchy) { - Hierarchy.emplace_back(); + for (const auto &Curr : SerializedData.Hierarchy) { + Hierarchy.push_back(stringToDIType(IRDB, Curr)); } - for (const auto &Curr : SerializedCG.VTables) { - VTables.emplace_back(); + for (const auto &Curr : SerializedData.VTables) { + LLVMVFTable CurrVTable; + + for (const auto &FuncName : Curr) { + CurrVTable.VFT.push_back(stringToFunction(IRDB, FuncName)); + } + + VTables.push_back(CurrVTable); } } @@ -350,17 +372,18 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; for (const auto &Curr : NameToType) { - Data.NameToType.try_emplace(Curr.getKey(), - Curr.getValue()->getMetadataID()); - } - - for (const auto &Curr : TypeToVertex) { - Data.TypeToVertex.try_emplace(Curr.getFirst()->getName().str(), - Curr.getSecond()); + Data.NameToType.try_emplace(Curr.getKey().str(), + Curr.getValue()->getName().str()); } - + /// TODO: + /* + for (const auto &Curr : TypeToVertex) { + Data.TypeToVertex.try_emplace(Curr.getFirst()->getName().str(), + Curr.getSecond()); + } + */ for (const auto &Curr : VertexTypes) { - Data.VertexTypes.push_back(Curr->getMetadataID()); + Data.VertexTypes.push_back(Curr->getName().str()); } for (const auto &Curr : TransitiveDerivedIndex) { @@ -380,7 +403,7 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { CurrVTableAsString.push_back(Func->getName().str()); } - Data.VTables.emplace_back(std::move(CurrVTableAsString)); + Data.VTables.push_back(std::move(CurrVTableAsString)); } return Data; diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index abdabde6c..9d9741242 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -14,6 +14,8 @@ #include "llvm/ADT/StringRef.h" +#include + namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { @@ -26,10 +28,12 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { } // TypeToVertex - for (const auto &[Key, Value] : - Json["TypeToVertex"].get()) { - Data.TypeToVertex.try_emplace(Key, Value); - } + // Data.TypeToVertex.reserve( + // Json["TypeToVertex"].get().size()); + // for (const auto &[Key, Value] : + // Json["TypeToVertex"].get()) { + // Data.TypeToVertex.try_emplace(Key, Value); + //} // VertexTypes for (const auto &Value : Json["VertexTypes"]) { @@ -39,17 +43,25 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { // TransitiveDerivedIndex for (const auto &[First, Second] : Json["TransitiveDerivedIndex"].get()) { - Data.TransitiveDerivedIndex.emplace_back(First, Second); + // Data.TransitiveDerivedIndex.emplace_back(First, Second); } // Hierarchy for (const auto &Value : Json["Hierarchy"]) { Data.Hierarchy.push_back(Value); } // VTables + /// TODO: Fabian fragen, wie ich hier am besten mit der deque arbeiten soll + int Counter = 0; for (const auto &CurrVTable : Json["VTables"]) { + Data.VTables.emplace_back(std::vector()); + + std::string NameOfCurrentVTable = std::to_string(Counter); + for (const auto &CurrVFunc : CurrVTable) { - /// TODO: find out how to deserialize this + Data.VTables[Counter].push_back(CurrVFunc); } + + Counter++; } return Data; @@ -62,9 +74,9 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { JSON["NameToType"][Curr.first()] = Curr.second; } - for (const auto &Curr : TypeToVertex) { - JSON["TypeToVertex"][Curr.first] = Curr.second; - } + // for (const auto &Curr : TypeToVertex) { + // JSON["TypeToVertex"][Curr.first] = Curr.second; + // } for (const auto &Curr : VertexTypes) { JSON["VertexTypes"].push_back(Curr); @@ -78,8 +90,15 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { JSON["Hierarchy"].push_back(Curr); } + int Counter = 0; for (const auto &CurrVTable : VTables) { - JSON["VTables"].push_back(CurrVTable); + std::string NameForVTable = std::to_string(Counter); + + for (const auto &CurrVFunc : CurrVTable) { + JSON["VTables"][NameForVTable].push_back(CurrVFunc); + } + + Counter++; } OS << JSON; From 751366f79d916d033802cd3e658d53875fdebe29 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 29 Mar 2024 19:13:59 +0100 Subject: [PATCH 14/42] fixed DIBTHData TypeToVertex not compiling --- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 6 +++-- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 26 +++++++++---------- .../DIBasedTypeHierarchyData.cpp | 8 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index 991b39fdb..9019e3e47 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -10,12 +10,12 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHYDATA_H #define PHASAR_PHASARLLVM_TYPEHIERARCHY_DIBASEDTYPEHIERARCHYDATA_H -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/raw_ostream.h" #include #include +#include namespace psr { struct DIBasedTypeHierarchyData { @@ -27,7 +27,9 @@ struct DIBasedTypeHierarchyData { llvm::StringMap NameToType; // llvm::DenseMap TypeToVertex // using ClassType = const llvm::DIType * - /// TODO: llvm::DenseMap TypeToVertex; + // Note: Using DenseMap creates an error, therefore I've + // resorted to using a StringMap + llvm::StringMap TypeToVertex; // std::vector VertexTypes std::vector VertexTypes; // std::vector> TransitiveDerivedIndex diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index eb1a1e963..43bc6e57a 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -272,13 +272,12 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( NameToType.try_emplace(Curr.getKey(), stringToDIType(IRDB, Curr.getValue())); } - /// TODO: - /* - for (const auto &Curr : SerializedData.TypeToVertex) { - TypeToVertex.try_emplace(stringToDIType(IRDB, Curr.getFirst()), - Curr.getSecond()); - } - */ + + 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)); @@ -375,13 +374,12 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { Data.NameToType.try_emplace(Curr.getKey().str(), Curr.getValue()->getName().str()); } - /// TODO: - /* - for (const auto &Curr : TypeToVertex) { - Data.TypeToVertex.try_emplace(Curr.getFirst()->getName().str(), - Curr.getSecond()); - } - */ + + for (const auto &Curr : TypeToVertex) { + Data.TypeToVertex.try_emplace(Curr.getFirst()->getName().str(), + Curr.getSecond()); + } + for (const auto &Curr : VertexTypes) { Data.VertexTypes.push_back(Curr->getName().str()); } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index 9d9741242..e1c36ea73 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -30,10 +30,10 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { // TypeToVertex // Data.TypeToVertex.reserve( // Json["TypeToVertex"].get().size()); - // for (const auto &[Key, Value] : - // Json["TypeToVertex"].get()) { - // Data.TypeToVertex.try_emplace(Key, Value); - //} + for (const auto &[Key, Value] : + Json["TypeToVertex"].get()) { + Data.TypeToVertex.try_emplace(Key, Value); + } // VertexTypes for (const auto &Value : Json["VertexTypes"]) { From 6e37cd36f79dd737687e8c9542b649ee10edd083 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 3 Apr 2024 15:31:16 +0200 Subject: [PATCH 15/42] fixed serialization bugs and unittests --- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 15 +--- lib/ControlFlow/CallGraphData.cpp | 5 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 77 ++++++++----------- .../DIBasedTypeHierarchyData.cpp | 61 ++++++--------- .../PhasarLLVM/TypeHierarchy/CMakeLists.txt | 1 + .../DIBasedTypeHierarchySerializationTest.cpp | 24 +++++- 6 files changed, 82 insertions(+), 101 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index 9019e3e47..ff352b917 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -22,25 +22,12 @@ struct DIBasedTypeHierarchyData { // DITypes and llvm::Function * are serialized by serializing their names and // using the DebugInfoFinder to deserialize them - // llvm::StringMap NameToType - // using ClassType = const llvm::DIType * llvm::StringMap NameToType; - // llvm::DenseMap TypeToVertex - // using ClassType = const llvm::DIType * - // Note: Using DenseMap creates an error, therefore I've - // resorted to using a StringMap llvm::StringMap TypeToVertex; - // std::vector VertexTypes std::vector VertexTypes; - // std::vector> TransitiveDerivedIndex std::vector> TransitiveDerivedIndex; - // std::vector Hierarchy - // using ClassType = const llvm::DIType * std::vector Hierarchy; - // std::deque VTables - // Relevant data of LLVMVFTable: - // std::vector VFT; - std::deque> VTables; + std::vector> VTables; DIBasedTypeHierarchyData() noexcept = default; void printAsJson(llvm::raw_ostream &OS); diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index e7b59ba65..638976b25 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -19,10 +19,11 @@ static CallGraphData getDataFromJson(const nlohmann::json &Json) { // map F to vector of n_t's for (const auto &[FVal, FunctionVertexTyVals] : Json.get()) { - ToReturn.FToFunctionVertexTy.reserve(FunctionVertexTyVals.size()); + auto &FValMappedVector = ToReturn.FToFunctionVertexTy[FVal]; + FValMappedVector.reserve(FunctionVertexTyVals.size()); for (const auto &Curr : FunctionVertexTyVals) { - ToReturn.FToFunctionVertexTy[FVal].push_back(Curr); + FValMappedVector.push_back(Curr.get()); } } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 43bc6e57a..f7c1340ef 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -196,41 +196,24 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { buildTypeHierarchy(TG, VertexTypes, TransitiveDerivedIndex, Hierarchy); } -static llvm::SmallVector -findAllDITypes(const LLVMProjectIRDB &IRDB, llvm::StringRef Name) { - /// TODO: umschreiben, so dass diese Funktion alle DITypes mithilfe des Debug - /// Info Finders findet - llvm::SmallVector FnDefs; +static const llvm::DICompositeType * +stringToDICompositeType(const LLVMProjectIRDB *IRDB, + const llvm::StringRef DITypeName) { llvm::DebugInfoFinder DIF; - const auto *Mod = IRDB.getModule(); - - DIF.processModule(*Mod); - for (const auto &SubProgram : DIF.subprograms()) { - if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && - (SubProgram->getName() == Name || - SubProgram->getLinkageName() == Name)) { - FnDefs.push_back(IRDB.getFunction(SubProgram->getLinkageName())); - } - } - - DIF.reset(); + const auto *Module = IRDB->getModule(); + DIF.processModule(*Module); - if (FnDefs.empty()) { - const auto *F = IRDB.getFunction(Name); - if (F) { - FnDefs.push_back(F); - } - } else if (FnDefs.size() > 1) { - llvm::errs() << "The function name '" << Name - << "' is ambiguous. Possible candidates are:\n"; - for (const auto *F : FnDefs) { - llvm::errs() << "> " << F->getName() << "\n"; + for (const auto &Type : DIF.types()) { + if (Type) { + if (Type->getName() == DITypeName) { + if (const auto *DICT = llvm::dyn_cast(Type)) { + return DICT; + } + } } - llvm::errs() << "Please further specify the function's name, such that it " - "becomes unambiguous\n"; } - return FnDefs; + llvm::report_fatal_error("DIType doesn't exist"); } static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, @@ -239,15 +222,13 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, const auto *Module = IRDB->getModule(); DIF.processModule(*Module); - for (const auto &SubProgram : DIF.subprograms()) { - if (SubProgram->isDistinct() && !SubProgram->getLinkageName().empty() && - (SubProgram->getName() == DITypeName || - SubProgram->getLinkageName() == DITypeName)) { - if (const auto *DIT = llvm::dyn_cast(SubProgram)) { - return DIT; + for (const auto &Type : DIF.types()) { + if (Type) { + if (Type->getName() == DITypeName) { + if (const auto *DIT = llvm::dyn_cast(Type)) { + return DIT; + } } - - llvm::report_fatal_error("Subprogram with DITypeName isn't a DIType"); } } @@ -257,17 +238,21 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, static const llvm::Function * stringToFunction(const LLVMProjectIRDB *IRDB, const llvm::StringRef FunctionName) { - if (const auto *Func = llvm::dyn_cast( - psr::fromMetaDataId(*IRDB, FunctionName))) { + if (const auto *Func = IRDB->getFunction(FunctionName)) { return Func; } - llvm::report_fatal_error("Function doesn't exist"); + llvm::errs() << "Function " << FunctionName << " doesn't exist"; + return nullptr; } DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) { + for (const auto &Curr : SerializedData.VertexTypes) { + VertexTypes.push_back(stringToDICompositeType(IRDB, Curr)); + } + for (const auto &Curr : SerializedData.NameToType) { NameToType.try_emplace(Curr.getKey(), stringToDIType(IRDB, Curr.getValue())); @@ -288,13 +273,13 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( } for (const auto &Curr : SerializedData.VTables) { - LLVMVFTable CurrVTable; + LLVMVFTable CurrVTable = LLVMVFTable(); for (const auto &FuncName : Curr) { CurrVTable.VFT.push_back(stringToFunction(IRDB, FuncName)); } - VTables.push_back(CurrVTable); + VTables.push_back(std::move(CurrVTable)); } } @@ -398,7 +383,11 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { CurrVTableAsString.reserve(Curr.getAllFunctions().size()); for (const auto &Func : Curr.getAllFunctions()) { - CurrVTableAsString.push_back(Func->getName().str()); + if (Func) { + CurrVTableAsString.push_back(Func->getName().str()); + continue; + } + CurrVTableAsString.emplace_back("Null"); } Data.VTables.push_back(std::move(CurrVTableAsString)); diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index e1c36ea73..b9af3e0eb 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -14,54 +14,44 @@ #include "llvm/ADT/StringRef.h" +#include #include +#include namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { DIBasedTypeHierarchyData Data; - // NameToType for (const auto &[Key, Value] : Json["NameToType"].get()) { - Data.NameToType.try_emplace(Key, Value); + Data.NameToType.try_emplace(Key, Value.get()); } - // TypeToVertex - // Data.TypeToVertex.reserve( - // Json["TypeToVertex"].get().size()); for (const auto &[Key, Value] : Json["TypeToVertex"].get()) { - Data.TypeToVertex.try_emplace(Key, Value); + Data.TypeToVertex.try_emplace(Key, Value.get()); } - // VertexTypes for (const auto &Value : Json["VertexTypes"]) { - Data.VertexTypes.push_back(Value); + Data.VertexTypes.push_back(Value.get()); } - // TransitiveDerivedIndex - for (const auto &[First, Second] : - Json["TransitiveDerivedIndex"].get()) { - // Data.TransitiveDerivedIndex.emplace_back(First, Second); + for (const auto &CurrPair : Json["TransitiveDerivedIndex"]) { + Data.TransitiveDerivedIndex.emplace_back(CurrPair[0].get(), + CurrPair[1].get()); } - // Hierarchy + for (const auto &Value : Json["Hierarchy"]) { - Data.Hierarchy.push_back(Value); + Data.Hierarchy.push_back(Value.get()); } - // VTables - /// TODO: Fabian fragen, wie ich hier am besten mit der deque arbeiten soll - int Counter = 0; - for (const auto &CurrVTable : Json["VTables"]) { - Data.VTables.emplace_back(std::vector()); - std::string NameOfCurrentVTable = std::to_string(Counter); + for (const auto &CurrVTable : Json["VTables"]) { + auto &Test = Data.VTables.emplace_back(); for (const auto &CurrVFunc : CurrVTable) { - Data.VTables[Counter].push_back(CurrVFunc); + Test.push_back(CurrVFunc.get()); } - - Counter++; } return Data; @@ -71,34 +61,32 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json JSON; for (const auto &Curr : NameToType) { - JSON["NameToType"][Curr.first()] = Curr.second; + JSON["NameToType"][Curr.getKey()] = Curr.getValue(); } - // for (const auto &Curr : TypeToVertex) { - // JSON["TypeToVertex"][Curr.first] = Curr.second; - // } + for (const auto &Curr : TypeToVertex) { + JSON["TypeToVertex"][Curr.getKey()] = Curr.getValue(); + } for (const auto &Curr : VertexTypes) { JSON["VertexTypes"].push_back(Curr); } + /// TODO: geschachteltes Array verwenden, statt Counter + int Number = 0; for (const auto &Curr : TransitiveDerivedIndex) { - JSON["TransitiveDerivedIndex"][Curr.first] = Curr.second; + JSON["TransitiveDerivedIndex"][Number].push_back(Curr.first); + JSON["TransitiveDerivedIndex"][Number++].push_back(Curr.second); } for (const auto &Curr : Hierarchy) { JSON["Hierarchy"].push_back(Curr); } - int Counter = 0; for (const auto &CurrVTable : VTables) { - std::string NameForVTable = std::to_string(Counter); - for (const auto &CurrVFunc : CurrVTable) { - JSON["VTables"][NameForVTable].push_back(CurrVFunc); + JSON["VTables"].push_back(CurrVFunc); } - - Counter++; } OS << JSON; @@ -111,10 +99,9 @@ DIBasedTypeHierarchyData::deserializeJson(const llvm::Twine &Path) { DIBasedTypeHierarchyData DIBasedTypeHierarchyData::loadJsonString(llvm::StringRef JsonAsString) { - // nlohmann::json::parse needs a std::string, llvm::Twine won't work - nlohmann::json ToStringify = + nlohmann::json Data = nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); - return getDataFromJson(ToStringify); + return getDataFromJson(Data); } } // namespace psr diff --git a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt index 512574c25..2432ec447 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt +++ b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt @@ -1,4 +1,5 @@ set(PointerSources + DIBasedTypeHierarchySerializationTest.cpp DIBasedTypeHierarchyTest.cpp LLVMTypeHierarchyTest.cpp TypeGraphTest.cpp diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 863ad5067..4bc9f5f58 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -29,15 +29,19 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, for (const auto &OrigCurrentType : Orig.getAllTypes()) { EXPECT_EQ(OrigCurrentType, Deser.getType(OrigCurrentType->getName().str())); - EXPECT_EQ(Orig.getVFTable(OrigCurrentType), - Deser.getVFTable(OrigCurrentType)); + + for (const auto &CurrVFunc : + Orig.getVFTable(OrigCurrentType)->getAllFunctions()) { + EXPECT_TRUE(Deser.getVFTable(OrigCurrentType) + ->getFunction(CurrVFunc->getValueID())); + } } } TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { using namespace std::string_literals; - psr::LLVMProjectIRDB IRDB(psr::unittest::PathToLLTestFiles + GetParam()); + psr::LLVMProjectIRDB IRDB(PathToLlFiles + GetParam()); psr::DIBasedTypeHierarchy DIBTH(IRDB); std::string Ser; @@ -53,7 +57,19 @@ TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { } static constexpr std::string_view TypeHierarchyTestFiles[] = { - "type_hierarchy_1_cpp_dbg.ll", "type_hierarchy_2_cpp_dbg.ll"}; + "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(TypeHierarchySerializationTest, TypeHierarchySerialization, From 8708a76d76b25e350910035ff5a66358bf536c91 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 4 Apr 2024 11:25:49 +0200 Subject: [PATCH 16/42] DITHS Test fixes, 13 pass, 11 fail --- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 2 +- .../DIBasedTypeHierarchyData.cpp | 8 ++++--- .../DIBasedTypeHierarchySerializationTest.cpp | 22 ++++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index f7c1340ef..a2143eaac 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -242,7 +242,7 @@ stringToFunction(const LLVMProjectIRDB *IRDB, return Func; } - llvm::errs() << "Function " << FunctionName << " doesn't exist"; + llvm::errs() << "Function " << FunctionName << " doesn't exist\n"; return nullptr; } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index b9af3e0eb..e3056a75b 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -47,10 +47,10 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { } for (const auto &CurrVTable : Json["VTables"]) { - auto &Test = Data.VTables.emplace_back(); + auto &DataPos = Data.VTables.emplace_back(); for (const auto &CurrVFunc : CurrVTable) { - Test.push_back(CurrVFunc.get()); + DataPos.push_back(CurrVFunc.get()); } } @@ -84,8 +84,10 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { } for (const auto &CurrVTable : VTables) { + auto &DataPos = JSON["VTables"].emplace_back(); + for (const auto &CurrVFunc : CurrVTable) { - JSON["VTables"].push_back(CurrVFunc); + DataPos.push_back(CurrVFunc); } } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 4bc9f5f58..0a57d72d3 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -32,8 +32,19 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, for (const auto &CurrVFunc : Orig.getVFTable(OrigCurrentType)->getAllFunctions()) { - EXPECT_TRUE(Deser.getVFTable(OrigCurrentType) - ->getFunction(CurrVFunc->getValueID())); + bool FoundFunction = false; + for (const auto &DeserFunc : + Deser.getVFTable(OrigCurrentType)->getAllFunctions()) { + if (DeserFunc) { + if (CurrVFunc) { + if (DeserFunc->getName() == CurrVFunc->getName()) { + FoundFunction = true; + break; + } + } + } + } + EXPECT_TRUE(FoundFunction); } } } @@ -45,7 +56,6 @@ TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { psr::DIBasedTypeHierarchy DIBTH(IRDB); std::string Ser; - // stream data into a json file using the printAsJson() function llvm::raw_string_ostream StringStream(Ser); DIBTH.printAsJson(StringStream); @@ -54,6 +64,12 @@ TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); compareResults(DIBTH, DeserializedDIBTH); + /* + DIBTH.printAsJson(); + llvm::outs() << "\n----------------------------\n"; + llvm::outs() << Ser << "\n----------------------------\n"; + llvm::outs().flush(); + */ } static constexpr std::string_view TypeHierarchyTestFiles[] = { From 50d966a23e6ae4644d9729fc62c6badcc439ec3a Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 4 Apr 2024 17:51:01 +0200 Subject: [PATCH 17/42] DIBTH Ser Test, 1 failing Test left --- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 14 +++++++++- .../DIBasedTypeHierarchyData.cpp | 8 ++++++ .../DIBasedTypeHierarchySerializationTest.cpp | 26 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index a2143eaac..cf9f1fc3a 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -242,16 +242,24 @@ stringToFunction(const LLVMProjectIRDB *IRDB, return Func; } - llvm::errs() << "Function " << FunctionName << " doesn't exist\n"; return nullptr; } DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) { + llvm::outs() << "Size: " << SerializedData.VertexTypes.size() << "\n"; + llvm::outs().flush(); + + int Counter = 0; + VertexTypes.reserve(SerializedData.VertexTypes.size()); for (const auto &Curr : SerializedData.VertexTypes) { VertexTypes.push_back(stringToDICompositeType(IRDB, Curr)); + Counter++; } + llvm::outs() << "Constr: " << Counter << "\n"; + llvm::outs() << "VertexTypes: " << VertexTypes.size() << "\n"; + llvm::outs().flush(); for (const auto &Curr : SerializedData.NameToType) { NameToType.try_emplace(Curr.getKey(), @@ -365,9 +373,13 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { Curr.getSecond()); } + int Counter = 0; for (const auto &Curr : VertexTypes) { Data.VertexTypes.push_back(Curr->getName().str()); + Counter++; } + llvm::outs() << Counter << "\n"; + llvm::outs().flush(); for (const auto &Curr : TransitiveDerivedIndex) { Data.TransitiveDerivedIndex.emplace_back( diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index e3056a75b..69bd0a4ed 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -33,9 +33,13 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { Data.TypeToVertex.try_emplace(Key, Value.get()); } + int Counter = 0; for (const auto &Value : Json["VertexTypes"]) { Data.VertexTypes.push_back(Value.get()); + Counter++; } + llvm::outs() << "DIBTH getDataFromJson: " << Counter << "\n"; + llvm::outs().flush(); for (const auto &CurrPair : Json["TransitiveDerivedIndex"]) { Data.TransitiveDerivedIndex.emplace_back(CurrPair[0].get(), @@ -68,9 +72,13 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { JSON["TypeToVertex"][Curr.getKey()] = Curr.getValue(); } + int Counter = 0; for (const auto &Curr : VertexTypes) { JSON["VertexTypes"].push_back(Curr); + Counter++; } + llvm::outs() << "DIBTHData: " << Counter << "\n"; + llvm::outs().flush(); /// TODO: geschachteltes Array verwenden, statt Counter int Number = 0; diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 0a57d72d3..862ae41b0 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -24,6 +24,26 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { + llvm::outs() << "----------------------------------\n"; + llvm::outs() << "--------Orig.getAllTypes()--------\n"; + llvm::outs() << "----------------------------------\n"; + llvm::outs().flush(); + int Counter = 0; + for (const auto &Curr : Orig.getAllTypes()) { + llvm::outs() << Counter++ << ": " << Curr->getName() << "\n"; + llvm::outs().flush(); + } + + llvm::outs() << "----------------------------------\n"; + llvm::outs() << "-------Deser.getAllTypes()--------\n"; + llvm::outs() << "----------------------------------\n"; + llvm::outs().flush(); + + Counter = 0; + for (const auto &Curr : Deser.getAllTypes()) { + llvm::outs() << Counter++ << ": " << Curr->getName() << "\n"; + llvm::outs().flush(); + } ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); @@ -42,6 +62,12 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, break; } } + } else { + // This case is for a function that has no caller + if (!CurrVFunc) { + FoundFunction = true; + break; + } } } EXPECT_TRUE(FoundFunction); From 9d81f4e962df631f230b91d7bb7ba202d5da8b08 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 5 Apr 2024 21:30:04 +0200 Subject: [PATCH 18/42] GeneralStatisticsAnalysisData impl --- .../Passes/GeneralStatisticsAnalysisData.h | 73 +++++++++ .../Passes/GeneralStatisticsAnalysis.cpp | 32 +++- .../Passes/GeneralStatisticsAnalysisData.cpp | 138 ++++++++++++++++++ .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 24 +-- .../DIBasedTypeHierarchySerializationTest.cpp | 20 --- 5 files changed, 248 insertions(+), 39 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h create mode 100644 lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h new file mode 100644 index 000000000..fa4c18df7 --- /dev/null +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H +#define PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H + +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include + +namespace psr { +struct GeneralStatisticsAnalysisData { + 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; + std::string ModuleName{}; + + GeneralStatisticsAnalysisData() noexcept = default; + void printAsJson(llvm::raw_ostream &OS); + + static GeneralStatisticsAnalysisData deserializeJson(const llvm::Twine &Path); + static GeneralStatisticsAnalysisData + loadJsonString(llvm::StringRef JsonAsString); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index e853bf724..67ab2dca5 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -9,9 +9,9 @@ #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" +#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" -#include "phasar/Utils/NlohmannLogging.h" #include "phasar/Utils/PAMMMacros.h" #include "llvm/IR/CFG.h" @@ -288,8 +288,36 @@ 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 { - OS << getAsJson() << '\n'; + GeneralStatisticsAnalysisData Data; + Data.printAsJson(OS); } nlohmann::json GeneralStatistics::getAsJson() const { diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp new file mode 100644 index 000000000..2adad5aba --- /dev/null +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisData.cpp @@ -0,0 +1,138 @@ +/****************************************************************************** + * 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/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index cf9f1fc3a..d65e9dc82 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -204,11 +204,9 @@ stringToDICompositeType(const LLVMProjectIRDB *IRDB, DIF.processModule(*Module); for (const auto &Type : DIF.types()) { - if (Type) { - if (Type->getName() == DITypeName) { - if (const auto *DICT = llvm::dyn_cast(Type)) { - return DICT; - } + if (Type->getName() == DITypeName) { + if (const auto *DICT = llvm::dyn_cast(Type)) { + return DICT; } } } @@ -235,16 +233,6 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, llvm::report_fatal_error("DIType doesn't exist"); } -static const llvm::Function * -stringToFunction(const LLVMProjectIRDB *IRDB, - const llvm::StringRef FunctionName) { - if (const auto *Func = IRDB->getFunction(FunctionName)) { - return Func; - } - - return nullptr; -} - DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) { @@ -253,10 +241,12 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( int Counter = 0; VertexTypes.reserve(SerializedData.VertexTypes.size()); + for (const auto &Curr : SerializedData.VertexTypes) { VertexTypes.push_back(stringToDICompositeType(IRDB, Curr)); Counter++; } + llvm::outs() << "Constr: " << Counter << "\n"; llvm::outs() << "VertexTypes: " << VertexTypes.size() << "\n"; llvm::outs().flush(); @@ -284,7 +274,7 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( LLVMVFTable CurrVTable = LLVMVFTable(); for (const auto &FuncName : Curr) { - CurrVTable.VFT.push_back(stringToFunction(IRDB, FuncName)); + CurrVTable.VFT.push_back(IRDB->getFunction(FuncName)); } VTables.push_back(std::move(CurrVTable)); @@ -378,7 +368,7 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { Data.VertexTypes.push_back(Curr->getName().str()); Counter++; } - llvm::outs() << Counter << "\n"; + llvm::outs() << "getTypeHierarchyData: " << Counter << "\n"; llvm::outs().flush(); for (const auto &Curr : TransitiveDerivedIndex) { diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 862ae41b0..871055034 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -24,26 +24,6 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { - llvm::outs() << "----------------------------------\n"; - llvm::outs() << "--------Orig.getAllTypes()--------\n"; - llvm::outs() << "----------------------------------\n"; - llvm::outs().flush(); - int Counter = 0; - for (const auto &Curr : Orig.getAllTypes()) { - llvm::outs() << Counter++ << ": " << Curr->getName() << "\n"; - llvm::outs().flush(); - } - - llvm::outs() << "----------------------------------\n"; - llvm::outs() << "-------Deser.getAllTypes()--------\n"; - llvm::outs() << "----------------------------------\n"; - llvm::outs().flush(); - - Counter = 0; - for (const auto &Curr : Deser.getAllTypes()) { - llvm::outs() << Counter++ << ": " << Curr->getName() << "\n"; - llvm::outs().flush(); - } ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); From 643da4be1c258b7e59bf12ae1b4b69ea96125ace Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sat, 6 Apr 2024 10:18:15 +0200 Subject: [PATCH 19/42] LLVMAliasSetData impl --- .../phasar/PhasarLLVM/Pointer/LLVMAliasSet.h | 7 ++- .../PhasarLLVM/Pointer/LLVMAliasSetData.h | 32 +++++++++++ lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp | 31 +++++++++- lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp | 56 +++++++++++++++++++ 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h create mode 100644 lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h index 4e7ff668e..55c150df7 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_POINTER_LLVMALIASSET_H #define PHASAR_PHASARLLVM_POINTER_LLVMALIASSET_H +#include "phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h" #include "phasar/PhasarLLVM/Pointer/LLVMBasedAliasAnalysis.h" #include "phasar/Pointer/AliasInfoBase.h" #include "phasar/Pointer/AliasInfoTraits.h" @@ -95,7 +96,11 @@ class LLVMAliasSet : public AnalysisPropertiesMixin, void print(llvm::raw_ostream &OS = llvm::outs()) const; - [[nodiscard]] [[deprecated("Please use printAsJson() instead")]] nlohmann::json getAsJson() const; + [[nodiscard]] [[deprecated( + "Please use printAsJson() instead")]] nlohmann::json + getAsJson() const; + + [[nodiscard]] LLVMAliasSetData getLLVMAliasSetData() const; void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const; diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h new file mode 100644 index 000000000..41c52eb81 --- /dev/null +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasSetData.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMALIASSETDATA_H +#define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMALIASSETDATA_H + +#include "llvm/Support/raw_ostream.h" + +#include + +namespace psr { +struct LLVMAliasSetData { + // AliasSets + std::vector AliasSets; + std::vector AnalyzedFunctions; + + LLVMAliasSetData() noexcept = default; + void printAsJson(llvm::raw_ostream &OS); + + static LLVMAliasSetData deserializeJson(const llvm::Twine &Path); + static LLVMAliasSetData loadJsonString(llvm::StringRef JsonAsString); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMALIASSETDATA_H diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp index 83e796b6b..850c7cec6 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -723,8 +723,37 @@ nlohmann::json LLVMAliasSet::getAsJson() const { return J; } +LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { + LLVMAliasSetData Data; + + /// Serialize the AliasSets + auto &Sets = Data.AliasSets; + + for (const AliasSetTy *PTS : Owner.getAllAliasSets()) { + auto PtsJson = nlohmann::json::array(); + for (const auto *Alias : *PTS) { + auto Id = getMetaDataID(Alias); + if (Id != "-1") { + PtsJson.push_back(std::move(Id)); + } + } + if (!PtsJson.empty()) { + Sets.push_back(std::move(PtsJson)); + } + } + + /// Serialize the AnalyzedFunctions + auto &Fns = Data.AnalyzedFunctions; + for (const auto *F : AnalyzedFunctions) { + Fns.push_back(F->getName().str()); + } + + return Data; +} + void LLVMAliasSet::printAsJson(llvm::raw_ostream &OS) const { - OS << getAsJson(); + LLVMAliasSetData Data = getLLVMAliasSetData(); + Data.printAsJson(OS); } void LLVMAliasSet::print(llvm::raw_ostream &OS) const { diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp new file mode 100644 index 000000000..37c4280b0 --- /dev/null +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp @@ -0,0 +1,56 @@ +/****************************************************************************** + * 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/Pointer/LLVMAliasSetData.h" + +#include "phasar/Utils/IO.h" +#include "phasar/Utils/NlohmannLogging.h" + +namespace psr { + +static LLVMAliasSetData getDataFromJson(const nlohmann::json &Json) { + LLVMAliasSetData Data; + + for (const auto &Value : Json["AliasSets"]) { + Data.AliasSets.push_back(Value.get()); + } + + for (const auto &Value : Json["AnalyzedFunctions"]) { + Data.AnalyzedFunctions.push_back(Value.get()); + } + + return Data; +} + +void LLVMAliasSetData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json JSON; + + for (const auto &Curr : AliasSets) { + JSON["AliasSets"].push_back(Curr); + } + + for (const auto &Curr : AnalyzedFunctions) { + JSON["AnalyzedFunctions"].push_back(Curr); + } + + OS << JSON; +} + +LLVMAliasSetData LLVMAliasSetData::deserializeJson(const llvm::Twine &Path) { + return getDataFromJson(readJsonFile(Path)); +} + +LLVMAliasSetData +LLVMAliasSetData::loadJsonString(llvm::StringRef JsonAsString) { + nlohmann::json Data = + nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); + return getDataFromJson(Data); +} + +} // namespace psr From 7f79712fa2d246f5c05507f8da23885be6c77c0a Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 8 Apr 2024 22:10:25 +0200 Subject: [PATCH 20/42] last printAsJson Impls --- .../TypeHierarchy/DIBasedTypeHierarchy.h | 4 +- .../TypeHierarchy/LLVMTypeHierarchy.h | 3 + .../TypeHierarchy/LLVMTypeHierarchyData.h | 32 ++++++++++ .../PhasarLLVM/TypeHierarchy/LLVMVFTable.h | 7 ++- .../TypeHierarchy/LLVMVFTableData.h | 30 ++++++++++ .../DIBasedTypeHierarchyData.cpp | 18 +++--- .../TypeHierarchy/LLVMTypeHierarchy.cpp | 31 +++++++++- .../TypeHierarchy/LLVMTypeHierarchyData.cpp | 60 +++++++++++++++++++ lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp | 16 ++++- .../TypeHierarchy/LLVMVFTableData.cpp | 47 +++++++++++++++ 10 files changed, 234 insertions(+), 14 deletions(-) create mode 100644 include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h create mode 100644 include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h create mode 100644 lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp create mode 100644 lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index 4c73b5f02..c6efe7310 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -96,7 +96,9 @@ class DIBasedTypeHierarchy */ void printAsDot(llvm::raw_ostream &OS = llvm::outs()) const; - [[nodiscard]] nlohmann::json getAsJson() const override; + [[nodiscard]] [[deprecated( + "Please use printAsJson() instead")]] nlohmann::json + getAsJson() const override; /** * @brief Prints the class hierarchy to an ostream in json format. diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index 21191b183..d3f4b0b8e 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -17,6 +17,7 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMTYPEHIERARCHY_H_ #define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMTYPEHIERARCHY_H_ +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h" #include "phasar/TypeHierarchy/TypeHierarchy.h" @@ -205,6 +206,8 @@ class LLVMTypeHierarchy void print(llvm::raw_ostream &OS = llvm::outs()) const override; + LLVMTypeHierarchyData getTypeHierarchyData() const; + [[nodiscard]] [[deprecated( "Please use printAsJson() instead")]] nlohmann::json getAsJson() const override; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h new file mode 100644 index 000000000..b93ebe65e --- /dev/null +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMTYPEHIERARCHYDATA_H_ +#define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMTYPEHIERARCHYDATA_H_ + +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/raw_ostream.h" + +#include + +namespace psr { +struct LLVMTypeHierarchyData { + std::string PhasarConfigJsonTypeHierarchyID; + llvm::StringMap> TypeGraph; + + LLVMTypeHierarchyData() noexcept = default; + void printAsJson(llvm::raw_ostream &OS); + + static LLVMTypeHierarchyData deserializeJson(const llvm::Twine &Path); + static LLVMTypeHierarchyData loadJsonString(llvm::StringRef JsonAsString); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMTYPEHIERARCHYDATA_H_ diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h index 82981f7a4..4f505d91b 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h @@ -10,6 +10,7 @@ #ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLE_H_ #define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLE_H_ +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h" #include "phasar/TypeHierarchy/VFTable.h" #include "nlohmann/json.hpp" @@ -66,7 +67,11 @@ class LLVMVFTable : public VFTable { void print(llvm::raw_ostream &OS) const override; - [[nodiscard]] nlohmann::json getAsJson() const override; + [[nodiscard]] [[deprecated( + "Please use printAsJson() instead")]] nlohmann::json + getAsJson() const override; + + [[nodiscard]] LLVMVFTableData getVFTableData() const; void printAsJson(llvm::raw_ostream &OS) const override; diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h new file mode 100644 index 000000000..66360c248 --- /dev/null +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h @@ -0,0 +1,30 @@ +/****************************************************************************** + * 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 + *****************************************************************************/ + +#ifndef PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLEDATA_H_ +#define PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLEDATA_H_ + +#include "llvm/Support/raw_ostream.h" + +#include + +namespace psr { +struct LLVMVFTableData { + std::vector VFT; + + LLVMVFTableData() noexcept = default; + void printAsJson(llvm::raw_ostream &OS); + + static LLVMVFTableData deserializeJson(const llvm::Twine &Path); + static LLVMVFTableData loadJsonString(llvm::StringRef JsonAsString); +}; + +} // namespace psr + +#endif // PHASAR_PHASARLLVM_TYPEHIERARCHY_LLVMVFTABLEDATA_H_ diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index 69bd0a4ed..fa2d17d16 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -62,19 +62,19 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { } void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { - nlohmann::json JSON; + nlohmann::json Json; for (const auto &Curr : NameToType) { - JSON["NameToType"][Curr.getKey()] = Curr.getValue(); + Json["NameToType"][Curr.getKey()] = Curr.getValue(); } for (const auto &Curr : TypeToVertex) { - JSON["TypeToVertex"][Curr.getKey()] = Curr.getValue(); + Json["TypeToVertex"][Curr.getKey()] = Curr.getValue(); } int Counter = 0; for (const auto &Curr : VertexTypes) { - JSON["VertexTypes"].push_back(Curr); + Json["VertexTypes"].push_back(Curr); Counter++; } llvm::outs() << "DIBTHData: " << Counter << "\n"; @@ -83,23 +83,23 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { /// TODO: geschachteltes Array verwenden, statt Counter int Number = 0; for (const auto &Curr : TransitiveDerivedIndex) { - JSON["TransitiveDerivedIndex"][Number].push_back(Curr.first); - JSON["TransitiveDerivedIndex"][Number++].push_back(Curr.second); + Json["TransitiveDerivedIndex"][Number].push_back(Curr.first); + Json["TransitiveDerivedIndex"][Number++].push_back(Curr.second); } for (const auto &Curr : Hierarchy) { - JSON["Hierarchy"].push_back(Curr); + Json["Hierarchy"].push_back(Curr); } for (const auto &CurrVTable : VTables) { - auto &DataPos = JSON["VTables"].emplace_back(); + auto &DataPos = Json["VTables"].emplace_back(); for (const auto &CurrVFunc : CurrVTable) { DataPos.push_back(CurrVFunc); } } - OS << JSON; + OS << Json; } DIBasedTypeHierarchyData diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp index bc2e32534..7ae3efc60 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp @@ -401,8 +401,37 @@ void LLVMTypeHierarchy::printAsDot(llvm::raw_ostream &OS) const { OS << S.str(); } +LLVMTypeHierarchyData LLVMTypeHierarchy::getTypeHierarchyData() const { + LLVMTypeHierarchyData Data; + + /// TODO: + + return Data; +} + void LLVMTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { - OS << getAsJson(); + LLVMTypeHierarchyData Data = getTypeHierarchyData(); + Data.PhasarConfigJsonTypeHierarchyID = + PhasarConfig::JsonTypeHierarchyID().str(); + + vertex_iterator VIv; + vertex_iterator VIvEnd; + out_edge_iterator EI; + + out_edge_iterator EIEnd; + // iterate all graph vertices + for (boost::tie(VIv, VIvEnd) = boost::vertices(TypeGraph); VIv != VIvEnd; + ++VIv) { + Data.TypeGraph[TypeGraph[*VIv].getTypeName()]; + // iterate all out edges of vertex vi_v + for (boost::tie(EI, EIEnd) = boost::out_edges(*VIv, TypeGraph); EI != EIEnd; + ++EI) { + Data.TypeGraph[TypeGraph[*VIv].getTypeName()].push_back( + TypeGraph[boost::target(*EI, TypeGraph)].getTypeName()); + } + } + + Data.printAsJson(OS); } // void LLVMTypeHierarchy::printGraphAsDot(ostream &out) { diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp new file mode 100644 index 000000000..2408fdf1a --- /dev/null +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp @@ -0,0 +1,60 @@ +/****************************************************************************** + * 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/TypeHierarchy/LLVMTypeHierarchyData.h" + +#include "phasar/Utils/IO.h" +#include "phasar/Utils/NlohmannLogging.h" + +namespace psr { + +static LLVMTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { + LLVMTypeHierarchyData Data; + + for (const auto &CurrOuterType : Json[Data.PhasarConfigJsonTypeHierarchyID]) { + Data.TypeGraph.try_emplace(CurrOuterType.get(), + std::vector{}); + + for (const auto &CurrInnerType : CurrOuterType) { + Data.TypeGraph[CurrOuterType.get()].push_back( + CurrInnerType.get()); + } + } + + return Data; +} + +void LLVMTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json Json; + + for (const auto &Curr : TypeGraph) { + auto &DataPos = + Json[PhasarConfigJsonTypeHierarchyID][Curr.getKey()].emplace_back(); + + for (const auto &CurrTypeName : Curr.getValue()) { + DataPos.push_back(CurrTypeName); + } + } + + OS << Json; +} + +LLVMTypeHierarchyData +LLVMTypeHierarchyData::deserializeJson(const llvm::Twine &Path) { + return getDataFromJson(readJsonFile(Path)); +} + +LLVMTypeHierarchyData +LLVMTypeHierarchyData::loadJsonString(llvm::StringRef JsonAsString) { + nlohmann::json Data = + nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); + return getDataFromJson(Data); +} + +} // namespace psr diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp index ced61d660..547c69a10 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp @@ -8,6 +8,8 @@ *****************************************************************************/ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h" + +#include "phasar/PhasarLLVM/TypeHierarchy/LLVMVFTableData.h" #include "phasar/Utils/NlohmannLogging.h" #include "llvm/IR/Function.h" @@ -50,9 +52,19 @@ nlohmann::json LLVMVFTable::getAsJson() const { return J; } +[[nodiscard]] LLVMVFTableData LLVMVFTable::getVFTableData() const { + LLVMVFTableData Data; + + for (const auto &Curr : VFT) { + Data.VFT.push_back(Curr->getName().str()); + } + + return Data; +} + void LLVMVFTable::printAsJson(llvm::raw_ostream &OS) const { - nlohmann::json Json = "{}"_json; - OS << Json; + LLVMVFTableData Data = getVFTableData(); + Data.printAsJson(OS); } std::vector diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp new file mode 100644 index 000000000..272500dda --- /dev/null +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * 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/TypeHierarchy/LLVMVFTableData.h" + +#include "phasar/Utils/IO.h" +#include "phasar/Utils/NlohmannLogging.h" + +namespace psr { + +static LLVMVFTableData getDataFromJson(const nlohmann::json &Json) { + LLVMVFTableData Data; + + for (const auto &Curr : Json["VFT"]) { + Data.VFT.push_back(Curr); + } + + return Data; +} + +void LLVMVFTableData::printAsJson(llvm::raw_ostream &OS) { + nlohmann::json JSON; + + for (const auto &Curr : VFT) { + JSON["VFT"].push_back(Curr); + } + + OS << JSON; +} + +LLVMVFTableData LLVMVFTableData::deserializeJson(const llvm::Twine &Path) { + return getDataFromJson(readJsonFile(Path)); +} + +LLVMVFTableData LLVMVFTableData::loadJsonString(llvm::StringRef JsonAsString) { + nlohmann::json Data = + nlohmann::json::parse(JsonAsString.begin(), JsonAsString.end()); + return getDataFromJson(Data); +} + +} // namespace psr From a347b7d63d1c20116b150ebd0af5f9214190ebbe Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 10 Apr 2024 12:27:32 +0200 Subject: [PATCH 21/42] 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; +} From b4c8ff3b846d2f015e69114ea6f1bac1c6ee787d Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 10 Apr 2024 22:37:16 +0200 Subject: [PATCH 22/42] changes + fixes from meeting --- .../TypeHierarchy/LLVMTypeHierarchyData.cpp | 21 +++++++++++++------ .../LLVMTypeHierarchySerializationTest.cpp | 6 ++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp index 2408fdf1a..9aea8a7c5 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp @@ -16,14 +16,21 @@ namespace psr { static LLVMTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { LLVMTypeHierarchyData Data; + Data.PhasarConfigJsonTypeHierarchyID = + Json["PhasarConfigJsonTypeHierarchyID"]; - for (const auto &CurrOuterType : Json[Data.PhasarConfigJsonTypeHierarchyID]) { - Data.TypeGraph.try_emplace(CurrOuterType.get(), - std::vector{}); + llvm::outs() << "Before array :" + << "\n"; + llvm::outs().flush(); + for (const auto &[Key, ValueArray] : + Json[Data.PhasarConfigJsonTypeHierarchyID] + .get()) { + Data.TypeGraph.try_emplace(Key, std::vector{}); + llvm::outs() << "Key :" << Key << "\n"; + llvm::outs().flush(); - for (const auto &CurrInnerType : CurrOuterType) { - Data.TypeGraph[CurrOuterType.get()].push_back( - CurrInnerType.get()); + for (const auto &CurrInnerType : ValueArray) { + Data.TypeGraph[Key].push_back(CurrInnerType.get()); } } @@ -33,6 +40,8 @@ static LLVMTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { void LLVMTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json Json; + Json["PhasarConfigJsonTypeHierarchyID"] = PhasarConfigJsonTypeHierarchyID; + for (const auto &Curr : TypeGraph) { auto &DataPos = Json[PhasarConfigJsonTypeHierarchyID][Curr.getKey()].emplace_back(); diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index 3b3c424e6..e835a18fc 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -65,12 +65,18 @@ TEST_P(LLVMTypeHierarchySerialization, OrigAndDeserEqual) { std::string Ser; llvm::raw_string_ostream StringStream(Ser); + llvm::outs() << "before print\n"; TypeHierarchy.printAsJson(StringStream); + llvm::outs() << Ser << "\n"; + + llvm::outs() << "before DeserializedTypeHierarchy\n"; psr::LLVMTypeHierarchy DeserializedTypeHierarchy( IRDB, psr::LLVMTypeHierarchyData::loadJsonString(Ser)); + llvm::outs() << "before compareResults\n"; compareResults(TypeHierarchy, DeserializedTypeHierarchy); + llvm::outs() << "before after\n"; } static constexpr std::string_view TypeHierarchyTestFiles[] = { From c8359613fab4e7fe2510a9cc819ba997917c4f13 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 11 Apr 2024 23:31:27 +0200 Subject: [PATCH 23/42] no equality of values DIBTH Test --- include/phasar/Pointer/AliasInfo.h | 6 +++++- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 14 ++++--------- .../TypeHierarchy/LLVMTypeHierarchyData.cpp | 5 ----- .../DIBasedTypeHierarchySerializationTest.cpp | 21 ++++++++++++------- .../LLVMTypeHierarchySerializationTest.cpp | 13 ++++++------ 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index ba9fa480f..576a7b529 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -22,6 +22,7 @@ #include "llvm/Support/raw_ostream.h" #include "nlohmann/json.hpp" +#include "nlohmann/json_fwd.hpp" #include #include @@ -141,7 +142,10 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { } [[nodiscard]] nlohmann::json getAsJson() const { - assert(VT != nullptr); + if (VT == nullptr) { + return {}; + } + return VT->GetAsJson(AA); } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index e1b4934d7..125cf47f5 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -176,6 +176,10 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { for (const auto *Ty : DIF.types()) { if (const auto *Composite = llvm::dyn_cast(Ty)) { + /// TODO: find a way to add an empty Entry + if (Composite->getTag() == llvm::dwarf::DW_TAG_array_type) { + continue; + } TypeToVertex.try_emplace(Composite, VertexTypes.size()); VertexTypes.push_back(Composite); NameToType.try_emplace(Composite->getName(), Composite); @@ -240,8 +244,6 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) { - llvm::outs() << "Size: " << SerializedData.VertexTypes.size() << "\n"; - llvm::outs().flush(); int Counter = 0; VertexTypes.reserve(SerializedData.VertexTypes.size()); @@ -251,10 +253,6 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( Counter++; } - llvm::outs() << "Constr: " << Counter << "\n"; - llvm::outs() << "VertexTypes: " << VertexTypes.size() << "\n"; - llvm::outs().flush(); - for (const auto &Curr : SerializedData.NameToType) { NameToType.try_emplace(Curr.getKey(), stringToDIType(IRDB, Curr.getValue())); @@ -376,22 +374,18 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { 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(); for (const auto &Curr : TransitiveDerivedIndex) { Data.TransitiveDerivedIndex.emplace_back( diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp index 9aea8a7c5..1d3ad892c 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp @@ -19,15 +19,10 @@ static LLVMTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { Data.PhasarConfigJsonTypeHierarchyID = Json["PhasarConfigJsonTypeHierarchyID"]; - llvm::outs() << "Before array :" - << "\n"; - llvm::outs().flush(); for (const auto &[Key, ValueArray] : Json[Data.PhasarConfigJsonTypeHierarchyID] .get()) { Data.TypeGraph.try_emplace(Key, std::vector{}); - llvm::outs() << "Key :" << Key << "\n"; - llvm::outs().flush(); for (const auto &CurrInnerType : ValueArray) { Data.TypeGraph[Key].push_back(CurrInnerType.get()); diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 4a5c132ef..4a8db0d5c 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -25,6 +25,16 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { + std::vector OrigAllTypes(Orig.getAllTypes().begin(), + Orig.getAllTypes().end()); + std::vector DeserAllTypes( + Deser.getAllTypes().begin(), Deser.getAllTypes().end()); + for (int Index = 0; Index < Orig.getAllTypes().size(); Index++) { + llvm::outs() << "| " << *(OrigAllTypes.begin() + Index) << " - " + << *(DeserAllTypes.begin() + Index) << " |\n"; + llvm::outs().flush(); + } + /* llvm::outs() << "Original\n"; for (const auto &Curr : Orig.getAllTypes()) { Curr->print(llvm::outs()); @@ -38,9 +48,10 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, } 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())); + EXPECT_EQ(OrigCurrentType->getName(), + Deser.getType(OrigCurrentType->getName().str())->getName()); for (const auto &CurrVFunc : Orig.getVFTable(OrigCurrentType)->getAllFunctions()) { @@ -82,12 +93,6 @@ TEST_P(TypeHierarchySerialization, OrigAndDeserEqual) { &IRDB, psr::DIBasedTypeHierarchyData::loadJsonString(Ser)); compareResults(DIBTH, DeserializedDIBTH); - /* - DIBTH.printAsJson(); - llvm::outs() << "\n----------------------------\n"; - llvm::outs() << Ser << "\n----------------------------\n"; - llvm::outs().flush(); - */ } static constexpr std::string_view TypeHierarchyTestFiles[] = { diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index e835a18fc..1b85dbc64 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -7,6 +7,7 @@ #include "phasar/Utils/Utilities.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/DerivedTypes.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -65,18 +66,18 @@ TEST_P(LLVMTypeHierarchySerialization, OrigAndDeserEqual) { std::string Ser; llvm::raw_string_ostream StringStream(Ser); - llvm::outs() << "before print\n"; - TypeHierarchy.printAsJson(StringStream); + // llvm::outs() << "before print\n"; + // TypeHierarchy.printAsJson(StringStream); - llvm::outs() << Ser << "\n"; + // llvm::outs() << Ser << "\n"; - llvm::outs() << "before DeserializedTypeHierarchy\n"; + // llvm::outs() << "before DeserializedTypeHierarchy\n"; psr::LLVMTypeHierarchy DeserializedTypeHierarchy( IRDB, psr::LLVMTypeHierarchyData::loadJsonString(Ser)); - llvm::outs() << "before compareResults\n"; + // llvm::outs() << "before compareResults\n"; compareResults(TypeHierarchy, DeserializedTypeHierarchy); - llvm::outs() << "before after\n"; + // llvm::outs() << "before after\n"; } static constexpr std::string_view TypeHierarchyTestFiles[] = { From 7f6194e563611233cfe7cb3e1afd9e73ab0b45f4 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 12 Apr 2024 10:29:55 +0200 Subject: [PATCH 24/42] fixed all bugs, all unittests pass --- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 1 - .../DIBasedTypeHierarchyData.cpp | 5 --- .../TypeHierarchy/LLVMTypeHierarchyData.cpp | 4 ++- .../DIBasedTypeHierarchySerializationTest.cpp | 24 +------------- .../LLVMTypeHierarchySerializationTest.cpp | 31 +------------------ 5 files changed, 5 insertions(+), 60 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 125cf47f5..4a5e3b14e 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -176,7 +176,6 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { for (const auto *Ty : DIF.types()) { if (const auto *Composite = llvm::dyn_cast(Ty)) { - /// TODO: find a way to add an empty Entry if (Composite->getTag() == llvm::dwarf::DW_TAG_array_type) { continue; } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index fa2d17d16..b7eef8f8c 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -38,8 +38,6 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { Data.VertexTypes.push_back(Value.get()); Counter++; } - llvm::outs() << "DIBTH getDataFromJson: " << Counter << "\n"; - llvm::outs().flush(); for (const auto &CurrPair : Json["TransitiveDerivedIndex"]) { Data.TransitiveDerivedIndex.emplace_back(CurrPair[0].get(), @@ -77,10 +75,7 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { Json["VertexTypes"].push_back(Curr); Counter++; } - llvm::outs() << "DIBTHData: " << Counter << "\n"; - llvm::outs().flush(); - /// TODO: geschachteltes Array verwenden, statt Counter int Number = 0; for (const auto &Curr : TransitiveDerivedIndex) { Json["TransitiveDerivedIndex"][Number].push_back(Curr.first); diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp index 1d3ad892c..450481e06 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp @@ -25,7 +25,9 @@ static LLVMTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { Data.TypeGraph.try_emplace(Key, std::vector{}); for (const auto &CurrInnerType : ValueArray) { - Data.TypeGraph[Key].push_back(CurrInnerType.get()); + for (const auto &CurrString : CurrInnerType) { + Data.TypeGraph[Key].push_back(CurrString.get()); + } } } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 4a8db0d5c..cd41fa5f7 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -24,31 +24,9 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { - - std::vector OrigAllTypes(Orig.getAllTypes().begin(), - Orig.getAllTypes().end()); - std::vector DeserAllTypes( - Deser.getAllTypes().begin(), Deser.getAllTypes().end()); - for (int Index = 0; Index < Orig.getAllTypes().size(); Index++) { - llvm::outs() << "| " << *(OrigAllTypes.begin() + Index) << " - " - << *(DeserAllTypes.begin() + Index) << " |\n"; - llvm::outs().flush(); - } - /* - 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()); -*/ + for (const auto &OrigCurrentType : Orig.getAllTypes()) { EXPECT_EQ(OrigCurrentType->getName(), Deser.getType(OrigCurrentType->getName().str())->getName()); diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index 1b85dbc64..b5862a27c 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -31,29 +31,6 @@ void compareResults(const psr::LLVMTypeHierarchy &Orig, 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); - } } } @@ -66,18 +43,12 @@ TEST_P(LLVMTypeHierarchySerialization, OrigAndDeserEqual) { std::string Ser; llvm::raw_string_ostream StringStream(Ser); - // llvm::outs() << "before print\n"; - // TypeHierarchy.printAsJson(StringStream); - - // llvm::outs() << Ser << "\n"; + TypeHierarchy.printAsJson(StringStream); - // llvm::outs() << "before DeserializedTypeHierarchy\n"; psr::LLVMTypeHierarchy DeserializedTypeHierarchy( IRDB, psr::LLVMTypeHierarchyData::loadJsonString(Ser)); - // llvm::outs() << "before compareResults\n"; compareResults(TypeHierarchy, DeserializedTypeHierarchy); - // llvm::outs() << "before after\n"; } static constexpr std::string_view TypeHierarchyTestFiles[] = { From 16bbf2a8982c3b97e78f18a18f77328453412e35 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 15 Apr 2024 18:10:53 +0200 Subject: [PATCH 25/42] Fix crash in buildTypeGraph in the presence of typedefs --- lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 4a5e3b14e..eb43cacfd 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -110,8 +110,13 @@ buildTypeGraph(llvm::ArrayRef VertexTypes, if (const auto *Inheritenace = llvm::dyn_cast(Fld); Inheritenace && Inheritenace->getTag() == llvm::dwarf::DW_TAG_inheritance) { - auto BaseIdx = TypeToVertex.lookup(Inheritenace->getBaseType()); - assert(BaseIdx != 0 || VertexTypes[0] == Inheritenace->getBaseType()); + const auto *Base = Inheritenace->getBaseType(); + while (Base->getTag() == llvm::dwarf::DW_TAG_typedef) { + Base = llvm::cast(Base)->getBaseType(); + } + + auto BaseIdx = TypeToVertex.lookup(Base); + assert(BaseIdx != 0 || VertexTypes[0] == Base); TG.DerivedTypesOf[BaseIdx].push_back(DerivedIdx); TG.Roots.reset(DerivedIdx); From 47bf183848e9abca1fad973439e936ced90b4bbf Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 17 Apr 2024 09:17:52 +0200 Subject: [PATCH 26/42] fixed LLVMAliasSetSerializationTest --- lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp | 3 +-- .../Pointer/LLVMAliasSetSerializationTest.cpp | 10 ---------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp index 3fad1896d..d211ee2d0 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -727,8 +727,6 @@ LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { LLVMAliasSetData Data; /// Serialize the AliasSets - auto &AliasSetsDataPosition = Data.AliasSets.emplace_back(); - for (const AliasSetTy *PTS : Owner.getAllAliasSets()) { std::vector PtsJson{}; @@ -739,6 +737,7 @@ LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { } } if (!PtsJson.empty()) { + auto &AliasSetsDataPosition = Data.AliasSets.emplace_back(); for (const auto &Curr : PtsJson) { AliasSetsDataPosition.push_back(Curr); } diff --git a/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp b/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp index 17d94c767..431c82218 100644 --- a/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp +++ b/unittests/PhasarLLVM/Pointer/LLVMAliasSetSerializationTest.cpp @@ -39,7 +39,6 @@ static SetTy makeSet(const nlohmann::json &J) { } static void checkSer(const nlohmann::json &Ser, const GroundTruthTy &Gt) { - ASSERT_TRUE(Ser.count("AliasSets")); ASSERT_TRUE(Ser.count("AnalyzedFunctions")); @@ -77,20 +76,11 @@ static void analyze(llvm::StringRef File, const GroundTruthTy &Gt, ValueAnnotationPass::resetValueID(); LLVMProjectIRDB IRDB(unittest::PathToLLTestFiles + File); - // llvm::outs() << *IRDB.getWPAModule() << '\n'; - LLVMAliasSet PTS(&IRDB, false); LLVMTypeHierarchy TH(IRDB); LLVMBasedICFG ICF(&IRDB, CallGraphAnalysisType::OTF, {EntryPoint.str()}, &TH, &PTS); - auto Ser = PTS.getAsJson(); - checkSer(Ser, Gt); - - LLVMAliasSet Deser(&IRDB, Ser); - checkDeser(*IRDB.getModule(), PTS, Deser); - - // printAsJson serialization std::string SerString; llvm::raw_string_ostream StringStream(SerString); PTS.printAsJson(StringStream); From 767a90e3ee568f24598851e05110070170aca17d Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 18:15:23 +0200 Subject: [PATCH 27/42] Add more aggressive composite type filter --- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 24 ++++++++++--------- .../DIBasedTypeHierarchySerializationTest.cpp | 5 ++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index eb43cacfd..86b0e0e44 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -179,9 +179,16 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { // -- Filter all struct- or class types + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays) + static constexpr llvm::dwarf::Tag DwarfTags[] = { + llvm::dwarf::DW_TAG_class_type, + llvm::dwarf::DW_TAG_structure_type, + llvm::dwarf::DW_TAG_union_type, + }; + for (const auto *Ty : DIF.types()) { if (const auto *Composite = llvm::dyn_cast(Ty)) { - if (Composite->getTag() == llvm::dwarf::DW_TAG_array_type) { + if (!llvm::is_contained(DwarfTags, Composite->getTag())) { continue; } TypeToVertex.try_emplace(Composite, VertexTypes.size()); @@ -359,16 +366,15 @@ DIBasedTypeHierarchy::getAsJson() const { DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; for (const auto &Curr : NameToType) { - Data.NameToType.try_emplace(Curr.getKey().str(), + Data.NameToType.try_emplace(Curr.getKey(), Curr.getValue()->getName().str()); } for (const auto &Curr : TypeToVertex) { - Data.TypeToVertex.try_emplace(Curr.getFirst()->getName().str(), - Curr.getSecond()); + Data.TypeToVertex.try_emplace(Curr.getFirst()->getName(), Curr.getSecond()); } - int Counter = 0; + Data.VertexTypes.reserve(VertexTypes.size()); for (const auto &Curr : VertexTypes) { if (!Curr) { Data.VertexTypes.emplace_back(""); @@ -377,13 +383,11 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { if (!Curr->getName().empty()) { Data.VertexTypes.push_back(Curr->getName().str()); - Counter++; continue; } if (!Curr->getIdentifier().empty()) { Data.VertexTypes.push_back(Curr->getIdentifier().str()); - Counter++; continue; } @@ -391,11 +395,9 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { llvm::errs() << "VertexType has no valid name or identifier\n"; } - for (const auto &Curr : TransitiveDerivedIndex) { - Data.TransitiveDerivedIndex.emplace_back( - std::pair(Curr.first, Curr.second)); - } + Data.TransitiveDerivedIndex = TransitiveDerivedIndex; + Data.Hierarchy.reserve(Hierarchy.size()); for (const auto &Curr : Hierarchy) { Data.Hierarchy.push_back(Curr->getName().str()); } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index cd41fa5f7..86d706bc4 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -24,8 +24,9 @@ class TypeHierarchySerialization void compareResults(const psr::DIBasedTypeHierarchy &Orig, const psr::DIBasedTypeHierarchy &Deser) { - ASSERT_EQ(Orig.getAllTypes().size(), Deser.getAllTypes().size()); - ASSERT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); + + 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(), From fe605e90b46849c8a6457f50886be23e77f67dcf Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 19:01:19 +0200 Subject: [PATCH 28/42] 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()) { From 53e222eef4660354e7bba8b40c257b86d837736d Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 19:25:14 +0200 Subject: [PATCH 29/42] Implicit vertex index --- .../TypeHierarchy/DIBasedTypeHierarchyData.h | 2 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 32 ++++++++++++------- .../DIBasedTypeHierarchyData.cpp | 11 ++----- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h index 93672e59a..52cd85569 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.h @@ -22,7 +22,7 @@ struct DIBasedTypeHierarchyData { // DITypes and llvm::Function * are serialized by serializing their names and // using the DebugInfoFinder to deserialize them - 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 82b0550c6..46a4e39fc 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -259,17 +259,23 @@ static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, llvm::report_fatal_error("DIType doesn't exist"); } +// NOLINTNEXTLINE +static constexpr char NullFunName[] = "__null__"; + DIBasedTypeHierarchy::DIBasedTypeHierarchy( 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) { - const auto *Ty = stringToDICompositeType(IRDB, Curr.getKey()); - TypeToVertex.try_emplace(Ty, Curr.getValue()); - NameToType.try_emplace(Curr.getKey(), Ty); - VertexTypes.at(Curr.getValue()) = Ty; + VertexTypes.reserve(SerializedData.VertexTypes.size()); + TypeToVertex.reserve(SerializedData.VertexTypes.size()); + size_t Idx = 0; + for (const auto &Curr : SerializedData.VertexTypes) { + const auto *Ty = stringToDICompositeType(IRDB, Curr); + VertexTypes.push_back(Ty); + TypeToVertex.try_emplace(Ty, Idx); + NameToType.try_emplace(Curr, Ty); + + ++Idx; } Hierarchy.reserve(SerializedData.Hierarchy.size()); @@ -282,6 +288,9 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( CurrVTable.reserve(Curr.size()); for (const auto &FuncName : Curr) { + if (FuncName == NullFunName) { + CurrVTable.push_back(nullptr); + } CurrVTable.push_back(IRDB->getFunction(FuncName)); } @@ -368,9 +377,10 @@ DIBasedTypeHierarchy::getAsJson() const { DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { DIBasedTypeHierarchyData Data; - for (const auto &Curr : TypeToVertex) { - Data.TypeToVertex.try_emplace(getTypeName(Curr.getFirst()), - Curr.getSecond()); + Data.VertexTypes.reserve(VertexTypes.size()); + + for (const auto &Curr : VertexTypes) { + Data.VertexTypes.push_back(getTypeName(Curr)); } Data.TransitiveDerivedIndex = TransitiveDerivedIndex; @@ -389,7 +399,7 @@ DIBasedTypeHierarchyData DIBasedTypeHierarchy::getTypeHierarchyData() const { CurrVTableAsString.push_back(Func->getName().str()); continue; } - CurrVTableAsString.emplace_back("Null"); + CurrVTableAsString.emplace_back(NullFunName); } Data.VTables.push_back(std::move(CurrVTableAsString)); diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index 0d6ae0701..43eef1c64 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -23,9 +23,7 @@ namespace psr { static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { DIBasedTypeHierarchyData Data; - for (const auto &[Key, Value] : Json["TypeToVertex"].items()) { - Data.TypeToVertex.try_emplace(Key, Value.get()); - } + Data.VertexTypes = Json["VertexTypes"].get>(); Data.TransitiveDerivedIndex = Json["TransitiveDerivedIndex"] @@ -47,13 +45,8 @@ static DIBasedTypeHierarchyData getDataFromJson(const nlohmann::json &Json) { void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { nlohmann::json Json; - auto &JTypeToVertex = Json["TypeToVertex"]; - for (const auto &Curr : TypeToVertex) { - JTypeToVertex[Curr.getKey()] = Curr.getValue(); - } - + Json["VertexTypes"] = VertexTypes; Json["TransitiveDerivedIndex"] = TransitiveDerivedIndex; - Json["Hierarchy"] = Hierarchy; auto &JVTables = Json["VTables"]; From e4d289200ef5ba55ad80323d8e2d2b21077ba88b Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 20:04:19 +0200 Subject: [PATCH 30/42] Prioritize type id over type name as the latter may be ambiguous --- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 19 ++++++++++--------- .../DIBasedTypeHierarchySerializationTest.cpp | 10 +++++++--- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 46a4e39fc..7fa166eaa 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -166,8 +166,8 @@ static void buildTypeHierarchy( } static llvm::StringRef getCompositeTypeName(const llvm::DICompositeType *Ty) { - auto Name = Ty->getName(); - return Name.empty() ? Ty->getIdentifier() : Name; + auto Ident = Ty->getIdentifier(); + return Ident.empty() ? Ty->getName() : Ident; } DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { @@ -196,11 +196,12 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { if (!llvm::is_contained(DwarfTags, Composite->getTag())) { continue; } - TypeToVertex.try_emplace(Composite, VertexTypes.size()); - VertexTypes.push_back(Composite); - NameToType.try_emplace(getCompositeTypeName(Composite), Composite); + if (TypeToVertex.try_emplace(Composite, VertexTypes.size()).second) { + VertexTypes.push_back(Composite); + NameToType.try_emplace(getCompositeTypeName(Composite), Composite); - assert(!getCompositeTypeName(Composite).empty()); + assert(!getCompositeTypeName(Composite).empty()); + } } } @@ -227,11 +228,11 @@ stringToDICompositeType(const LLVMProjectIRDB *IRDB, for (const auto *Type : DIF.types()) { if (const auto *DICT = llvm::dyn_cast(Type)) { - if (DICT->getName() == DITypeName) { + auto Ident = DICT->getIdentifier(); + if (Ident == DITypeName) { return DICT; } - - if (DICT->getIdentifier() == DITypeName) { + if (Ident.empty() && DICT->getName() == DITypeName) { return DICT; } } diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 1816a753e..57d0e50af 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -31,9 +31,13 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, 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); + EXPECT_EQ(OrigCurrentType, DeserTy); + + if (OrigCurrentType != DeserTy) { + llvm::errs() << "Mismatched types:\n> OrigTy: " << *OrigCurrentType + << '\n'; + llvm::errs() << "> DeserTy: " << *DeserTy << '\n'; + } for (const auto &CurrVFunc : Orig.getVFTable(OrigCurrentType)->getAllFunctions()) { From 7d3641c3c84b4c789719702253e0f70fc1f8d58c Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 20 Apr 2024 20:48:17 +0200 Subject: [PATCH 31/42] Adapt DI TH test to identifiers as names --- .../DIBasedTypeHierarchyTest.cpp | 300 +++++++++--------- 1 file changed, 150 insertions(+), 150 deletions(-) diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp index 5b97f15e8..3205863a3 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp @@ -24,9 +24,9 @@ TEST(DBTHTest, BasicTHReconstruction_1) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -44,9 +44,9 @@ TEST(DBTHTest, BasicTHReconstruction_2) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -64,9 +64,9 @@ TEST(DBTHTest, BasicTHReconstruction_3) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -84,9 +84,9 @@ TEST(DBTHTest, BasicTHReconstruction_4) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -104,11 +104,11 @@ TEST(DBTHTest, BasicTHReconstruction_5) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 3U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); + const auto &OtherBaseType = DBTH.getType("_ZTS9OtherBase"); ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -129,9 +129,9 @@ TEST(DBTHTest, BasicTHReconstruction_6) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -149,19 +149,19 @@ TEST(DBTHTest, BasicTHReconstruction_7) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 7U); - const auto &AType = DBTH.getType("A"); + const auto &AType = DBTH.getType("_ZTS1A"); ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); + const auto &BType = DBTH.getType("_ZTS1B"); ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); + const auto &DType = DBTH.getType("_ZTS1D"); ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); + const auto &XType = DBTH.getType("_ZTS1X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); EXPECT_TRUE(DBTH.hasType(AType)); @@ -202,15 +202,15 @@ TEST(DBTHTest, BasicTHReconstruction_7_b) { EXPECT_EQ(DBTH.getAllTypes().size(), 6U); const auto &AType = DBTH.getType("A"); ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); const auto &XType = DBTH.getType("X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); + const auto &OmegaType = DBTH.getType("_ZTS5Omega"); ASSERT_NE(nullptr, OmegaType); EXPECT_TRUE(DBTH.hasType(AType)); @@ -247,13 +247,13 @@ TEST(DBTHTest, BasicTHReconstruction_8) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 4U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + const auto &NonvirtualClassType = DBTH.getType("_ZTS15NonvirtualClass"); EXPECT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + const auto &NonvirtualStructType = DBTH.getType("_ZTS16NonvirtualStruct"); EXPECT_NE(nullptr, NonvirtualStructType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -273,9 +273,9 @@ TEST(DBTHTest, BasicTHReconstruction_9) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -293,9 +293,9 @@ TEST(DBTHTest, BasicTHReconstruction_10) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -313,9 +313,9 @@ TEST(DBTHTest, BasicTHReconstruction_11) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -333,9 +333,9 @@ TEST(DBTHTest, BasicTHReconstruction_12) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 2U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -357,7 +357,7 @@ TEST(DBTHTest, BasicTHReconstruction_12_b) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -380,7 +380,7 @@ TEST(DBTHTest, BasicTHReconstruction_12_c) { EXPECT_EQ(DBTH.getAllTypes().size(), 2U); const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); EXPECT_TRUE(DBTH.hasType(ChildType)); @@ -439,16 +439,16 @@ TEST(DBTHTest, BasicTHReconstruction_16) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // Since ChildsChild is never used, it is optimized out // const auto &ChildsChildType = DBTH.getType("ChildsChild"); // ASSERT_EQ(nullptr, ChildsChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); + const auto &BaseTwoType = DBTH.getType("_ZTS7BaseTwo"); ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); + const auto &ChildTwoType = DBTH.getType("_ZTS8ChildTwo"); ASSERT_NE(nullptr, ChildTwoType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -475,16 +475,16 @@ TEST(DBTHTest, BasicTHReconstruction_17) { // check for all types // EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // const auto &Child2Type = DBTH.getType("Child2"); // Since Child2Type is never used, it is optimized out // ASSERT_EQ(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); + const auto &KidType = DBTH.getType("_ZTS3Kid"); ASSERT_NE(nullptr, KidType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -511,14 +511,14 @@ TEST(DBTHTest, BasicTHReconstruction_18) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 4U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // const auto &Child_2Type = DBTH.getType("Child_2"); // Since Child2Type is never used, it is optimized out // ASSERT_EQ(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); + const auto &Child3Type = DBTH.getType("_ZTS7Child_3"); ASSERT_NE(nullptr, Child3Type); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -544,17 +544,17 @@ TEST(DBTHTest, BasicTHReconstruction_19) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 6U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); + const auto &FooType = DBTH.getType("_ZTS3Foo"); ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); + const auto &BarType = DBTH.getType("_ZTS3Bar"); ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); + const auto &LoremType = DBTH.getType("_ZTS5Lorem"); ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); + const auto &ImpsumType = DBTH.getType("_ZTS6Impsum"); ASSERT_NE(nullptr, ImpsumType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -580,11 +580,11 @@ TEST(DBTHTest, BasicTHReconstruction_20) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 3U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -605,15 +605,15 @@ TEST(DBTHTest, BasicTHReconstruction_21) { // check for all types EXPECT_EQ(DBTH.getAllTypes().size(), 5U); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); + const auto &Base3Type = DBTH.getType("_ZTS5Base3"); ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); + const auto &Child2Type = DBTH.getType("_ZTS6Child2"); ASSERT_NE(nullptr, Child2Type); EXPECT_TRUE(DBTH.hasType(BaseType)); @@ -645,9 +645,9 @@ TEST(DBTHTest, VTableConstruction_1) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); ASSERT_TRUE(DBTH.hasVFTable(BaseType)); @@ -670,9 +670,9 @@ TEST(DBTHTest, VTableConstruction_2) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); ASSERT_TRUE(DBTH.hasVFTable(BaseType)); @@ -695,9 +695,9 @@ TEST(DBTHTest, VTableConstruction_3) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); ASSERT_TRUE(DBTH.hasVFTable(BaseType)); @@ -722,9 +722,9 @@ TEST(DBTHTest, VTableConstruction_4) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); ASSERT_TRUE(DBTH.hasVFTable(BaseType)); @@ -752,11 +752,11 @@ TEST(DBTHTest, VTableConstruction_5) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); + const auto &OtherBaseType = DBTH.getType("_ZTS9OtherBase"); ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); ASSERT_TRUE(DBTH.hasVFTable(BaseType)); @@ -792,9 +792,9 @@ TEST(DBTHTest, VTableConstruction_6) { "type_hierarchies/type_hierarchy_6_cpp_dbg.ll"); DIBasedTypeHierarchy DBTH(IRDB); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -865,17 +865,17 @@ TEST(DBTHTest, VTableConstruction_7_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &AType = DBTH.getType("A"); + const auto &AType = DBTH.getType("_ZTS1A"); ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); - const auto &XType = DBTH.getType("X"); + const auto &XType = DBTH.getType("_ZTS1X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("vY"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); + const auto &OmegaType = DBTH.getType("_ZTS5Omega"); ASSERT_NE(nullptr, OmegaType); const auto &VTableForAType = DBTH.getVFTable(AType); @@ -907,9 +907,9 @@ TEST(DBTHTest, VTableConstruction_8) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); EXPECT_NE(nullptr, NonvirtualClassType); @@ -945,9 +945,9 @@ TEST(DBTHTest, VTableConstruction_9) { "type_hierarchies/type_hierarchy_9_cpp_dbg.ll"); DIBasedTypeHierarchy DBTH(IRDB); - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -972,9 +972,9 @@ TEST(DBTHTest, VTableConstruction_10) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -998,9 +998,9 @@ TEST(DBTHTest, VTableConstruction_11) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1020,9 +1020,9 @@ TEST(DBTHTest, VTableConstruction_12) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1042,11 +1042,11 @@ TEST(DBTHTest, VTableConstruction_12_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1070,9 +1070,9 @@ TEST(DBTHTest, VTableConstruction_12_c) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); const auto &VTableForChild = DBTH.getVFTable(ChildType); @@ -1133,9 +1133,9 @@ TEST(DBTHTest, VTableConstruction_16) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &ChildOfChildType = DBTH.getType("ChildOfChild"); ASSERT_NE(nullptr, ChildOfChildType); @@ -1177,9 +1177,9 @@ TEST(DBTHTest, VTableConstruction_17) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // Since Child2 is never used, it is sometimes optimized out by the compiler // const auto &Child2Type = DBTH.getType("Child2"); @@ -1229,9 +1229,9 @@ TEST(DBTHTest, VTableConstruction_18) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &Child2Type = DBTH.getType("Child_2"); ASSERT_NE(nullptr, Child2Type); @@ -1272,9 +1272,9 @@ TEST(DBTHTest, VTableConstruction_19) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &FooType = DBTH.getType("Foo"); ASSERT_NE(nullptr, FooType); @@ -1325,11 +1325,11 @@ TEST(DBTHTest, VTableConstruction_20) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); const auto &Base2Type = DBTH.getType("Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1358,13 +1358,13 @@ TEST(DBTHTest, VTableConstruction_21) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); const auto &Base2Type = DBTH.getType("Base2"); ASSERT_NE(nullptr, Base2Type); const auto &Base3Type = DBTH.getType("Base3"); ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &Child2Type = DBTH.getType("Child2"); ASSERT_NE(nullptr, Child2Type); @@ -1422,9 +1422,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_1) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1444,9 +1444,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_2) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1466,9 +1466,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_3) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1486,9 +1486,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_4) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1508,11 +1508,11 @@ TEST(DBTHTest, TransitivelyReachableTypes_5) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &OtherBaseType = DBTH.getType("OtherBase"); + const auto &OtherBaseType = DBTH.getType("_ZTS9OtherBase"); ASSERT_NE(nullptr, OtherBaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1537,9 +1537,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_6) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1729,9 +1729,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_8) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); ASSERT_NE(nullptr, NonvirtualClassType); @@ -1775,9 +1775,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_9) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1797,9 +1797,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_10) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1819,9 +1819,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_11) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1841,9 +1841,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_12) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1863,9 +1863,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_12_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &ChildsChildType = DBTH.getType("ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); @@ -1894,7 +1894,7 @@ TEST(DBTHTest, TransitivelyReachableTypes_12_c) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &ChildsChildType = DBTH.getType("ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); @@ -1922,7 +1922,7 @@ TEST(DBTHTest, TransitivelyReachableTypes_14) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1937,9 +1937,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_15) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1959,9 +1959,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_16) { "type_hierarchies/type_hierarchy_16_cpp_dbg.ll"); DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // const auto &ChildsChildType = DBTH.getType("ChildsChild"); // Since ChildsChild is never used, it is optimized out @@ -2004,9 +2004,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_17) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); // const auto &Child2Type = DBTH.getType("Child2"); // Since Child2 is never used, it is optimized out @@ -2049,9 +2049,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_18) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &Child2Type = DBTH.getType("Child_2"); ASSERT_NE(nullptr, Child2Type); @@ -2087,9 +2087,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_19) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &FooType = DBTH.getType("Foo"); ASSERT_NE(nullptr, FooType); @@ -2136,11 +2136,11 @@ TEST(DBTHTest, TransitivelyReachableTypes_20) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); const auto &Base2Type = DBTH.getType("Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -2166,13 +2166,13 @@ TEST(DBTHTest, TransitivelyReachableTypes_21) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("Base"); + const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); const auto &Base2Type = DBTH.getType("Base2"); ASSERT_NE(nullptr, Base2Type); const auto &Base3Type = DBTH.getType("Base3"); ASSERT_NE(nullptr, Base3Type); - const auto &ChildType = DBTH.getType("Child"); + const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); const auto &Child2Type = DBTH.getType("Child2"); ASSERT_NE(nullptr, Child2Type); From f630ebefa0a4b75e95105af87f1b9bd75c7ff14d Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 21 Apr 2024 13:15:26 +0200 Subject: [PATCH 32/42] Fix vtable + transitive di th tests --- .../DIBasedTypeHierarchyTest.cpp | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp index 3205863a3..01f677363 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyTest.cpp @@ -819,19 +819,19 @@ TEST(DBTHTest, VTableConstruction_7) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &AType = DBTH.getType("A"); + const auto &AType = DBTH.getType("_ZTS1A"); ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); + const auto &BType = DBTH.getType("_ZTS1B"); ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); + const auto &DType = DBTH.getType("_ZTS1D"); ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); + const auto &XType = DBTH.getType("_ZTS1X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); const auto &VTableForAType = DBTH.getVFTable(AType); @@ -865,13 +865,13 @@ TEST(DBTHTest, VTableConstruction_7_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &AType = DBTH.getType("_ZTS1A"); + const auto &AType = DBTH.getType("A"); ASSERT_NE(nullptr, AType); const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); - const auto &XType = DBTH.getType("_ZTS1X"); + const auto &XType = DBTH.getType("X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("vY"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); @@ -911,9 +911,9 @@ TEST(DBTHTest, VTableConstruction_8) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + const auto &NonvirtualClassType = DBTH.getType("_ZTS15NonvirtualClass"); EXPECT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + const auto &NonvirtualStructType = DBTH.getType("_ZTS16NonvirtualStruct"); EXPECT_NE(nullptr, NonvirtualStructType); const auto &VTableForBaseType = DBTH.getVFTable(BaseType); @@ -1042,9 +1042,9 @@ TEST(DBTHTest, VTableConstruction_12_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("_ZTS4Base"); + const auto &BaseType = DBTH.getType("Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("_ZTS5Child"); + const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); @@ -1070,7 +1070,7 @@ TEST(DBTHTest, VTableConstruction_12_c) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &ChildType = DBTH.getType("_ZTS5Child"); + const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); @@ -1137,11 +1137,11 @@ TEST(DBTHTest, VTableConstruction_16) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildOfChildType = DBTH.getType("ChildOfChild"); + const auto &ChildOfChildType = DBTH.getType("_ZTS12ChildOfChild"); ASSERT_NE(nullptr, ChildOfChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); + const auto &BaseTwoType = DBTH.getType("_ZTS7BaseTwo"); ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); + const auto &ChildTwoType = DBTH.getType("_ZTS8ChildTwo"); ASSERT_NE(nullptr, ChildTwoType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1184,9 +1184,9 @@ TEST(DBTHTest, VTableConstruction_17) { // Since Child2 is never used, it is sometimes optimized out by the compiler // const auto &Child2Type = DBTH.getType("Child2"); // ASSERT_NE(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); + const auto &KidType = DBTH.getType("_ZTS3Kid"); ASSERT_NE(nullptr, KidType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1233,9 +1233,9 @@ TEST(DBTHTest, VTableConstruction_18) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child_2"); + const auto &Child2Type = DBTH.getType("_ZTS7Child_2"); ASSERT_NE(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); + const auto &Child3Type = DBTH.getType("_ZTS7Child_3"); ASSERT_NE(nullptr, Child3Type); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1276,13 +1276,13 @@ TEST(DBTHTest, VTableConstruction_19) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); + const auto &FooType = DBTH.getType("_ZTS3Foo"); ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); + const auto &BarType = DBTH.getType("_ZTS3Bar"); ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); + const auto &LoremType = DBTH.getType("_ZTS5Lorem"); ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); + const auto &ImpsumType = DBTH.getType("_ZTS6Impsum"); ASSERT_NE(nullptr, ImpsumType); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1327,7 +1327,7 @@ TEST(DBTHTest, VTableConstruction_20) { // check for all types const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); @@ -1360,13 +1360,13 @@ TEST(DBTHTest, VTableConstruction_21) { // check for all types const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); + const auto &Base3Type = DBTH.getType("_ZTS5Base3"); ASSERT_NE(nullptr, Base3Type); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); + const auto &Child2Type = DBTH.getType("_ZTS6Child2"); ASSERT_NE(nullptr, Child2Type); const auto &VTableForBase = DBTH.getVFTable(BaseType); @@ -1559,19 +1559,19 @@ TEST(DBTHTest, TransitivelyReachableTypes_7) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &AType = DBTH.getType("A"); + const auto &AType = DBTH.getType("_ZTS1A"); ASSERT_NE(nullptr, AType); - const auto &BType = DBTH.getType("B"); + const auto &BType = DBTH.getType("_ZTS1B"); ASSERT_NE(nullptr, BType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); - const auto &DType = DBTH.getType("D"); + const auto &DType = DBTH.getType("_ZTS1D"); ASSERT_NE(nullptr, DType); - const auto &XType = DBTH.getType("X"); + const auto &XType = DBTH.getType("_ZTS1X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); auto ReachableTypesA = DBTH.getSubTypes(AType); @@ -1655,15 +1655,15 @@ TEST(DBTHTest, TransitivelyReachableTypes_7_b) { // check for all types const auto &AType = DBTH.getType("A"); ASSERT_NE(nullptr, AType); - const auto &CType = DBTH.getType("C"); + const auto &CType = DBTH.getType("_ZTS1C"); ASSERT_NE(nullptr, CType); const auto &XType = DBTH.getType("X"); ASSERT_NE(nullptr, XType); - const auto &YType = DBTH.getType("Y"); + const auto &YType = DBTH.getType("_ZTS1Y"); ASSERT_NE(nullptr, YType); - const auto &ZType = DBTH.getType("Z"); + const auto &ZType = DBTH.getType("_ZTS1Z"); ASSERT_NE(nullptr, ZType); - const auto &OmegaType = DBTH.getType("Omega"); + const auto &OmegaType = DBTH.getType("_ZTS5Omega"); ASSERT_NE(nullptr, OmegaType); auto ReachableTypesA = DBTH.getSubTypes(AType); @@ -1733,9 +1733,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_8) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &NonvirtualClassType = DBTH.getType("NonvirtualClass"); + const auto &NonvirtualClassType = DBTH.getType("_ZTS15NonvirtualClass"); ASSERT_NE(nullptr, NonvirtualClassType); - const auto &NonvirtualStructType = DBTH.getType("NonvirtualStruct"); + const auto &NonvirtualStructType = DBTH.getType("_ZTS16NonvirtualStruct"); ASSERT_NE(nullptr, NonvirtualStructType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1863,11 +1863,11 @@ TEST(DBTHTest, TransitivelyReachableTypes_12_b) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("_ZTS4Base"); + const auto &BaseType = DBTH.getType("Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("_ZTS5Child"); + const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1894,9 +1894,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_12_c) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &ChildType = DBTH.getType("_ZTS5Child"); + const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); - const auto &ChildsChildType = DBTH.getType("ChildsChild"); + const auto &ChildsChildType = DBTH.getType("_ZTS11ChildsChild"); ASSERT_NE(nullptr, ChildsChildType); auto ReachableTypesChild = DBTH.getSubTypes(ChildType); @@ -1922,7 +1922,7 @@ TEST(DBTHTest, TransitivelyReachableTypes_14) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("_ZTS4Base"); + const auto &BaseType = DBTH.getType("Base"); ASSERT_NE(nullptr, BaseType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1937,9 +1937,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_15) { DIBasedTypeHierarchy DBTH(IRDB); // check for all types - const auto &BaseType = DBTH.getType("_ZTS4Base"); + const auto &BaseType = DBTH.getType("Base"); ASSERT_NE(nullptr, BaseType); - const auto &ChildType = DBTH.getType("_ZTS5Child"); + const auto &ChildType = DBTH.getType("Child"); ASSERT_NE(nullptr, ChildType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -1966,9 +1966,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_16) { // const auto &ChildsChildType = DBTH.getType("ChildsChild"); // Since ChildsChild is never used, it is optimized out // ASSERT_EQ(nullptr, ChildsChildType); - const auto &BaseTwoType = DBTH.getType("BaseTwo"); + const auto &BaseTwoType = DBTH.getType("_ZTS7BaseTwo"); ASSERT_NE(nullptr, BaseTwoType); - const auto &ChildTwoType = DBTH.getType("ChildTwo"); + const auto &ChildTwoType = DBTH.getType("_ZTS8ChildTwo"); ASSERT_NE(nullptr, ChildTwoType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -2011,9 +2011,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_17) { // const auto &Child2Type = DBTH.getType("Child2"); // Since Child2 is never used, it is optimized out // ASSERT_EQ(nullptr, Child2Type); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &KidType = DBTH.getType("Kid"); + const auto &KidType = DBTH.getType("_ZTS3Kid"); ASSERT_NE(nullptr, KidType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -2053,9 +2053,9 @@ TEST(DBTHTest, TransitivelyReachableTypes_18) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child_2"); + const auto &Child2Type = DBTH.getType("_ZTS7Child_2"); ASSERT_NE(nullptr, Child2Type); - const auto &Child3Type = DBTH.getType("Child_3"); + const auto &Child3Type = DBTH.getType("_ZTS7Child_3"); ASSERT_NE(nullptr, Child3Type); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -2091,13 +2091,13 @@ TEST(DBTHTest, TransitivelyReachableTypes_19) { ASSERT_NE(nullptr, BaseType); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &FooType = DBTH.getType("Foo"); + const auto &FooType = DBTH.getType("_ZTS3Foo"); ASSERT_NE(nullptr, FooType); - const auto &BarType = DBTH.getType("Bar"); + const auto &BarType = DBTH.getType("_ZTS3Bar"); ASSERT_NE(nullptr, BarType); - const auto &LoremType = DBTH.getType("Lorem"); + const auto &LoremType = DBTH.getType("_ZTS5Lorem"); ASSERT_NE(nullptr, LoremType); - const auto &ImpsumType = DBTH.getType("Impsum"); + const auto &ImpsumType = DBTH.getType("_ZTS6Impsum"); ASSERT_NE(nullptr, ImpsumType); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); @@ -2138,7 +2138,7 @@ TEST(DBTHTest, TransitivelyReachableTypes_20) { // check for all types const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); @@ -2168,13 +2168,13 @@ TEST(DBTHTest, TransitivelyReachableTypes_21) { // check for all types const auto &BaseType = DBTH.getType("_ZTS4Base"); ASSERT_NE(nullptr, BaseType); - const auto &Base2Type = DBTH.getType("Base2"); + const auto &Base2Type = DBTH.getType("_ZTS5Base2"); ASSERT_NE(nullptr, Base2Type); - const auto &Base3Type = DBTH.getType("Base3"); + const auto &Base3Type = DBTH.getType("_ZTS5Base3"); ASSERT_NE(nullptr, Base3Type); const auto &ChildType = DBTH.getType("_ZTS5Child"); ASSERT_NE(nullptr, ChildType); - const auto &Child2Type = DBTH.getType("Child2"); + const auto &Child2Type = DBTH.getType("_ZTS6Child2"); ASSERT_NE(nullptr, Child2Type); auto ReachableTypesBase = DBTH.getSubTypes(BaseType); From d8766de6c176ad668ac6c370ad6187a876be5ec0 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 21 Apr 2024 13:25:07 +0200 Subject: [PATCH 33/42] Optimizing deprecation warnings for getAsJson --- .../phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h | 2 +- include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h | 2 +- include/phasar/Pointer/AliasInfo.h | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h index 66fa5e34e..c9bbb5b99 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedBackwardICFG.h @@ -67,7 +67,7 @@ class LLVMBasedBackwardICFG : public LLVMBasedBackwardCFG, getReturnSitesOfCallAtImpl(n_t Inst) const; void printImpl(llvm::raw_ostream &OS) const; void printAsJsonImpl(llvm::raw_ostream &OS) const; - [[nodiscard]] nlohmann::json getAsJsonImpl() const; + [[nodiscard, deprecated]] nlohmann::json getAsJsonImpl() const; [[nodiscard]] const CallGraph &getCallGraphImpl() const noexcept; llvm::LLVMContext BackwardRetsCtx; diff --git a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h index f1c03879a..471fba581 100644 --- a/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h +++ b/include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h @@ -150,7 +150,7 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase { getReturnSitesOfCallAtImpl(n_t Inst) const; void printImpl(llvm::raw_ostream &OS) const; void printAsJsonImpl(llvm::raw_ostream &OS) const; - [[nodiscard]] nlohmann::json getAsJsonImpl() const; + [[nodiscard, deprecated]] nlohmann::json getAsJsonImpl() const; [[nodiscard]] const CallGraph &getCallGraphImpl() const noexcept { return CG; } diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index 576a7b529..d2941404b 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -141,7 +141,8 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { VT->Print(AA, OS); } - [[nodiscard]] nlohmann::json getAsJson() const { + [[nodiscard, deprecated("Use printAsJson() instead")]] nlohmann::json + getAsJson() const { if (VT == nullptr) { return {}; } @@ -245,7 +246,10 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { static_cast(AA)->print(OS); }, [](const void *AA) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" return static_cast(AA)->getAsJson(); +#pragma GCC diagnostic pop }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); From 4d079d827cbc300a8b626736cf21aa7f1884baf2 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 22 Apr 2024 23:15:34 +0200 Subject: [PATCH 34/42] TypeTrait check current non functioning impl --- include/phasar/Pointer/AliasInfo.h | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index d2941404b..ef9380cf0 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -141,12 +141,8 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { VT->Print(AA, OS); } - [[nodiscard, deprecated("Use printAsJson() instead")]] nlohmann::json - getAsJson() const { - if (VT == nullptr) { - return {}; - } - + [[nodiscard]] nlohmann::json getAsJson() const { + assert(VT != nullptr); return VT->GetAsJson(AA); } @@ -190,6 +186,16 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { assert(isa() && "Invalid AliasInfo cast!"); return static_cast(AA); } + /* + template + [[nodiscard]] auto hasGetAsJsonImpl() -> decltype(nlohmann::json()) { + return static_cast(AA)->getAsJson(); + } + */ + + template + using hasGetAsJson = + decltype(std::declval().getAsJson(std::declval())); private: struct VTable { @@ -245,11 +251,10 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->print(OS); }, - [](const void *AA) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated" - return static_cast(AA)->getAsJson(); -#pragma GCC diagnostic pop + [](const void *AA) noexcept { + /// TODO: hier bei Compile-Time checken ob getAsJson in dem ConcreteAA + /// existiert. Wenn nein, leeres json. + return hasGetAsJson(AA); }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); From fa6bb87a98c25324d5a443cc0e77fb6fa3f3570a Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 28 Apr 2024 11:26:54 +0200 Subject: [PATCH 35/42] fixed TypeHierarchySerialization Tests --- .../GeneralStatisticsAnalysisSerializer.h | 48 ----------- .../TypeHierarchy/LLVMTypeHierarchy.h | 2 - include/phasar/Pointer/AliasInfo.h | 21 ++--- include/phasar/Utils/TypeTraits.h | 8 ++ .../Passes/GeneralStatisticsAnalysis.cpp | 79 ++++++++----------- .../GeneralStatisticsAnalysisSerializer.cpp | 43 ---------- lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp | 5 +- .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 20 ++--- .../TypeHierarchy/LLVMTypeHierarchy.cpp | 15 ++-- lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp | 10 ++- .../DIBasedTypeHierarchySerializationTest.cpp | 20 ++++- .../LLVMTypeHierarchySerializationTest.cpp | 6 +- 12 files changed, 93 insertions(+), 184 deletions(-) delete mode 100644 include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h delete mode 100644 lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h deleted file mode 100644 index f51a1b049..000000000 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h +++ /dev/null @@ -1,48 +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 - *****************************************************************************/ - -#ifndef PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H -#define PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H - -#include "llvm/Support/raw_ostream.h" - -#include -#include -#include - -namespace psr { -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 BasicBlocks = 0; - size_t CallSites = 0; - size_t DebugIntrinsics = 0; - size_t Instructions = 0; - size_t MemIntrinsics = 0; - size_t Branches = 0; - size_t GetElementPtrs = 0; - size_t LandingPads = 0; - size_t PhiNodes = 0; - size_t NumInlineAsm = 0; - size_t IndCalls = 0; - size_t NonVoidInsts = 0; - size_t NumberOfAllocaInstructions = 0; - std::string ModuleName{}; - - GeneralStatisticsAnalysisSerializer() noexcept = default; - void printAsJson(llvm::raw_ostream &OS); -}; - -} // namespace psr - -#endif // PHASAR_PHASARLLVM_PASSES_GENERALSTATISTICSANALYSISDATA_H diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index b075e427e..3507be022 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -212,8 +212,6 @@ class LLVMTypeHierarchy void print(llvm::raw_ostream &OS = llvm::outs()) const override; - LLVMTypeHierarchyData getTypeHierarchyData() const; - [[nodiscard]] [[deprecated( "Please use printAsJson() instead")]] nlohmann::json getAsJson() const override; diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index ef9380cf0..d93d4f064 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -21,9 +21,6 @@ #include "llvm/Support/TypeName.h" #include "llvm/Support/raw_ostream.h" -#include "nlohmann/json.hpp" -#include "nlohmann/json_fwd.hpp" - #include #include @@ -186,16 +183,6 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { assert(isa() && "Invalid AliasInfo cast!"); return static_cast(AA); } - /* - template - [[nodiscard]] auto hasGetAsJsonImpl() -> decltype(nlohmann::json()) { - return static_cast(AA)->getAsJson(); - } - */ - - template - using hasGetAsJson = - decltype(std::declval().getAsJson(std::declval())); private: struct VTable { @@ -252,9 +239,11 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { static_cast(AA)->print(OS); }, [](const void *AA) noexcept { - /// TODO: hier bei Compile-Time checken ob getAsJson in dem ConcreteAA - /// existiert. Wenn nein, leeres json. - return hasGetAsJson(AA); + /// TODO: die commit changes von fabian nehmen + if constexpr (has_getAsJson::value) { + return static_cast(AA)->getAsJson(); + } + return nlohmann::json(); }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index 2c6d771c7..8be00acd3 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -13,6 +13,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" +#include "nlohmann/json.hpp" + #include #include #include @@ -246,6 +248,12 @@ template using type_identity_t = typename type_identity::type; template static constexpr size_t variant_idx = detail::variant_idx::value; +template +struct has_getAsJson : std::false_type {}; // NOLINT +template +struct has_getAsJson().getAsJson())> + : std::true_type {}; // NOLINT + struct TrueFn { template [[nodiscard]] bool operator()(const Args &.../*unused*/) const noexcept { diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 8c50b63ba..44591281f 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -9,9 +9,9 @@ #include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h" -#include "phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/NlohmannLogging.h" #include "phasar/Utils/PAMMMacros.h" #include "llvm/IR/CFG.h" @@ -289,53 +289,42 @@ GeneralStatistics::getRetResInstructions() const { } void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { - 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 Json; + + Json["Instructions"] = Instructions; + Json["Functions"] = Functions; + Json["ExternalFunctions"] = ExternalFunctions; + Json["FunctionDefinitions"] = FunctionDefinitions; + Json["AddressTakenFunctions"] = AddressTakenFunctions; + Json["Globals"] = Globals; + Json["GlobalConsts"] = GlobalConsts; + Json["ExternalGlobals"] = ExternalGlobals; + Json["GlobalsDefinitions"] = GlobalsDefinitions; + Json["AllocaInstructions"] = AllocaInstructions.size(); + Json["BasicBlocks"] = BasicBlocks; + Json["TotalNumPredecessorBBs"] = TotalNumPredecessorBBs; + Json["CallSites"] = CallSites; + Json["NumInlineAsm"] = NumInlineAsm; + Json["MemIntrinsics"] = MemIntrinsics; + Json["IndCalls"] = IndCalls; + Json["DebugIntrinsics"] = DebugIntrinsics; + Json["Switches"] = Switches; + Json["Branches"] = Branches; + Json["GetElementPtrs"] = GetElementPtrs; + Json["LandingPads"] = LandingPads; + Json["PhiNodes"] = PhiNodes; + Json["NonVoidInsts"] = NonVoidInsts; + Json["ModuleName"] = ModuleName; + + OS << Json; } 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; + std::string GeneralStatisticsAsString; + llvm::raw_string_ostream Stream(GeneralStatisticsAsString); + printAsJson(Stream); + + return nlohmann::json::parse(GeneralStatisticsAsString); } } // namespace psr diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp deleted file mode 100644 index ffc971580..000000000 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysisSerializer.cpp +++ /dev/null @@ -1,43 +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/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 d211ee2d0..40b95feaa 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSet.cpp @@ -737,10 +737,7 @@ LLVMAliasSetData LLVMAliasSet::getLLVMAliasSetData() const { } } if (!PtsJson.empty()) { - auto &AliasSetsDataPosition = Data.AliasSets.emplace_back(); - for (const auto &Curr : PtsJson) { - AliasSetsDataPosition.push_back(Curr); - } + Data.AliasSets.push_back(std::move(PtsJson)); } } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 7fa166eaa..14b9a14cc 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -220,12 +220,8 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { } static const llvm::DICompositeType * -stringToDICompositeType(const LLVMProjectIRDB *IRDB, +stringToDICompositeType(const llvm::DebugInfoFinder &DIF, const llvm::StringRef DITypeName) { - llvm::DebugInfoFinder DIF; - const auto *Module = IRDB->getModule(); - DIF.processModule(*Module); - for (const auto *Type : DIF.types()) { if (const auto *DICT = llvm::dyn_cast(Type)) { auto Ident = DICT->getIdentifier(); @@ -241,12 +237,8 @@ stringToDICompositeType(const LLVMProjectIRDB *IRDB, llvm::report_fatal_error("DIType doesn't exist"); } -static const llvm::DIType *stringToDIType(const LLVMProjectIRDB *IRDB, +static const llvm::DIType *stringToDIType(const llvm::DebugInfoFinder &DIF, const llvm::StringRef DITypeName) { - llvm::DebugInfoFinder DIF; - const auto *Module = IRDB->getModule(); - DIF.processModule(*Module); - for (const auto *Type : DIF.types()) { if (Type) { if (Type->getName() == DITypeName) { @@ -267,11 +259,15 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( const LLVMProjectIRDB *IRDB, const DIBasedTypeHierarchyData &SerializedData) : TransitiveDerivedIndex(SerializedData.TransitiveDerivedIndex) { + llvm::DebugInfoFinder DIF; + const auto *Module = IRDB->getModule(); + DIF.processModule(*Module); + VertexTypes.reserve(SerializedData.VertexTypes.size()); TypeToVertex.reserve(SerializedData.VertexTypes.size()); size_t Idx = 0; for (const auto &Curr : SerializedData.VertexTypes) { - const auto *Ty = stringToDICompositeType(IRDB, Curr); + const auto *Ty = stringToDICompositeType(DIF, Curr); VertexTypes.push_back(Ty); TypeToVertex.try_emplace(Ty, Idx); NameToType.try_emplace(Curr, Ty); @@ -281,7 +277,7 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy( Hierarchy.reserve(SerializedData.Hierarchy.size()); for (const auto &Curr : SerializedData.Hierarchy) { - Hierarchy.push_back(stringToDIType(IRDB, Curr)); + Hierarchy.push_back(stringToDIType(DIF, Curr)); } for (const auto &Curr : SerializedData.VTables) { diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp index fbe3fd506..3436c8551 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp @@ -108,6 +108,9 @@ LLVMTypeHierarchy::LLVMTypeHierarchy( TypeVFTMap[StructType] = getVirtualFunctions(*IRDBModule, *StructType); } + // build the hierarchy for the module + constructHierarchy(*IRDBModule); + // add all edges for (auto *StructType : StructTypes) { // use type information to check if it is really a subtype @@ -285,10 +288,12 @@ void LLVMTypeHierarchy::constructHierarchy(const llvm::Module &M) { TypeVFTMap[StructType] = getVirtualFunctions(M, *StructType); } } + // construct the edges between a type and its subtypes for (auto *StructType : StructTypes) { // use type information to check if it is really a subtype auto SubTypes = getSubTypes(M, *StructType); + for (const auto *SubType : SubTypes) { boost::add_edge(TypeVertexMap[SubType], TypeVertexMap[StructType], TypeGraph); @@ -447,16 +452,8 @@ void LLVMTypeHierarchy::printAsDot(llvm::raw_ostream &OS) const { OS << S.str(); } -LLVMTypeHierarchyData LLVMTypeHierarchy::getTypeHierarchyData() const { - LLVMTypeHierarchyData Data; - - /// TODO: - - return Data; -} - void LLVMTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { - LLVMTypeHierarchyData Data = getTypeHierarchyData(); + LLVMTypeHierarchyData Data; Data.PhasarConfigJsonTypeHierarchyID = PhasarConfig::JsonTypeHierarchyID().str(); diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp index 6034e2357..d61eda384 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp @@ -15,6 +15,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/Operator.h" +#include "llvm/Support/raw_ostream.h" #include #include @@ -56,8 +57,13 @@ nlohmann::json LLVMVFTable::getAsJson() const { LLVMVFTableData Data; for (const auto &Curr : VFT) { - /// TODO: check if Curr null - Data.VFT.push_back(Curr->getName().str()); + if (Curr) { + Data.VFT.push_back(Curr->getName().str()); + continue; + } + + Data.VFT.emplace_back(""); + llvm::errs() << "Function was null"; } return Data; diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index 57d0e50af..57299bc9e 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -29,10 +29,28 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, EXPECT_EQ(Orig.getAllVTables().size(), Deser.getAllVTables().size()); for (const auto *OrigCurrentType : Orig.getAllTypes()) { - + // check types const auto *DeserTy = Deser.getType(Orig.getTypeName(OrigCurrentType)); EXPECT_EQ(OrigCurrentType, DeserTy); + // check edges + const auto OrigSubTypes = Orig.subTypesOf(OrigCurrentType); + const auto DeserSubTypes = Deser.subTypesOf(OrigCurrentType); + + for (const auto &CurrOrigSubType : OrigSubTypes) { + bool DeserHasSubType = false; + + for (const auto &CurrDeserSubType : DeserSubTypes) { + if (CurrDeserSubType->getName() == CurrOrigSubType->getName()) { + DeserHasSubType = true; + break; + } + } + + EXPECT_TRUE(DeserHasSubType); + } + + // check virtual functions and vtables if (OrigCurrentType != DeserTy) { llvm::errs() << "Mismatched types:\n> OrigTy: " << *OrigCurrentType << '\n'; diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index b5862a27c..873e65a03 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -4,6 +4,7 @@ #include "phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/NlohmannLogging.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/StringRef.h" @@ -24,12 +25,13 @@ class LLVMTypeHierarchySerialization }; // Test Fixture -void compareResults(const psr::LLVMTypeHierarchy &Orig, - const psr::LLVMTypeHierarchy &Deser) { +void compareResults(psr::LLVMTypeHierarchy &Orig, + 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()) { + // check types EXPECT_EQ(OrigCurrentType, Deser.getType(OrigCurrentType->getName().str())); } } From cb8bc831bdacbb07e25308a2796f5f53af689513 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 28 Apr 2024 11:33:59 +0200 Subject: [PATCH 36/42] Optimized deprecation warinings for getAsJson --- include/phasar/Pointer/AliasInfo.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/phasar/Pointer/AliasInfo.h b/include/phasar/Pointer/AliasInfo.h index d93d4f064..3ab63412e 100644 --- a/include/phasar/Pointer/AliasInfo.h +++ b/include/phasar/Pointer/AliasInfo.h @@ -138,7 +138,8 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { VT->Print(AA, OS); } - [[nodiscard]] nlohmann::json getAsJson() const { + [[nodiscard, deprecated("Use printAsJson() instead")]] nlohmann::json + getAsJson() const { assert(VT != nullptr); return VT->GetAsJson(AA); } @@ -239,11 +240,13 @@ class AliasInfoRef : public AnalysisPropertiesMixin> { static_cast(AA)->print(OS); }, [](const void *AA) noexcept { - /// TODO: die commit changes von fabian nehmen +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated" if constexpr (has_getAsJson::value) { return static_cast(AA)->getAsJson(); } return nlohmann::json(); +#pragma GCC diagnostic pop }, [](const void *AA, llvm::raw_ostream &OS) { static_cast(AA)->printAsJson(OS); From fd70a41ffba45a4c1e011be826003243d70603d1 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 30 Apr 2024 23:41:18 +0200 Subject: [PATCH 37/42] debug code backup --- .../TypeHierarchy/LLVMTypeHierarchy.h | 2 +- .../PhasarLLVM/TypeHierarchy/LLVMVFTable.h | 3 ++ .../TypeHierarchy/LLVMTypeHierarchy.cpp | 54 ++++++++++++------- lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp | 3 +- .../LLVMTypeHierarchySerializationTest.cpp | 32 +++++++++++ 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h index 3507be022..f54153121 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h @@ -127,7 +127,7 @@ class LLVMTypeHierarchy static bool isStruct(llvm::StringRef TypeName); std::vector - getSubTypes(const llvm::Module &M, const llvm::StructType &Type); + getSubTypes(const llvm::Module &M, const llvm::StructType &Type) const; std::vector getVirtualFunctions(const llvm::Module &M, const llvm::StructType &Type); diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h index 4f505d91b..20bfb5196 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/LLVMVFTable.h @@ -37,6 +37,9 @@ class LLVMVFTable : public VFTable { std::vector VFT; public: + // NOLINTNEXTLINE + static constexpr char NullFunName[] = "__null__"; + LLVMVFTable() = default; LLVMVFTable(std::vector Fs) : VFT(std::move(Fs)) {} ~LLVMVFTable() override = default; diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp index 3436c8551..54c840a1a 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp @@ -77,12 +77,14 @@ LLVMTypeHierarchy::LLVMTypeHierarchy(LLVMProjectIRDB &IRDB) { LLVMTypeHierarchy::LLVMTypeHierarchy( LLVMProjectIRDB &IRDB, const LLVMTypeHierarchyData &SerializedData) { + + llvm::StringMap NameToStructType; const auto &IRDBModule = IRDB.getModule(); VisitedModules.insert(IRDBModule); auto StructTypes = IRDBModule->getIdentifiedStructTypes(); - llvm::StringMap NameToStructType; + // find all struct types by name for (const auto &SerElement : SerializedData.TypeGraph) { bool MatchFound = false; @@ -104,20 +106,33 @@ LLVMTypeHierarchy::LLVMTypeHierarchy( for (const auto &Curr : NameToStructType) { const auto &StructType = Curr.getValue(); auto Vertex = boost::add_vertex(TypeGraph); + TypeVertexMap[StructType] = Vertex; TypeGraph[Vertex] = VertexProperties(StructType); TypeVFTMap[StructType] = getVirtualFunctions(*IRDBModule, *StructType); } - - // build the hierarchy for the module - constructHierarchy(*IRDBModule); + llvm::outs() << "NameToStructTypeSize: " << NameToStructType.size() << "\n\n"; + llvm::outs() << "TypeVertexMap: " << TypeVertexMap.size() << "\n\n"; // 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); + llvm::outs() << "Deser Edges:\n"; + for (const auto &SerElement : SerializedData.TypeGraph) { + llvm::outs() << "Key: " << SerElement.getKey().str() << "\nValues:\n"; + llvm::outs() << "SerElementTypeVert: " + << TypeVertexMap[NameToStructType[SerElement.getKey().str()]] + << "\n"; + llvm::outs() << "SerElement.getValue: " << SerElement.getValue() << "\n"; + for (const auto &CurrEdge : SerElement.getValue()) { + llvm::outs() << CurrEdge << "\n"; + + llvm::outs() << "CurrEdgeTypeVertex: " + << TypeVertexMap[NameToStructType[CurrEdge]] << "\n"; + + /// TODO: find out why the edge isn't being added, despite all types + /// existing, all helper variables initialized and everything serialized + /// correctly. + boost::add_edge( + TypeVertexMap[NameToStructType[SerElement.getKey().str()]], + TypeVertexMap[NameToStructType[CurrEdge]], TypeGraph); } } } @@ -201,11 +216,11 @@ void LLVMTypeHierarchy::buildLLVMTypeHierarchy(const llvm::Module &M) { std::vector LLVMTypeHierarchy::getSubTypes(const llvm::Module & /*M*/, - const llvm::StructType &Type) { + const llvm::StructType &Type) const { // find corresponding type info variable std::vector SubTypes; std::string ClearName = removeStructOrClassPrefix(Type); - if (const auto *TI = ClearNameTIMap[ClearName]) { + if (const auto *TI = ClearNameTIMap.at(ClearName)) { if (!TI->hasInitializer()) { PHASAR_LOG_LEVEL_CAT(DEBUG, "LLVMTypeHierarchy", ClearName << " does not have initializer"); @@ -221,7 +236,7 @@ LLVMTypeHierarchy::getSubTypes(const llvm::Module & /*M*/, if (Name.find(TypeInfoPrefix) != llvm::StringRef::npos) { auto ClearName = removeTypeInfoPrefix(llvm::demangle(Name.str())); - if (const auto *Type = ClearNameTypeMap[ClearName]) { + if (const auto *Type = ClearNameTypeMap.at(ClearName)) { SubTypes.push_back(Type); } } @@ -459,20 +474,23 @@ void LLVMTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { vertex_iterator VIv; vertex_iterator VIvEnd; + out_edge_iterator EI; out_edge_iterator EIEnd; // iterate all graph vertices for (boost::tie(VIv, VIvEnd) = boost::vertices(TypeGraph); VIv != VIvEnd; ++VIv) { - Data.TypeGraph[TypeGraph[*VIv].getTypeName()]; - // iterate all out edges of vertex vi_v - for (boost::tie(EI, EIEnd) = boost::out_edges(*VIv, TypeGraph); EI != EIEnd; - ++EI) { + llvm::outs() << "VertexName: " << TypeGraph[*VIv].getTypeName() << "\n"; + // Data.TypeGraph[TypeGraph[*VIv].getTypeName()]; + // iterate all out edges of vertex vi_v + for (const auto &CurrReachable : TypeGraph[*VIv].ReachableTypes) { Data.TypeGraph[TypeGraph[*VIv].getTypeName()].push_back( - TypeGraph[boost::target(*EI, TypeGraph)].getTypeName()); + CurrReachable->getName().str()); + llvm::outs() << "Reachable: " << CurrReachable->getName().str() << "\n"; } } + llvm::outs() << "\n\n\n"; Data.printAsJson(OS); } diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp index d61eda384..2b6b443ef 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTable.cpp @@ -62,8 +62,7 @@ nlohmann::json LLVMVFTable::getAsJson() const { continue; } - Data.VFT.emplace_back(""); - llvm::errs() << "Function was null"; + Data.VFT.emplace_back(NullFunName); } return Data; diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index 873e65a03..2597a0172 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -33,6 +33,38 @@ void compareResults(psr::LLVMTypeHierarchy &Orig, for (const auto &OrigCurrentType : Orig.getAllTypes()) { // check types EXPECT_EQ(OrigCurrentType, Deser.getType(OrigCurrentType->getName().str())); + + // check edges + for (const auto &OrigEdgeCurrentType : Orig.getAllTypes()) { + // Deser.isSubType can take the same arguments as Orig.isSubType, since + // Deser should have the same types + + llvm::outs() << "Orig subtypes SIZE of: " + << OrigEdgeCurrentType->getName() << " - " + << Orig.getSubTypes(OrigEdgeCurrentType).size() << "\n"; + + llvm::outs() << "Deser subtypes SIZE of: " + << OrigEdgeCurrentType->getName() << " - " + << Deser.getSubTypes(OrigEdgeCurrentType).size() << "\n"; + + llvm::outs() << "Orig subtypes of: " << OrigEdgeCurrentType->getName() + << "\n"; + for (const auto &Curr : Orig.getSubTypes(OrigEdgeCurrentType)) { + llvm::outs() << Curr->getName() << "\n"; + } + llvm::outs() << "Deser subtypes of: " << OrigEdgeCurrentType->getName() + << "\n"; + for (const auto &Curr : Deser.getSubTypes(OrigEdgeCurrentType)) { + llvm::outs() << Curr->getName() << "\n"; + } + + bool ExpectedValue = Orig.isSubType(OrigCurrentType, OrigEdgeCurrentType); + bool DeserializedValue = + Deser.isSubType(Deser.getType(OrigCurrentType->getName().str()), + Deser.getType(OrigEdgeCurrentType->getName().str())); + + EXPECT_EQ(ExpectedValue, DeserializedValue); + } } } From d1078f590948181fff63797d2843b54b56385b49 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 5 May 2024 15:20:51 +0200 Subject: [PATCH 38/42] Fix LLVMBasedTypeHierarchy --- .../TypeHierarchy/LLVMTypeHierarchy.cpp | 63 ++++++++----------- .../LLVMTypeHierarchySerializationTest.cpp | 19 ------ 2 files changed, 25 insertions(+), 57 deletions(-) diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp index 54c840a1a..74a1dd971 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.cpp @@ -97,8 +97,9 @@ LLVMTypeHierarchy::LLVMTypeHierarchy( } if (!MatchFound) { - llvm::errs() << "No matching StructType found for Type with name: " - << SerElement.getKey(); + PHASAR_LOG_LEVEL(WARNING, + "No matching StructType found for Type with name: " + << SerElement.getKey()); } } @@ -110,29 +111,23 @@ LLVMTypeHierarchy::LLVMTypeHierarchy( TypeGraph[Vertex] = VertexProperties(StructType); TypeVFTMap[StructType] = getVirtualFunctions(*IRDBModule, *StructType); } - llvm::outs() << "NameToStructTypeSize: " << NameToStructType.size() << "\n\n"; - llvm::outs() << "TypeVertexMap: " << TypeVertexMap.size() << "\n\n"; // add all edges - llvm::outs() << "Deser Edges:\n"; for (const auto &SerElement : SerializedData.TypeGraph) { - llvm::outs() << "Key: " << SerElement.getKey().str() << "\nValues:\n"; - llvm::outs() << "SerElementTypeVert: " - << TypeVertexMap[NameToStructType[SerElement.getKey().str()]] - << "\n"; - llvm::outs() << "SerElement.getValue: " << SerElement.getValue() << "\n"; + const auto *SrcType = NameToStructType[SerElement.getKey()]; + if (!SrcType) { + continue; + } + auto Vtx = TypeVertexMap.at(SrcType); for (const auto &CurrEdge : SerElement.getValue()) { - llvm::outs() << CurrEdge << "\n"; - - llvm::outs() << "CurrEdgeTypeVertex: " - << TypeVertexMap[NameToStructType[CurrEdge]] << "\n"; + const auto *DestType = NameToStructType[CurrEdge]; + if (!SrcType) { + continue; + } + auto DestVtx = TypeVertexMap.at(DestType); - /// TODO: find out why the edge isn't being added, despite all types - /// existing, all helper variables initialized and everything serialized - /// correctly. - boost::add_edge( - TypeVertexMap[NameToStructType[SerElement.getKey().str()]], - TypeVertexMap[NameToStructType[CurrEdge]], TypeGraph); + TypeGraph[Vtx].ReachableTypes.insert(DestType); + boost::add_edge(Vtx, DestVtx, TypeGraph); } } } @@ -220,7 +215,9 @@ LLVMTypeHierarchy::getSubTypes(const llvm::Module & /*M*/, // find corresponding type info variable std::vector SubTypes; std::string ClearName = removeStructOrClassPrefix(Type); - if (const auto *TI = ClearNameTIMap.at(ClearName)) { + + if (auto It = ClearNameTIMap.find(ClearName); It != ClearNameTIMap.end()) { + const auto *TI = It->second; if (!TI->hasInitializer()) { PHASAR_LOG_LEVEL_CAT(DEBUG, "LLVMTypeHierarchy", ClearName << " does not have initializer"); @@ -236,8 +233,9 @@ LLVMTypeHierarchy::getSubTypes(const llvm::Module & /*M*/, if (Name.find(TypeInfoPrefix) != llvm::StringRef::npos) { auto ClearName = removeTypeInfoPrefix(llvm::demangle(Name.str())); - if (const auto *Type = ClearNameTypeMap.at(ClearName)) { - SubTypes.push_back(Type); + if (auto TypeIt = ClearNameTypeMap.find(ClearName); + TypeIt != ClearNameTypeMap.end()) { + SubTypes.push_back(TypeIt->second); } } } @@ -472,25 +470,14 @@ void LLVMTypeHierarchy::printAsJson(llvm::raw_ostream &OS) const { Data.PhasarConfigJsonTypeHierarchyID = PhasarConfig::JsonTypeHierarchyID().str(); - vertex_iterator VIv; - vertex_iterator VIvEnd; - - out_edge_iterator EI; - - out_edge_iterator EIEnd; // iterate all graph vertices - for (boost::tie(VIv, VIvEnd) = boost::vertices(TypeGraph); VIv != VIvEnd; - ++VIv) { - llvm::outs() << "VertexName: " << TypeGraph[*VIv].getTypeName() << "\n"; - // Data.TypeGraph[TypeGraph[*VIv].getTypeName()]; + for (auto Vtx : boost::make_iterator_range(boost::vertices(TypeGraph))) { // iterate all out edges of vertex vi_v - for (const auto &CurrReachable : TypeGraph[*VIv].ReachableTypes) { - Data.TypeGraph[TypeGraph[*VIv].getTypeName()].push_back( - CurrReachable->getName().str()); - llvm::outs() << "Reachable: " << CurrReachable->getName().str() << "\n"; + auto &SerTypes = Data.TypeGraph[TypeGraph[Vtx].getTypeName()]; + for (const auto &CurrReachable : TypeGraph[Vtx].ReachableTypes) { + SerTypes.push_back(CurrReachable->getName().str()); } } - llvm::outs() << "\n\n\n"; Data.printAsJson(OS); } diff --git a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp index 2597a0172..57d3bb4cf 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchySerializationTest.cpp @@ -39,25 +39,6 @@ void compareResults(psr::LLVMTypeHierarchy &Orig, // Deser.isSubType can take the same arguments as Orig.isSubType, since // Deser should have the same types - llvm::outs() << "Orig subtypes SIZE of: " - << OrigEdgeCurrentType->getName() << " - " - << Orig.getSubTypes(OrigEdgeCurrentType).size() << "\n"; - - llvm::outs() << "Deser subtypes SIZE of: " - << OrigEdgeCurrentType->getName() << " - " - << Deser.getSubTypes(OrigEdgeCurrentType).size() << "\n"; - - llvm::outs() << "Orig subtypes of: " << OrigEdgeCurrentType->getName() - << "\n"; - for (const auto &Curr : Orig.getSubTypes(OrigEdgeCurrentType)) { - llvm::outs() << Curr->getName() << "\n"; - } - llvm::outs() << "Deser subtypes of: " << OrigEdgeCurrentType->getName() - << "\n"; - for (const auto &Curr : Deser.getSubTypes(OrigEdgeCurrentType)) { - llvm::outs() << Curr->getName() << "\n"; - } - bool ExpectedValue = Orig.isSubType(OrigCurrentType, OrigEdgeCurrentType); bool DeserializedValue = Deser.isSubType(Deser.getType(OrigCurrentType->getName().str()), From 1a2f47abfc178ff00c657d108ea85124a98d91ff Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 8 May 2024 15:06:12 +0200 Subject: [PATCH 39/42] added operator<< statistics to printAsJson --- .../Passes/GeneralStatisticsAnalysis.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 44591281f..376bf4433 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -298,23 +298,40 @@ void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { Json["AddressTakenFunctions"] = AddressTakenFunctions; Json["Globals"] = Globals; Json["GlobalConsts"] = GlobalConsts; + Json["GlobalVariables"].push_back(Globals); + Json["GlobalVariables"].push_back(GlobalConsts); Json["ExternalGlobals"] = ExternalGlobals; Json["GlobalsDefinitions"] = GlobalsDefinitions; Json["AllocaInstructions"] = AllocaInstructions.size(); - Json["BasicBlocks"] = BasicBlocks; - Json["TotalNumPredecessorBBs"] = TotalNumPredecessorBBs; Json["CallSites"] = CallSites; + Json["IndCalls"] = IndCalls; Json["NumInlineAsm"] = NumInlineAsm; Json["MemIntrinsics"] = MemIntrinsics; - Json["IndCalls"] = IndCalls; Json["DebugIntrinsics"] = DebugIntrinsics; Json["Switches"] = Switches; - Json["Branches"] = Branches; Json["GetElementPtrs"] = GetElementPtrs; - Json["LandingPads"] = LandingPads; Json["PhiNodes"] = PhiNodes; + Json["LandingPads"] = LandingPads; + Json["BasicBlocks"] = BasicBlocks; + Json["TotalNumPredecessorBBs"] = TotalNumPredecessorBBs; + Json["Branches"] = Branches; Json["NonVoidInsts"] = NonVoidInsts; Json["ModuleName"] = ModuleName; + Json["AvgPredPerBasicBlock"].push_back(TotalNumPredecessorBBs); + Json["AvgPredPerBasicBlock"].push_back(BasicBlocks); + Json["MaxPredPerBasicBlock"] = MaxNumPredecessorBBs; + Json["AvgSuccPerBasicBlock"].push_back(TotalNumSuccessorBBs); + Json["AvgSuccPerBasicBlock"].push_back(BasicBlocks); + Json["MaxSuccPerBasicBlock"] = MaxNumSuccessorBBs; + Json["AvgOperantsPerInst"].push_back(TotalNumOperands); + Json["AvgOperantsPerInst"].push_back(Instructions); + Json["MaxNumOperands"] = MaxNumOperands; + Json["AvgUsesPerInst"].push_back(TotalNumUses); + Json["AvgUsesPerInst"].push_back(Instructions); + Json["MaxUsesPerInst"] = MaxNumUses; + Json["NumInstWithMultipleUses"] = NumInstWithMultipleUses; + Json["NonVoidInsts"] = NonVoidInsts; + Json["NumInstsUsedOutsideBB"] = NumInstsUsedOutsideBB; OS << Json; } From 4eb1f12b9b8477cbd3a977612b4df09219bb0669 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 19 May 2024 12:15:37 +0200 Subject: [PATCH 40/42] Fix GeneralStatistics printAsJson + minor --- lib/ControlFlow/CallGraphData.cpp | 2 +- .../Passes/GeneralStatisticsAnalysis.cpp | 32 +++++++++---------- lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp | 2 +- .../DIBasedTypeHierarchyData.cpp | 2 +- .../TypeHierarchy/LLVMTypeHierarchyData.cpp | 2 +- .../TypeHierarchy/LLVMVFTableData.cpp | 2 +- 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/lib/ControlFlow/CallGraphData.cpp b/lib/ControlFlow/CallGraphData.cpp index 638976b25..8b0f13a85 100644 --- a/lib/ControlFlow/CallGraphData.cpp +++ b/lib/ControlFlow/CallGraphData.cpp @@ -41,7 +41,7 @@ void CallGraphData::printAsJson(llvm::raw_ostream &OS) { } } - OS << JSON; + OS << JSON << '\n'; } CallGraphData CallGraphData::deserializeJson(const llvm::Twine &Path) { diff --git a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp index 376bf4433..ed64e4784 100644 --- a/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp +++ b/lib/PhasarLLVM/Passes/GeneralStatisticsAnalysis.cpp @@ -23,6 +23,7 @@ #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Format.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" @@ -291,6 +292,7 @@ GeneralStatistics::getRetResInstructions() const { void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { nlohmann::json Json; + Json["ModuleName"] = ModuleName; Json["Instructions"] = Instructions; Json["Functions"] = Functions; Json["ExternalFunctions"] = ExternalFunctions; @@ -298,15 +300,14 @@ void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { Json["AddressTakenFunctions"] = AddressTakenFunctions; Json["Globals"] = Globals; Json["GlobalConsts"] = GlobalConsts; - Json["GlobalVariables"].push_back(Globals); - Json["GlobalVariables"].push_back(GlobalConsts); + Json["GlobalVariables"] = Globals - GlobalConsts; Json["ExternalGlobals"] = ExternalGlobals; Json["GlobalsDefinitions"] = GlobalsDefinitions; Json["AllocaInstructions"] = AllocaInstructions.size(); Json["CallSites"] = CallSites; - Json["IndCalls"] = IndCalls; - Json["NumInlineAsm"] = NumInlineAsm; - Json["MemIntrinsics"] = MemIntrinsics; + Json["IndirectCallSites"] = IndCalls; + Json["NumInlineAssembly"] = NumInlineAsm; + Json["MemoryIntrinsics"] = MemIntrinsics; Json["DebugIntrinsics"] = DebugIntrinsics; Json["Switches"] = Switches; Json["GetElementPtrs"] = GetElementPtrs; @@ -315,25 +316,21 @@ void GeneralStatistics::printAsJson(llvm::raw_ostream &OS) const { Json["BasicBlocks"] = BasicBlocks; Json["TotalNumPredecessorBBs"] = TotalNumPredecessorBBs; Json["Branches"] = Branches; - Json["NonVoidInsts"] = NonVoidInsts; - Json["ModuleName"] = ModuleName; - Json["AvgPredPerBasicBlock"].push_back(TotalNumPredecessorBBs); - Json["AvgPredPerBasicBlock"].push_back(BasicBlocks); + Json["AvgPredPerBasicBlock"] = + double(TotalNumPredecessorBBs) / double(BasicBlocks); Json["MaxPredPerBasicBlock"] = MaxNumPredecessorBBs; - Json["AvgSuccPerBasicBlock"].push_back(TotalNumSuccessorBBs); - Json["AvgSuccPerBasicBlock"].push_back(BasicBlocks); + Json["AvgSuccPerBasicBlock"] = + double(TotalNumSuccessorBBs) / double(BasicBlocks); Json["MaxSuccPerBasicBlock"] = MaxNumSuccessorBBs; - Json["AvgOperantsPerInst"].push_back(TotalNumOperands); - Json["AvgOperantsPerInst"].push_back(Instructions); - Json["MaxNumOperands"] = MaxNumOperands; - Json["AvgUsesPerInst"].push_back(TotalNumUses); - Json["AvgUsesPerInst"].push_back(Instructions); + Json["AvgOperandsPerInst"] = double(TotalNumOperands) / double(Instructions); + Json["MaxNumOperandsPerInst"] = MaxNumOperands; + Json["AvgUsesPerInst"] = double(TotalNumUses) / double(Instructions); Json["MaxUsesPerInst"] = MaxNumUses; Json["NumInstWithMultipleUses"] = NumInstWithMultipleUses; Json["NonVoidInsts"] = NonVoidInsts; Json["NumInstsUsedOutsideBB"] = NumInstsUsedOutsideBB; - OS << Json; + OS << Json << '\n'; } nlohmann::json GeneralStatistics::getAsJson() const { @@ -405,6 +402,7 @@ llvm::raw_ostream &psr::operator<<(llvm::raw_ostream &OS, << AlignNum("Phi Nodes", Statistics.PhiNodes) << AlignNum("LandingPads", Statistics.LandingPads) << AlignNum("Basic Blocks", Statistics.BasicBlocks) + << AlignNum("Branches", Statistics.Branches) << AlignNum("Avg #pred per BasicBlock", Statistics.TotalNumPredecessorBBs, Statistics.BasicBlocks) << AlignNum("Max #pred per BasicBlock", diff --git a/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp index d9831d361..4f807c581 100644 --- a/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp +++ b/lib/PhasarLLVM/Pointer/LLVMAliasSetData.cpp @@ -39,7 +39,7 @@ void LLVMAliasSetData::printAsJson(llvm::raw_ostream &OS) { JSON["AnalyzedFunctions"].push_back(Curr); } - OS << JSON; + OS << JSON << '\n'; } LLVMAliasSetData LLVMAliasSetData::deserializeJson(const llvm::Twine &Path) { diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp index 43eef1c64..b1fc17cb2 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchyData.cpp @@ -58,7 +58,7 @@ void DIBasedTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { } } - OS << Json; + OS << Json << '\n'; } DIBasedTypeHierarchyData diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp index 450481e06..5247e8f17 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchyData.cpp @@ -48,7 +48,7 @@ void LLVMTypeHierarchyData::printAsJson(llvm::raw_ostream &OS) { } } - OS << Json; + OS << Json << '\n'; } LLVMTypeHierarchyData diff --git a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp index 65f1095dd..69d2a8da6 100644 --- a/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/LLVMVFTableData.cpp @@ -31,7 +31,7 @@ void LLVMVFTableData::printAsJson(llvm::raw_ostream &OS) const { JSON["VFT"].push_back(Curr); } - OS << JSON; + OS << JSON << '\n'; } LLVMVFTableData LLVMVFTableData::deserializeJson(const llvm::Twine &Path) { From 987050c4001f0470046162873367405d141bfc6e Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 19 May 2024 12:20:36 +0200 Subject: [PATCH 41/42] Add some more deprecations --- include/phasar/ControlFlow/CFGBase.h | 3 +- .../PhasarLLVM/Pointer/LLVMAliasGraph.h | 29 ++++++++++--------- include/phasar/TypeHierarchy/TypeHierarchy.h | 4 ++- include/phasar/TypeHierarchy/VFTable.h | 4 ++- lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp | 2 +- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/phasar/ControlFlow/CFGBase.h b/include/phasar/ControlFlow/CFGBase.h index 4067f05c1..4abfbd983 100644 --- a/include/phasar/ControlFlow/CFGBase.h +++ b/include/phasar/ControlFlow/CFGBase.h @@ -131,7 +131,8 @@ template class CFGBase { void print(ByConstRef Fun, llvm::raw_ostream &OS) const { self().printImpl(Fun, OS); } - [[nodiscard]] nlohmann::json getAsJson(ByConstRef Fun) const { + [[nodiscard, deprecated("Please use printAsJson() instead")]] nlohmann::json + getAsJson(ByConstRef Fun) const { return self().getAsJsonImpl(Fun); } diff --git a/include/phasar/PhasarLLVM/Pointer/LLVMAliasGraph.h b/include/phasar/PhasarLLVM/Pointer/LLVMAliasGraph.h index c266980b1..83c22dbef 100644 --- a/include/phasar/PhasarLLVM/Pointer/LLVMAliasGraph.h +++ b/include/phasar/PhasarLLVM/Pointer/LLVMAliasGraph.h @@ -58,8 +58,9 @@ struct AliasInfoTraits * * @brief Represents the points-to graph of a function. */ -class LLVMAliasGraph : public AnalysisPropertiesMixin, - AliasInfoBaseUtils { +class [[deprecated("Use LLVMAliasSet Instead")]] LLVMAliasGraph + : public AnalysisPropertiesMixin, + AliasInfoBaseUtils { using traits_t = AliasInfoTraits; public: @@ -126,9 +127,9 @@ class LLVMAliasGraph : public AnalysisPropertiesMixin, * considered. False, if May and Must Aliases should be * considered. */ - explicit LLVMAliasGraph( - LLVMProjectIRDB &IRDB, bool UseLazyEvaluation = true, - AliasAnalysisType PATy = AliasAnalysisType::CFLAnders); + explicit LLVMAliasGraph(LLVMProjectIRDB & IRDB, bool UseLazyEvaluation = true, + AliasAnalysisType PATy = + AliasAnalysisType::CFLAnders); /** * @brief Returns true if graph contains 0 nodes. @@ -162,15 +163,15 @@ class LLVMAliasGraph : public AnalysisPropertiesMixin, * @param F Function pointer * @return Vector with pointers. */ - std::vector - getPointersEscapingThroughReturnsForFunction(const llvm::Function *Fd) const; + std::vector getPointersEscapingThroughReturnsForFunction( + const llvm::Function *Fd) const; /** * @brief Checks if a given value is represented by a vertex in the points-to * graph. * @return True, the points-to graph contains the given value. */ - bool containsValue(llvm::Value *V); + bool containsValue(llvm::Value * V); /** * The value-vertex-map maps each Value of the points-to graph to @@ -192,8 +193,8 @@ class LLVMAliasGraph : public AnalysisPropertiesMixin, const graph_t &PAG; }; - static inline PointerVertexOrEdgePrinter - makePointerVertexOrEdgePrinter(const graph_t &PAG) { + static inline PointerVertexOrEdgePrinter makePointerVertexOrEdgePrinter( + const graph_t &PAG) { return {PAG}; } @@ -220,9 +221,9 @@ class LLVMAliasGraph : public AnalysisPropertiesMixin, AliasSetPtrTy getAliasSet(const llvm::Value *V, const llvm::Instruction *I = nullptr); - AllocationSiteSetPtrTy - getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false, - const llvm::Instruction *I = nullptr); + AllocationSiteSetPtrTy getReachableAllocationSites( + const llvm::Value *V, bool IntraProcOnly = false, + const llvm::Instruction *I = nullptr); [[nodiscard]] bool isInReachableAllocationSites( const llvm::Value *V, const llvm::Value *PotentialValue, @@ -251,7 +252,7 @@ class LLVMAliasGraph : public AnalysisPropertiesMixin, void computeAliasGraph(const llvm::Value *V); - void computeAliasGraph(llvm::Function *F); + void computeAliasGraph(llvm::Function * F); struct AllocationSiteDFSVisitor; struct ReachabilityDFSVisitor; diff --git a/include/phasar/TypeHierarchy/TypeHierarchy.h b/include/phasar/TypeHierarchy/TypeHierarchy.h index 75ff142f5..f2bf769d3 100644 --- a/include/phasar/TypeHierarchy/TypeHierarchy.h +++ b/include/phasar/TypeHierarchy/TypeHierarchy.h @@ -51,7 +51,9 @@ template class TypeHierarchy { virtual void print(llvm::raw_ostream &OS = llvm::outs()) const = 0; - [[nodiscard]] virtual nlohmann::json getAsJson() const = 0; + [[nodiscard, + deprecated("Please use printAsJson() instead")]] virtual nlohmann::json + getAsJson() const = 0; virtual void printAsJson(llvm::raw_ostream &OS) const = 0; }; diff --git a/include/phasar/TypeHierarchy/VFTable.h b/include/phasar/TypeHierarchy/VFTable.h index 83f354a8f..83c544dbc 100644 --- a/include/phasar/TypeHierarchy/VFTable.h +++ b/include/phasar/TypeHierarchy/VFTable.h @@ -38,7 +38,9 @@ template class VFTable { virtual void print(llvm::raw_ostream &OS) const = 0; - [[nodiscard]] virtual nlohmann::json getAsJson() const = 0; + [[nodiscard, + deprecated("Please use printAsJson() instead")]] virtual nlohmann::json + getAsJson() const = 0; virtual void printAsJson(llvm::raw_ostream &OS) const = 0; }; diff --git a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp index 9d4c5ee20..917a83d43 100644 --- a/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp +++ b/lib/PhasarLLVM/ControlFlow/LLVMBasedICFG.cpp @@ -458,7 +458,7 @@ void LLVMBasedICFG::printAsJsonImpl(llvm::raw_ostream &OS) const { [this](n_t Inst) { return IRDB->getInstructionId(Inst); }); } -[[nodiscard]] nlohmann::json LLVMBasedICFG::getAsJsonImpl() const { +nlohmann::json LLVMBasedICFG::getAsJsonImpl() const { return CG.getAsJson( [](f_t F) { return F->getName().str(); }, [this](n_t Inst) { return IRDB->getInstructionId(Inst); }); From a2cfbe1e504d997ec6f007a015d86b86a0b31528 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 9 Jun 2024 15:42:25 +0200 Subject: [PATCH 42/42] Fix now failing unittests --- .../TypeHierarchy/DIBasedTypeHierarchy.h | 5 ++++ .../TypeHierarchy/DIBasedTypeHierarchy.cpp | 26 ++++++++++--------- .../DIBasedTypeHierarchySerializationTest.cpp | 4 ++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h index 01b28e73c..0ea35bbdb 100644 --- a/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h +++ b/include/phasar/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.h @@ -20,6 +20,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/Support/Casting.h" #include @@ -67,6 +68,10 @@ class DIBasedTypeHierarchy [[nodiscard]] const auto &getAllVTables() const noexcept { return VTables; } [[nodiscard]] llvm::StringRef getTypeName(ClassType Type) const override { + if (const auto *CompTy = llvm::dyn_cast(Type)) { + auto Ident = CompTy->getIdentifier(); + return Ident.empty() ? CompTy->getName() : Ident; + } return Type->getName(); } diff --git a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp index 00d9cc2bd..ce8f8ab27 100644 --- a/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp +++ b/lib/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchy.cpp @@ -221,35 +221,37 @@ DIBasedTypeHierarchy::DIBasedTypeHierarchy(const LLVMProjectIRDB &IRDB) { static const llvm::DICompositeType * stringToDICompositeType(const llvm::DebugInfoFinder &DIF, - const llvm::StringRef DITypeName) { + llvm::StringRef DITypeName) { + const llvm::DICompositeType *ByName = nullptr; + bool HasUniqueByName = false; for (const auto *Type : DIF.types()) { if (const auto *DICT = llvm::dyn_cast(Type)) { auto Ident = DICT->getIdentifier(); if (Ident == DITypeName) { return DICT; } - if (Ident.empty() && DICT->getName() == DITypeName) { - return DICT; + if (DICT->getName() == DITypeName) { + HasUniqueByName = ByName == nullptr; + ByName = DICT; } } } + if (HasUniqueByName) { + return ByName; + } - llvm::report_fatal_error("DIType doesn't exist"); + llvm::report_fatal_error("DIType doesn't exist: " + DITypeName); } static const llvm::DIType *stringToDIType(const llvm::DebugInfoFinder &DIF, - const llvm::StringRef DITypeName) { + llvm::StringRef DITypeName) { for (const auto *Type : DIF.types()) { - if (Type) { - if (Type->getName() == DITypeName) { - if (const auto *DIT = llvm::dyn_cast(Type)) { - return DIT; - } - } + if (Type->getName() == DITypeName) { + return Type; } } - llvm::report_fatal_error("DIType doesn't exist"); + llvm::report_fatal_error("DIType doesn't exist " + DITypeName); } // NOLINTNEXTLINE diff --git a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp index fe51d5bdb..72ea20f23 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp +++ b/unittests/PhasarLLVM/TypeHierarchy/DIBasedTypeHierarchySerializationTest.cpp @@ -31,7 +31,9 @@ void compareResults(const psr::DIBasedTypeHierarchy &Orig, for (const auto *OrigCurrentType : Orig.getAllTypes()) { // check types const auto *DeserTy = Deser.getType(Orig.getTypeName(OrigCurrentType)); - EXPECT_EQ(OrigCurrentType, DeserTy); + EXPECT_EQ(OrigCurrentType, DeserTy) + << "Failed to match type with name '" + << Orig.getTypeName(OrigCurrentType).str() << "'"; // check edges const auto OrigSubTypes = Orig.subTypesOf(OrigCurrentType);