-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added a uninit variables analysis with indexes
The added analysis exists as a seperate tool and does the same as the ifds-uninit analysis in phaser-cli but also remembers which indices are initialized.
- Loading branch information
1 parent
6e0f6f6
commit 1a96918
Showing
6 changed files
with
779 additions
and
0 deletions.
There are no files selected for viewing
102 changes: 102 additions & 0 deletions
102
include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesIndexed.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/****************************************************************************** | ||
* Copyright (c) 2017 Philipp Schubert. | ||
* All rights reserved. This program and the accompanying materials are made | ||
* available under the terms of LICENSE.txt. | ||
* | ||
* Contributors: | ||
* Philipp Schubert and others | ||
*****************************************************************************/ | ||
|
||
#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IFDSUninitializedVariablesStructs_H | ||
#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IFDSUninitializedVariablesStructs_H | ||
|
||
#include "phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h" | ||
#include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" | ||
#include "phasar/Utils/IndexWrapper.h" | ||
|
||
#include <llvm/ADT/ArrayRef.h> | ||
|
||
#include <llvm/IR/DerivedTypes.h> | ||
|
||
#include <llvm/IR/Value.h> | ||
|
||
#include <llvm-14/llvm/IR/Instructions.h> | ||
|
||
#include <map> | ||
#include <set> | ||
#include <string> | ||
#include <vector> | ||
|
||
namespace psr { | ||
|
||
struct LLVMAnalysisDomainIndexed : public AnalysisDomain { | ||
public: | ||
using d_t = IndexWrapper<llvm::Value>; | ||
using n_t = const llvm::Instruction *; | ||
using f_t = const llvm::Function *; | ||
using t_t = const llvm::StructType *; | ||
using v_t = const llvm::Value *; | ||
using c_t = LLVMBasedCFG; | ||
using i_t = LLVMBasedICFG; | ||
using db_t = LLVMProjectIRDB; | ||
}; | ||
|
||
using LLVMIFDSAnalysisDomainIndexed = | ||
WithBinaryValueDomain<LLVMAnalysisDomainIndexed>; | ||
|
||
class IFDSUninitializedVariablesIndexed | ||
: public IFDSTabulationProblem<LLVMIFDSAnalysisDomainIndexed> { | ||
struct UninitResult { | ||
UninitResult() = default; | ||
unsigned int Line = 0; | ||
std::string FuncName; | ||
std::string FilePath; | ||
std::string SrcCode; | ||
std::vector<std::string> VarNames; | ||
std::map<IFDSUninitializedVariablesIndexed::n_t, | ||
std::set<IFDSUninitializedVariablesIndexed::d_t>> | ||
IRTrace; | ||
[[nodiscard]] bool empty() const; | ||
void print(llvm::raw_ostream &OS); | ||
}; | ||
|
||
public: | ||
IFDSUninitializedVariablesIndexed(const LLVMProjectIRDB *IRDB, | ||
std::vector<std::string> EntryPoints = {"main"}); | ||
|
||
~IFDSUninitializedVariablesIndexed() override = default; | ||
|
||
FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override; | ||
|
||
FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) override; | ||
|
||
FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun, | ||
n_t ExitStmt, n_t RetSite) override; | ||
|
||
FlowFunctionPtrType | ||
getCallToRetFlowFunction(n_t CallSite, n_t RetSite, | ||
llvm::ArrayRef<f_t> Callees) override; | ||
|
||
FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite, | ||
f_t DestFun) override; | ||
|
||
InitialSeeds<n_t, d_t, l_t> initialSeeds() override; | ||
|
||
[[nodiscard]] d_t createZeroValue() const; | ||
|
||
[[nodiscard]] bool isZeroValue(d_t Fact) const noexcept override; | ||
|
||
void emitTextReport(const SolverResults<n_t, d_t, l_t> &Results, | ||
llvm::raw_ostream &OS = llvm::outs()) override; | ||
|
||
[[nodiscard]] const std::map<n_t, std::set<d_t>> &getAllUndefUses() const; | ||
|
||
std::vector<UninitResult> aggregateResults(); | ||
|
||
private: | ||
std::map<n_t, std::set<d_t>> UndefValueUses; | ||
}; | ||
|
||
} // namespace psr | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IndexWrapper_H | ||
#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_PROBLEMS_IndexWrapper_H | ||
|
||
#include "phasar/Utils/Printer.h" | ||
#include <set> | ||
#include <string> | ||
#include <utility> | ||
#include <vector> | ||
|
||
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" | ||
|
||
|
||
#include <llvm/IR/DerivedTypes.h> | ||
#include <llvm/IR/Value.h> | ||
#include <llvm-14/llvm/IR/Instructions.h> | ||
|
||
namespace psr { | ||
/** | ||
* @brief A wrapper around llvm::Value objects to include an indexing into the | ||
* object | ||
* | ||
*/ | ||
template <typename T> struct IndexWrapper { | ||
|
||
T const *Value; | ||
std::vector<unsigned int> Indices; | ||
|
||
public: | ||
IndexWrapper() : Value(nullptr), Indices({}){}; | ||
IndexWrapper(const IndexWrapper & Other) : Value(Other.Value), Indices(Other.Indices){}; | ||
IndexWrapper(IndexWrapper && Other) noexcept : Value(Other.Value), Indices(std::move(Other.Indices)){}; | ||
IndexWrapper &operator=(const IndexWrapper & Other) { | ||
if (this == Other) { | ||
return *this; | ||
} | ||
this->Value = Other.Value; | ||
this->Indices = Other.Indices; | ||
return *this; | ||
}; | ||
IndexWrapper &operator=(IndexWrapper && Other) noexcept { | ||
if (this == &Other) { | ||
return *this; // Handle self-assignment | ||
} | ||
// Move members from Other to this | ||
Value = Other.Value; // Move the pointer | ||
Indices = std::move(Other.Indices); // Move the vector | ||
|
||
Other.Value = nullptr; // Nullify the moved-from object's Value | ||
return *this; | ||
}; | ||
IndexWrapper(T const *Value, std::vector<unsigned int> *Indices) | ||
: Value(Value), Indices(*Indices){}; | ||
IndexWrapper(T const *Value, std::vector<unsigned int> Indices) | ||
: Value(Value), Indices(std::move(Indices)){}; | ||
IndexWrapper(T const *Value) : Value(Value), Indices({}){}; | ||
~IndexWrapper() {}; | ||
T const *getValue() const { return Value; }; | ||
|
||
[[nodiscard]] std::vector<unsigned int> getIndices() const { | ||
return Indices; | ||
}; | ||
|
||
std::set<IndexWrapper<T>> | ||
excluded(const llvm::ArrayRef<unsigned int> &ExcludedIndex) const { | ||
if (this->indexContains(ExcludedIndex)) { | ||
std::set<IndexWrapper<T>> Result = {}; | ||
std::vector<unsigned int> PrefixVector = {}; | ||
llvm::Type *Ty = this->Value->getType(); | ||
for (unsigned int I : this->Indices) { | ||
if (auto *StructType = llvm::dyn_cast<llvm::StructType>(Ty)) { | ||
for (unsigned int J = 0; J < StructType->getNumElements(); ++I) { | ||
if (I != J) { | ||
PrefixVector.push_back(I); | ||
auto Index = std::vector<unsigned int>(PrefixVector); | ||
PrefixVector.pop_back(); | ||
Result.insert(IndexWrapper<T>(this->Value, Index)); | ||
} | ||
} | ||
Ty = StructType->getTypeAtIndex(I); | ||
} | ||
if (auto *ArrayType = llvm::dyn_cast<llvm::ArrayType>(Ty)) { | ||
for (unsigned int J = 0; J < ArrayType->getNumElements(); ++I) { | ||
if (I != J) { | ||
PrefixVector.push_back(I); | ||
auto Index = std::vector<unsigned int>(PrefixVector); | ||
PrefixVector.pop_back(); | ||
Result.insert(IndexWrapper<T>(this->Value, Index)); | ||
} | ||
} | ||
Ty = ArrayType->getElementType(); | ||
} | ||
} | ||
return Result; | ||
} | ||
return {*this}; | ||
}; | ||
|
||
bool contains(const IndexWrapper<T> &Other) const { | ||
return this->Value == Other.Value && this->indexContains(Other); | ||
}; | ||
|
||
[[nodiscard]] bool | ||
contains(const llvm::ExtractValueInst &ExtractValue) const { | ||
return this->Value == ExtractValue.getAggregateOperand() && | ||
this->indexContains(ExtractValue.getIndices()); | ||
}; | ||
|
||
[[nodiscard]] bool | ||
contains(const llvm::GetElementPtrInst &GetElementPtr) const { | ||
if (this->Value == GetElementPtr.getPointerOperand() && | ||
GetElementPtr.hasIndices() && | ||
this->Indices.size() <= GetElementPtr.getNumIndices()) { | ||
for (size_t I = 0; I < this->Indices.size(); ++I) { | ||
llvm::Value *OtherI = GetElementPtr.getOperand(I + 1); | ||
if (auto *ConstantIndex = llvm::dyn_cast<llvm::ConstantInt>(OtherI)) { | ||
if ((this->Indices)[I] != ConstantIndex->getZExtValue()) { | ||
return false; | ||
} | ||
} else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
bool indexContains(const IndexWrapper<T> &Other) const { | ||
return indexContains(Other.Indices); | ||
}; | ||
|
||
[[nodiscard]] bool | ||
indexContains(const llvm::ArrayRef<unsigned int> &OtherIndices) const { | ||
if (this->Indices.size() <= OtherIndices.size()) { | ||
for (size_t I = 0; I < this->Indices.size(); ++I) { | ||
if ((this->Indices)[I] != OtherIndices[I]) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
return false; | ||
}; | ||
|
||
bool operator<(const IndexWrapper<T> &Other) const { | ||
if (this->Value < Other.Value) { | ||
return true; | ||
} | ||
for (size_t I = 0; I < this->Indices.size(); ++I) { | ||
if ((this->Indices)[I] < (Other.Indices)[I]) { | ||
return true; | ||
} | ||
if ((this->Indices)[I] > (Other.Indices)[I]) { | ||
return false; | ||
} | ||
} | ||
return false; | ||
}; | ||
|
||
bool operator==(const IndexWrapper<T> &Other) const { | ||
return (this->Value == Other.Value) && (this->Indices == Other.Indices); | ||
}; | ||
std::string str() const { | ||
return "NOT YET IMPLEMENTED"; | ||
} | ||
|
||
}; | ||
|
||
|
||
} // namespace psr | ||
|
||
// Specialize std::hash for IndexWrapper | ||
namespace std { | ||
template <typename T> | ||
struct hash<psr::IndexWrapper<T>> { | ||
std::size_t operator()(const psr::IndexWrapper<T> &IW) const { | ||
std::size_t HashValue = std::hash<T const *>()(IW.Value); | ||
|
||
for (const auto &Index : IW.Indices) { | ||
HashValue ^= std::hash<unsigned int>()(Index) + 0x9e3779b9 + (HashValue << 6) + (HashValue >> 2); | ||
} | ||
|
||
return HashValue; | ||
} | ||
}; | ||
} // namespace std | ||
|
||
#endif |
Oops, something went wrong.