Skip to content

Commit bde38ab

Browse files
fabianbs96pdschubertMMory
authored
Redesign ProjectIRDB (#511)
* Add new LLVMProjectIRDB (WIP integrating into rest of phasar) * Further integrate new ProjectIRDB into phasar (still WIP) * Make phasar compile again (TODO: fix unittests) * Fix unittests * cleanup * Fix EdgeDomain * Get rid of some const_casts * Fix memory_resource issue for MAC systems in PointsToSetOwner * Add comments to ProjectIRDBBase + re-add emitPreprocessedIR * minor * Make the branch work again after the reverse-merge * Fix include order in InstInterationAnalysis test * Incorporate changes from f-RedesignICFG * minor typo fixes in comments Co-authored-by: Philipp Dominik Schubert <philipp@gazar.eu> Co-authored-by: Martin Mory <mmo@mail.upb.de>
1 parent 903b229 commit bde38ab

File tree

144 files changed

+2071
-2226
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

144 files changed

+2071
-2226
lines changed

include/phasar/Controller/AnalysisController.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@
1010
#ifndef PHASAR_CONTROLLER_ANALYSISCONTROLLER_H
1111
#define PHASAR_CONTROLLER_ANALYSISCONTROLLER_H
1212

13-
#include <set>
14-
#include <string>
15-
#include <vector>
16-
17-
#include "phasar/DB/ProjectIRDB.h"
13+
#include "phasar/DB/LLVMProjectIRDB.h"
1814
#include "phasar/PhasarLLVM/AnalysisStrategy/Strategies.h"
1915
#include "phasar/PhasarLLVM/AnalysisStrategy/WholeProgramAnalysis.h"
2016
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h"
@@ -30,8 +26,13 @@
3026
#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h"
3127
#include "phasar/PhasarLLVM/Utils/DataFlowAnalysisType.h"
3228
#include "phasar/Utils/EnumFlags.h"
29+
#include "phasar/Utils/IO.h"
3330
#include "phasar/Utils/Soundness.h"
3431

32+
#include <set>
33+
#include <string>
34+
#include <vector>
35+
3536
namespace psr {
3637

3738
enum class AnalysisControllerEmitterOptions : uint32_t {
@@ -55,7 +56,7 @@ enum class AnalysisControllerEmitterOptions : uint32_t {
5556

5657
class AnalysisController {
5758
private:
58-
ProjectIRDB &IRDB;
59+
LLVMProjectIRDB &IRDB;
5960
LLVMTypeHierarchy TH;
6061
LLVMPointsToSet PT;
6162
LLVMBasedICFG ICF;
@@ -66,7 +67,6 @@ class AnalysisController {
6667
AnalysisControllerEmitterOptions EmitterOptions =
6768
AnalysisControllerEmitterOptions::None;
6869
std::string ProjectID;
69-
std::string OutDirectory;
7070
std::filesystem::path ResultDirectory;
7171
IFDSIDESolverConfig SolverConfig;
7272
[[maybe_unused]] Soundness SoundnessLevel;
@@ -149,13 +149,11 @@ class AnalysisController {
149149
}
150150
}
151151

152-
std::unique_ptr<llvm::raw_fd_ostream>
153-
openFileStream(llvm::StringRef Filename);
154-
155152
template <typename T> void emitRequestedDataFlowResults(T &WPA) {
156153
if (EmitterOptions & AnalysisControllerEmitterOptions::EmitTextReport) {
157154
if (!ResultDirectory.empty()) {
158-
if (auto OFS = openFileStream("/psr-report.txt")) {
155+
if (auto OFS =
156+
openFileStream(ResultDirectory.string() + "/psr-report.txt")) {
159157
WPA.emitTextReport(*OFS);
160158
}
161159
} else {
@@ -165,7 +163,8 @@ class AnalysisController {
165163
if (EmitterOptions &
166164
AnalysisControllerEmitterOptions::EmitGraphicalReport) {
167165
if (!ResultDirectory.empty()) {
168-
if (auto OFS = openFileStream("/psr-report.html")) {
166+
if (auto OFS =
167+
openFileStream(ResultDirectory.string() + "/psr-report.html")) {
169168
WPA.emitGraphicalReport(*OFS);
170169
}
171170
} else {
@@ -174,7 +173,8 @@ class AnalysisController {
174173
}
175174
if (EmitterOptions & AnalysisControllerEmitterOptions::EmitRawResults) {
176175
if (!ResultDirectory.empty()) {
177-
if (auto OFS = openFileStream("/psr-raw-results.txt")) {
176+
if (auto OFS = openFileStream(ResultDirectory.string() +
177+
"/psr-raw-results.txt")) {
178178
WPA.dumpResults(*OFS);
179179
}
180180
} else {
@@ -188,7 +188,7 @@ class AnalysisController {
188188
}
189189

190190
public:
191-
AnalysisController(ProjectIRDB &IRDB,
191+
AnalysisController(LLVMProjectIRDB &IRDB,
192192
std::vector<DataFlowAnalysisType> DataFlowAnalyses,
193193
std::vector<std::string> AnalysisConfigs,
194194
PointerAnalysisType PTATy, CallGraphAnalysisType CGTy,
@@ -198,7 +198,7 @@ class AnalysisController {
198198
AnalysisControllerEmitterOptions EmitterOptions,
199199
IFDSIDESolverConfig SolverConfig,
200200
const std::string &ProjectID = "default-phasar-project",
201-
const std::string &OutDirectory = "",
201+
std::filesystem::path OutDirectory = {},
202202
const nlohmann::json &PrecomputedPointsToInfo = {});
203203

204204
~AnalysisController() = default;
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/******************************************************************************
2+
* Copyright (c) 2022 Philipp Schubert.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_DB_LLVMPROJECTIRDB_H
11+
#define PHASAR_DB_LLVMPROJECTIRDB_H
12+
13+
#include "phasar/DB/ProjectIRDBBase.h"
14+
#include "phasar/PhasarLLVM/Utils/LLVMBasedContainerConfig.h"
15+
#include "phasar/Utils/MaybeUniquePtr.h"
16+
17+
#include "llvm/ADT/ArrayRef.h"
18+
#include "llvm/ADT/DenseMap.h"
19+
#include "llvm/ADT/STLExtras.h"
20+
#include "llvm/ADT/StringRef.h"
21+
#include "llvm/ADT/iterator_range.h"
22+
#include "llvm/IR/Instruction.h"
23+
#include "llvm/IR/LLVMContext.h"
24+
#include "llvm/IR/Module.h"
25+
#include "llvm/Support/raw_ostream.h"
26+
27+
#include <memory>
28+
29+
namespace psr {
30+
class LLVMProjectIRDB;
31+
32+
template <> struct ProjectIRDBTraits<LLVMProjectIRDB> {
33+
using n_t = const llvm::Instruction *;
34+
using f_t = const llvm::Function *;
35+
using m_t = const llvm::Module *;
36+
using g_t = const llvm::GlobalVariable *;
37+
};
38+
39+
class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
40+
friend ProjectIRDBBase;
41+
42+
public:
43+
/// Reads and parses the given LLVM IR file and owns the resulting IR Module
44+
explicit LLVMProjectIRDB(const llvm::Twine &IRFileName);
45+
/// Initializes the new ProjectIRDB with the given IR Module _without_ taking
46+
/// ownership. The module is not being preprocessed.
47+
///
48+
/// CAUTION: Do not manage the same LLVM Module with multiple LLVMProjectIRDB
49+
/// instances at the same time! This will confuse the ModulesToSlotTracker
50+
explicit LLVMProjectIRDB(llvm::Module *Mod);
51+
/// Initializes the new ProjectIRDB with the given IR Moduleand takes
52+
/// ownership of it
53+
explicit LLVMProjectIRDB(std::unique_ptr<llvm::Module> Mod,
54+
bool DoPreprocessing = true);
55+
56+
LLVMProjectIRDB(const LLVMProjectIRDB &) = delete;
57+
LLVMProjectIRDB &operator=(LLVMProjectIRDB &) = delete;
58+
59+
~LLVMProjectIRDB();
60+
61+
[[nodiscard]] static std::unique_ptr<llvm::Module>
62+
getParsedIRModuleOrNull(const llvm::Twine &IRFileName,
63+
llvm::LLVMContext &Ctx) noexcept;
64+
65+
/// Also use the const overload
66+
using ProjectIRDBBase::getFunction;
67+
/// Non-const overload
68+
[[nodiscard]] llvm::Function *getFunction(llvm::StringRef FunctionName) {
69+
return Mod->getFunction(FunctionName);
70+
}
71+
72+
/// Also use the const overload
73+
using ProjectIRDBBase::getFunctionDefinition;
74+
/// Non-const overload
75+
[[nodiscard]] llvm::Function *
76+
getFunctionDefinition(llvm::StringRef FunctionName);
77+
78+
/// Also use the const overload
79+
using ProjectIRDBBase::getModule;
80+
/// Non-const overload
81+
[[nodiscard]] llvm::Module *getModule() { return Mod.get(); }
82+
83+
/// Similar to getInstruction(size_t), but is also able to return global
84+
/// variables by id
85+
[[nodiscard]] const llvm::Value *getValueFromId(size_t Id) const noexcept {
86+
return Id < IdToInst.size() ? IdToInst[Id] : nullptr;
87+
}
88+
89+
void emitPreprocessedIR(llvm::raw_ostream &OS) const;
90+
91+
/// Insert a new function F into the IRDB. F should be present in the same
92+
/// llvm::Module that is managed by the IRDB. insertFunction should not be
93+
/// called twice for the same function. Use with care!
94+
void insertFunction(llvm::Function *F, bool DoPreprocessing = true);
95+
96+
private:
97+
[[nodiscard]] m_t getModuleImpl() const noexcept { return Mod.get(); }
98+
[[nodiscard]] bool debugInfoAvailableImpl() const;
99+
[[nodiscard]] FunctionRange getAllFunctionsImpl() const {
100+
return llvm::map_range(Mod->functions(),
101+
Ref2PointerConverter<llvm::Function>{});
102+
}
103+
[[nodiscard]] f_t getFunctionImpl(llvm::StringRef FunctionName) const {
104+
return Mod->getFunction(FunctionName);
105+
}
106+
[[nodiscard]] f_t
107+
getFunctionDefinitionImpl(llvm::StringRef FunctionName) const;
108+
[[nodiscard]] bool
109+
hasFunctionImpl(llvm::StringRef FunctionName) const noexcept {
110+
return Mod->getFunction(FunctionName) != nullptr;
111+
}
112+
[[nodiscard]] g_t
113+
getGlobalVariableDefinitionImpl(llvm::StringRef GlobalVariableName) const;
114+
[[nodiscard]] size_t getNumInstructionsImpl() const noexcept {
115+
return IdToInst.size() - IdOffset;
116+
}
117+
[[nodiscard]] size_t getNumFunctionsImpl() const noexcept {
118+
return Mod->size();
119+
}
120+
[[nodiscard]] size_t getNumGlobalsImpl() const noexcept {
121+
return Mod->global_size();
122+
}
123+
124+
[[nodiscard]] n_t getInstructionImpl(size_t Id) const noexcept {
125+
// Effectively make use of integer overflow here...
126+
if (Id - IdOffset < IdToInst.size() - IdOffset) {
127+
return llvm::cast<llvm::Instruction>(IdToInst[Id]);
128+
}
129+
return n_t{};
130+
}
131+
132+
[[nodiscard]] auto getAllInstructionsImpl() const noexcept {
133+
return llvm::map_range(
134+
llvm::makeArrayRef(IdToInst).drop_front(IdOffset),
135+
[](const llvm::Value *V) { return llvm::cast<llvm::Instruction>(V); });
136+
}
137+
138+
[[nodiscard]] size_t getInstructionIdImpl(n_t Inst) const {
139+
auto It = InstToId.find(Inst);
140+
assert(It != InstToId.end());
141+
return It->second;
142+
}
143+
[[nodiscard]] bool isValidImpl() const noexcept;
144+
145+
void dumpImpl() const;
146+
147+
void initInstructionIds();
148+
/// XXX Later we might get rid of the metadata IDs entirely and therefore of
149+
/// the preprocessing as well
150+
void preprocessModule(llvm::Module *NonConstMod);
151+
152+
llvm::LLVMContext Ctx;
153+
MaybeUniquePtr<llvm::Module> Mod = nullptr;
154+
size_t IdOffset = 0;
155+
llvm::SmallVector<const llvm::Value *, 0> IdToInst;
156+
llvm::DenseMap<const llvm::Value *, size_t> InstToId;
157+
};
158+
159+
/**
160+
* Revserses the getMetaDataID function
161+
*/
162+
const llvm::Value *fromMetaDataId(const LLVMProjectIRDB &IRDB,
163+
llvm::StringRef Id);
164+
165+
extern template class ProjectIRDBBase<LLVMProjectIRDB>;
166+
} // namespace psr
167+
168+
#endif // PHASAR_DB_LLVMPROJECTIRDB_H

0 commit comments

Comments
 (0)