#ifndef LLVM_TRANSFORMS_UTILS_EVALUATOR_H
#define LLVM_TRANSFORMS_UTILS_EVALUATOR_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <deque>
#include <memory>
namespace llvm {
class CallBase;
class DataLayout;
class Function;
class TargetLibraryInfo;
class Evaluator {
struct MutableAggregate;
class MutableValue {
PointerUnion<Constant *, MutableAggregate *> Val;
void clear();
bool makeMutable();
public:
MutableValue(Constant *C) { Val = C; }
MutableValue(const MutableValue &) = delete;
MutableValue(MutableValue &&Other) {
Val = Other.Val;
Other.Val = nullptr;
}
~MutableValue() { clear(); }
Type *getType() const {
if (auto *C = Val.dyn_cast<Constant *>())
return C->getType();
return Val.get<MutableAggregate *>()->Ty;
}
Constant *toConstant() const {
if (auto *C = Val.dyn_cast<Constant *>())
return C;
return Val.get<MutableAggregate *>()->toConstant();
}
Constant *read(Type *Ty, APInt Offset, const DataLayout &DL) const;
bool write(Constant *V, APInt Offset, const DataLayout &DL);
};
struct MutableAggregate {
Type *Ty;
SmallVector<MutableValue> Elements;
MutableAggregate(Type *Ty) : Ty(Ty) {}
Constant *toConstant() const;
};
public:
Evaluator(const DataLayout &DL, const TargetLibraryInfo *TLI)
: DL(DL), TLI(TLI) {
ValueStack.emplace_back();
}
~Evaluator() {
for (auto &Tmp : AllocaTmps)
if (!Tmp->use_empty())
Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType()));
}
bool EvaluateFunction(Function *F, Constant *&RetVal,
const SmallVectorImpl<Constant*> &ActualArgs);
DenseMap<GlobalVariable *, Constant *> getMutatedInitializers() const {
DenseMap<GlobalVariable *, Constant *> Result;
for (auto &Pair : MutatedMemory)
Result[Pair.first] = Pair.second.toConstant();
return Result;
}
const SmallPtrSetImpl<GlobalVariable *> &getInvariants() const {
return Invariants;
}
private:
bool EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
bool &StrippedPointerCastsForAliasAnalysis);
Constant *getVal(Value *V) {
if (Constant *CV = dyn_cast<Constant>(V)) return CV;
Constant *R = ValueStack.back().lookup(V);
assert(R && "Reference to an uncomputed value!");
return R;
}
void setVal(Value *V, Constant *C) {
ValueStack.back()[V] = C;
}
Constant *castCallResultIfNeeded(Type *ReturnType, Constant *RV);
Function *getCalleeWithFormalArgs(CallBase &CB,
SmallVectorImpl<Constant *> &Formals);
bool getFormalParams(CallBase &CB, Function *F,
SmallVectorImpl<Constant *> &Formals);
Constant *ComputeLoadResult(Constant *P, Type *Ty);
Constant *ComputeLoadResult(GlobalVariable *GV, Type *Ty,
const APInt &Offset);
std::deque<DenseMap<Value*, Constant*>> ValueStack;
SmallVector<Function*, 4> CallStack;
DenseMap<GlobalVariable *, MutableValue> MutatedMemory;
SmallVector<std::unique_ptr<GlobalVariable>, 32> AllocaTmps;
SmallPtrSet<GlobalVariable*, 8> Invariants;
SmallPtrSet<Constant*, 8> SimpleConstants;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
};
}
#endif