Skip to content

Commit 2b4ec1c

Browse files
Misc Fixes II (#625)
* Fix some bugs * Add utils to LLVMIRToSrc * Make the Container type parameter of the flow function templates actually settable * Fix recursive template instantiation in C++20 mode * feat: boolean to toggle trim * Fix fromMetaDataId + add deserialization support for LLVMBasedICFG * pre-commit * IRDB ctor with pre-loaded IR * Add chrono utils for formatting std::chrono::duration * Real constness within SolverResults * Improve Table + minor * Fix crash in LCA * minor * Make myphasartool link properly with BUILD_SHARED_LIBS --------- Co-authored-by: Sriteja Kummita <[email protected]>
1 parent 4f568a7 commit 2b4ec1c

File tree

13 files changed

+286
-151
lines changed

13 files changed

+286
-151
lines changed

include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,12 @@ ConstantEdgeFunction<L>::join(EdgeFunctionRef<ConcreteEF> This,
425425
if (auto Default = defaultJoinOrNull<l_t>(This, OtherFunction)) {
426426
return Default;
427427
}
428+
429+
if (llvm::isa<EdgeIdentity<L>>(OtherFunction)) {
430+
// Prevent endless recursion
431+
return AllBottom<L>{};
432+
}
433+
428434
if (!OtherFunction.isConstant()) {
429435
// do not know how to join; hence ask other function to decide on this
430436
return OtherFunction.joinWith(This);

include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,6 @@ class IDESolver {
12131213
}
12141214

12151215
void printIncomingTab() const {
1216-
#ifdef DYNAMIC_LOG
12171216
IF_LOG_ENABLED(
12181217
PHASAR_LOG_LEVEL(DEBUG, "Start of incomingtab entry");
12191218
for (const auto &Cell
@@ -1231,29 +1230,27 @@ class IDESolver {
12311230
}
12321231
PHASAR_LOG_LEVEL(DEBUG, "---------------");
12331232
} PHASAR_LOG_LEVEL(DEBUG, "End of incomingtab entry");)
1234-
#endif
12351233
}
12361234

12371235
void printEndSummaryTab() const {
1238-
#ifdef DYNAMIC_LOG
12391236
IF_LOG_ENABLED(
12401237
PHASAR_LOG_LEVEL(DEBUG, "Start of endsummarytab entry");
1241-
for (const auto &Cell
1242-
: EndsummaryTab.cellVec()) {
1243-
PHASAR_LOG_LEVEL(DEBUG,
1244-
"sP: " << IDEProblem.NtoString(Cell.getRowKey()));
1245-
PHASAR_LOG_LEVEL(DEBUG,
1246-
"d1: " << IDEProblem.DtoString(Cell.getColumnKey()));
1247-
for (const auto &InnerCell : Cell.getValue().cellVec()) {
1248-
PHASAR_LOG_LEVEL(
1249-
DEBUG, " eP: " << IDEProblem.NtoString(InnerCell.getRowKey()));
1250-
PHASAR_LOG_LEVEL(DEBUG, " d2: " << IDEProblem.DtoString(
1251-
InnerCell.getColumnKey()));
1252-
PHASAR_LOG_LEVEL(DEBUG, " EF: " << InnerCell.getValue());
1253-
}
1238+
1239+
EndsummaryTab.foreachCell([this](const auto &Row, const auto &Col,
1240+
const auto &Val) {
1241+
PHASAR_LOG_LEVEL(DEBUG, "sP: " << IDEProblem.NtoString(Row));
1242+
PHASAR_LOG_LEVEL(DEBUG, "d1: " << IDEProblem.DtoString(Col));
1243+
1244+
Val.foreachCell([this](const auto &InnerRow, const auto &InnerCol,
1245+
const auto &InnerVal) {
1246+
PHASAR_LOG_LEVEL(DEBUG, " eP: " << IDEProblem.NtoString(InnerRow));
1247+
PHASAR_LOG_LEVEL(DEBUG, " d2: " << IDEProblem.DtoString(InnerCol));
1248+
PHASAR_LOG_LEVEL(DEBUG, " EF: " << InnerVal);
1249+
});
12541250
PHASAR_LOG_LEVEL(DEBUG, "---------------");
1255-
} PHASAR_LOG_LEVEL(DEBUG, "End of endsummarytab entry");)
1256-
#endif
1251+
});
1252+
1253+
PHASAR_LOG_LEVEL(DEBUG, "End of endsummarytab entry");)
12571254
}
12581255

12591256
void printComputedPathEdges() {

include/phasar/DataFlow/IfdsIde/SolverResults.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class SolverResultsBase {
9595
llvm::Instruction>,
9696
std::unordered_map<d_t, l_t>>
9797
resultsAtInLLVMSSA(ByConstRef<n_t> Stmt, bool AllowOverapproximation = false,
98-
bool StripZero = false);
98+
bool StripZero = false) const;
9999

100100
/// Returns the L-type result at the given statement for the given data-flow
101101
/// fact while respecting LLVM's SSA semantics.
@@ -118,7 +118,7 @@ class SolverResultsBase {
118118
llvm::Instruction>,
119119
l_t>
120120
resultAtInLLVMSSA(ByConstRef<n_t> Stmt, d_t Value,
121-
bool AllowOverapproximation = false);
121+
bool AllowOverapproximation = false) const;
122122

123123
[[nodiscard]] std::vector<typename Table<n_t, d_t, l_t>::Cell>
124124
getAllResultEntries() const {
@@ -129,7 +129,7 @@ class SolverResultsBase {
129129
void dumpResults(const ICFGTy &ICF, const NodePrinterBase<n_t> &NP,
130130
const DataFlowFactPrinterBase<d_t> &DP,
131131
const EdgeFactPrinterBase<l_t> &LP,
132-
llvm::raw_ostream &OS = llvm::outs()) {
132+
llvm::raw_ostream &OS = llvm::outs()) const {
133133
using f_t = typename ICFGTy::f_t;
134134

135135
PAMM_GET_INSTANCE;
@@ -179,15 +179,11 @@ class SolverResultsBase {
179179

180180
template <typename ICFGTy, typename ProblemTy>
181181
void dumpResults(const ICFGTy &ICF, const ProblemTy &IDEProblem,
182-
llvm::raw_ostream &OS = llvm::outs()) {
182+
llvm::raw_ostream &OS = llvm::outs()) const {
183183
dumpResults(ICF, IDEProblem, IDEProblem, IDEProblem, OS);
184184
}
185185

186186
private:
187-
[[nodiscard]] Derived &self() noexcept {
188-
static_assert(std::is_base_of_v<SolverResultsBase, Derived>);
189-
return static_cast<Derived &>(*this);
190-
}
191187
[[nodiscard]] const Derived &self() const noexcept {
192188
static_assert(std::is_base_of_v<SolverResultsBase, Derived>);
193189
return static_cast<const Derived &>(*this);
@@ -206,12 +202,12 @@ class SolverResults
206202
using typename base_t::l_t;
207203
using typename base_t::n_t;
208204

209-
SolverResults(Table<n_t, d_t, l_t> &ResTab, ByConstRef<d_t> ZV) noexcept
205+
SolverResults(const Table<n_t, d_t, l_t> &ResTab, ByConstRef<d_t> ZV) noexcept
210206
: Results(ResTab), ZV(ZV) {}
211207
SolverResults(Table<n_t, d_t, l_t> &&ResTab, ByConstRef<d_t> ZV) = delete;
212208

213209
private:
214-
Table<n_t, d_t, l_t> &Results;
210+
const Table<n_t, d_t, l_t> &Results;
215211
ByConstRef<D> ZV;
216212
};
217213

@@ -229,16 +225,20 @@ class OwningSolverResults
229225

230226
OwningSolverResults(Table<N, D, L> ResTab,
231227
D ZV) noexcept(std::is_nothrow_move_constructible_v<D>)
232-
: Results(std::move(ResTab)), ZV(ZV) {}
228+
: Results(std::move(ResTab)), ZV(std::move(ZV)) {}
233229

234-
[[nodiscard]] operator SolverResults<N, D, L>() const &noexcept {
230+
[[nodiscard]] SolverResults<N, D, L> get() const &noexcept {
235231
return {Results, ZV};
236232
}
233+
SolverResults<N, D, L> get() && = delete;
234+
235+
[[nodiscard]] operator SolverResults<N, D, L>() const &noexcept {
236+
return get();
237+
}
237238
operator SolverResults<N, D, L>() && = delete;
238239

239240
private:
240-
// psr::Table is not const-enabled, so we have to give out mutable references
241-
mutable Table<N, D, L> Results;
241+
Table<N, D, L> Results;
242242
D ZV;
243243
};
244244

include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/IR/Instruction.h"
2323
#include "llvm/IR/LLVMContext.h"
2424
#include "llvm/IR/Module.h"
25+
#include "llvm/Support/MemoryBufferRef.h"
2526
#include "llvm/Support/raw_ostream.h"
2627

2728
#include <memory>
@@ -48,10 +49,12 @@ class LLVMProjectIRDB : public ProjectIRDBBase<LLVMProjectIRDB> {
4849
/// CAUTION: Do not manage the same LLVM Module with multiple LLVMProjectIRDB
4950
/// instances at the same time! This will confuse the ModulesToSlotTracker
5051
explicit LLVMProjectIRDB(llvm::Module *Mod);
51-
/// Initializes the new ProjectIRDB with the given IR Moduleand takes
52+
/// Initializes the new ProjectIRDB with the given IR Module and takes
5253
/// ownership of it
5354
explicit LLVMProjectIRDB(std::unique_ptr<llvm::Module> Mod,
5455
bool DoPreprocessing = true);
56+
/// Parses the given LLVM IR file and owns the resulting IR Module
57+
explicit LLVMProjectIRDB(llvm::MemoryBufferRef Buf);
5558

5659
LLVMProjectIRDB(const LLVMProjectIRDB &) = delete;
5760
LLVMProjectIRDB &operator=(LLVMProjectIRDB &) = delete;

include/phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMSolverResults.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace psr::detail {
2424
template <typename Derived, typename N, typename D, typename L>
2525
template <typename NTy>
2626
auto SolverResultsBase<Derived, N, D, L>::resultsAtInLLVMSSA(
27-
ByConstRef<n_t> Stmt, bool AllowOverapproximation, bool StripZero) ->
27+
ByConstRef<n_t> Stmt, bool AllowOverapproximation, bool StripZero) const ->
2828
typename std::enable_if_t<
2929
std::is_same_v<std::decay_t<std::remove_pointer_t<NTy>>,
3030
llvm::Instruction>,
@@ -96,7 +96,7 @@ auto SolverResultsBase<Derived, N, D, L>::resultsAtInLLVMSSA(
9696
template <typename Derived, typename N, typename D, typename L>
9797
template <typename NTy>
9898
auto SolverResultsBase<Derived, N, D, L>::resultAtInLLVMSSA(
99-
ByConstRef<n_t> Stmt, d_t Value, bool AllowOverapproximation) ->
99+
ByConstRef<n_t> Stmt, d_t Value, bool AllowOverapproximation) const ->
100100
typename std::enable_if_t<
101101
std::is_same_v<std::decay_t<std::remove_pointer_t<NTy>>,
102102
llvm::Instruction>,

include/phasar/Utils/ChronoUtils.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/******************************************************************************
2+
* Copyright (c) 2023 Fabian Schiebel.
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_PHASARLLVM_UTILS_CHRONO_UTILS_H
11+
#define PHASAR_PHASARLLVM_UTILS_CHRONO_UTILS_H
12+
13+
#include "llvm/Support/Format.h"
14+
#include "llvm/Support/raw_ostream.h"
15+
16+
#include <chrono>
17+
18+
namespace psr {
19+
20+
/// Simple struct that allows formatting of time-durations as
21+
/// hours:minutes:seconds.microseconds.
22+
///
23+
/// \remark This feature may come into C++23, so until then, use this one.
24+
struct hms { // NOLINT
25+
std::chrono::hours Hours{};
26+
std::chrono::minutes Minutes{};
27+
std::chrono::seconds Seconds{};
28+
std::chrono::microseconds Micros{};
29+
30+
hms() noexcept = default;
31+
hms(std::chrono::nanoseconds NS) noexcept {
32+
using namespace std::chrono;
33+
34+
Hours = duration_cast<hours>(NS);
35+
NS -= Hours;
36+
Minutes = duration_cast<minutes>(NS);
37+
NS -= Minutes;
38+
Seconds = duration_cast<seconds>(NS);
39+
NS -= Seconds;
40+
Micros = duration_cast<microseconds>(NS);
41+
}
42+
43+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const hms &HMS);
44+
45+
[[nodiscard]] std::string str() const {
46+
std::string Ret;
47+
llvm::raw_string_ostream OS(Ret);
48+
OS << *this;
49+
return Ret;
50+
}
51+
};
52+
53+
} // namespace psr
54+
55+
#endif // PHASAR_PHASARLLVM_UTILS_CHRONO_UTILS_H

include/phasar/Utils/DefaultValue.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/******************************************************************************
2+
* Copyright (c) 2023 Fabian Schiebel.
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_PHASARLLVM_UTILS_DEFAULTVALUE_H
11+
#define PHASAR_PHASARLLVM_UTILS_DEFAULTVALUE_H
12+
13+
#include "phasar/Utils/ByRef.h"
14+
15+
#include <type_traits>
16+
17+
namespace psr {
18+
19+
/// Gets a (cached) reference to the default-constructed value of type T. If T
20+
/// is small and trivially default constructible, creates a temporary instead.
21+
/// Useful for getters that return ByConstRef<T> but need to handle the
22+
/// non-existing-T case
23+
template <typename T,
24+
typename = std::enable_if_t<std::is_default_constructible_v<T>>>
25+
[[nodiscard]] ByConstRef<T>
26+
getDefaultValue() noexcept(std::is_nothrow_default_constructible_v<T>) {
27+
auto DefaultConstruct = [] {
28+
if constexpr (std::is_aggregate_v<T>) {
29+
return T{};
30+
} else {
31+
return T();
32+
}
33+
};
34+
35+
if constexpr (CanEfficientlyPassByValue<T>) {
36+
return DefaultConstruct();
37+
} else {
38+
static T DefaultVal = DefaultConstruct();
39+
return DefaultVal;
40+
}
41+
}
42+
43+
} // namespace psr
44+
45+
#endif // PHASAR_PHASARLLVM_UTILS_DEFAULTVALUE_H

include/phasar/Utils/EquivalenceClassMap.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#ifndef PHASAR_UTILS_EQUIVALENCECLASSMAP_H
1111
#define PHASAR_UTILS_EQUIVALENCECLASSMAP_H
1212

13+
#include "llvm/ADT/STLExtras.h"
1314
#include "llvm/ADT/iterator_range.h"
1415

1516
#include <initializer_list>
@@ -148,10 +149,10 @@ template <typename KeyT, typename ValueT> struct EquivalenceClassMap {
148149
}
149150

150151
[[nodiscard]] const_iterator find(key_type Key) const {
151-
return find_if(StoredData.begin(), StoredData.end(),
152-
[&Key](const EquivalenceClassBucketT &Val) -> bool {
153-
return Val.first.count(Key) >= 1;
154-
});
152+
return llvm::find_if(StoredData,
153+
[&Key](const EquivalenceClassBucketT &Val) -> bool {
154+
return Val.first.count(Key) >= 1;
155+
});
155156
}
156157

157158
[[nodiscard]] std::optional<ValueT> findValue(key_type Key) const {

0 commit comments

Comments
 (0)