123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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 (const 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);
- Constant *ComputeLoadResult(GlobalVariable *GV, Type *Ty,
- const APInt &Offset);
- /// 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|