blob: 6a34ceba6f0536f84a2a363480e560a8329ef97c [file] [log] [blame]
//===- Evaluator.h - LLVM IR evaluator --------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Function evaluator for LLVM IR.
//
//===----------------------------------------------------------------------===//
#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;
/// This class evaluates LLVM IR, producing the Constant representing each SSA
/// instruction. Changes to global variables are stored in a mapping that can
/// be iterated over after the evaluation is complete. Once an evaluation call
/// fails, the evaluation object should not be reused.
class Evaluator {
struct MutableAggregate;
/// The evaluator represents values either as a Constant*, or as a
/// MutableAggregate, which allows changing individual aggregate elements
/// without creating a new interned Constant.
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 there are still users of the alloca, the program is doing something
// silly, e.g. storing the address of the alloca somewhere and using it
// later. Since this is undefined, we'll just make it be null.
if (!Tmp->use_empty())
Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType()));
}
/// Evaluate a call to function F, returning true if successful, false if we
/// can't evaluate it. ActualArgs contains the formal arguments for the
/// function.
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;
}
/// Casts call result to a type of bitcast call expression
Constant *castCallResultIfNeeded(Type *ReturnType, Constant *RV);
/// Given call site return callee and list of its formal arguments
Function *getCalleeWithFormalArgs(CallBase &CB,
SmallVectorImpl<Constant *> &Formals);
/// Given call site and callee returns list of callee formal argument
/// values converting them when necessary
bool getFormalParams(CallBase &CB, Function *F,
SmallVectorImpl<Constant *> &Formals);
Constant *ComputeLoadResult(Constant *P, Type *Ty);
/// As we compute SSA register values, we store their contents here. The back
/// of the deque contains the current function and the stack contains the
/// values in the calling frames.
std::deque<DenseMap<Value*, Constant*>> ValueStack;
/// This is used to detect recursion. In pathological situations we could hit
/// exponential behavior, but at least there is nothing unbounded.
SmallVector<Function*, 4> CallStack;
/// For each store we execute, we update this map. Loads check this to get
/// the most up-to-date value. If evaluation is successful, this state is
/// committed to the process.
DenseMap<GlobalVariable *, MutableValue> MutatedMemory;
/// To 'execute' an alloca, we create a temporary global variable to represent
/// its body. This vector is needed so we can delete the temporary globals
/// when we are done.
SmallVector<std::unique_ptr<GlobalVariable>, 32> AllocaTmps;
/// These global variables have been marked invariant by the static
/// constructor.
SmallPtrSet<GlobalVariable*, 8> Invariants;
/// These are constants we have checked and know to be simple enough to live
/// in a static initializer of a global.
SmallPtrSet<Constant*, 8> SimpleConstants;
const DataLayout &DL;
const TargetLibraryInfo *TLI;
};
} // end namespace llvm
#endif // LLVM_TRANSFORMS_UTILS_EVALUATOR_H