
The global ctor evaluator tries to evalute function calls where the call function type and function type do not match, by performing bitcasts. This currently causes a crash when calling a void function with non-void return type. I've opted to remove this functionality entirely rather than fixing this specific case. With opaque pointers, there shouldn't be a legitimate use case for this anymore, as we don't need to look through pointer type casts. Doing other bitcasts is very iffy because it ignores ABI considerations. We should at least leave adjusting the signatures to make them line up to InstCombine (which also does some iffy things, but is at least somewhat more constrained). Fixes https://github.com/llvm/llvm-project/issues/118725.
672 lines
25 KiB
C++
672 lines
25 KiB
C++
//===- Evaluator.cpp - LLVM IR evaluator ----------------------------------===//
|
|
//
|
|
// 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Transforms/Utils/Evaluator.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Analysis/ConstantFolding.h"
|
|
#include "llvm/IR/BasicBlock.h"
|
|
#include "llvm/IR/Constant.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DataLayout.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/GlobalAlias.h"
|
|
#include "llvm/IR/GlobalValue.h"
|
|
#include "llvm/IR/GlobalVariable.h"
|
|
#include "llvm/IR/InstrTypes.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
#include "llvm/IR/Type.h"
|
|
#include "llvm/IR/User.h"
|
|
#include "llvm/IR/Value.h"
|
|
#include "llvm/Support/Casting.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#define DEBUG_TYPE "evaluator"
|
|
|
|
using namespace llvm;
|
|
|
|
static inline bool
|
|
isSimpleEnoughValueToCommit(Constant *C,
|
|
SmallPtrSetImpl<Constant *> &SimpleConstants,
|
|
const DataLayout &DL);
|
|
|
|
/// Return true if the specified constant can be handled by the code generator.
|
|
/// We don't want to generate something like:
|
|
/// void *X = &X/42;
|
|
/// because the code generator doesn't have a relocation that can handle that.
|
|
///
|
|
/// This function should be called if C was not found (but just got inserted)
|
|
/// in SimpleConstants to avoid having to rescan the same constants all the
|
|
/// time.
|
|
static bool
|
|
isSimpleEnoughValueToCommitHelper(Constant *C,
|
|
SmallPtrSetImpl<Constant *> &SimpleConstants,
|
|
const DataLayout &DL) {
|
|
// Simple global addresses are supported, do not allow dllimport or
|
|
// thread-local globals.
|
|
if (auto *GV = dyn_cast<GlobalValue>(C))
|
|
return !GV->hasDLLImportStorageClass() && !GV->isThreadLocal();
|
|
|
|
// Simple integer, undef, constant aggregate zero, etc are all supported.
|
|
if (C->getNumOperands() == 0 || isa<BlockAddress>(C))
|
|
return true;
|
|
|
|
// Aggregate values are safe if all their elements are.
|
|
if (isa<ConstantAggregate>(C)) {
|
|
for (Value *Op : C->operands())
|
|
if (!isSimpleEnoughValueToCommit(cast<Constant>(Op), SimpleConstants, DL))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// We don't know exactly what relocations are allowed in constant expressions,
|
|
// so we allow &global+constantoffset, which is safe and uniformly supported
|
|
// across targets.
|
|
ConstantExpr *CE = cast<ConstantExpr>(C);
|
|
switch (CE->getOpcode()) {
|
|
case Instruction::BitCast:
|
|
// Bitcast is fine if the casted value is fine.
|
|
return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);
|
|
|
|
case Instruction::IntToPtr:
|
|
case Instruction::PtrToInt:
|
|
// int <=> ptr is fine if the int type is the same size as the
|
|
// pointer type.
|
|
if (DL.getTypeSizeInBits(CE->getType()) !=
|
|
DL.getTypeSizeInBits(CE->getOperand(0)->getType()))
|
|
return false;
|
|
return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);
|
|
|
|
// GEP is fine if it is simple + constant offset.
|
|
case Instruction::GetElementPtr:
|
|
for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
|
|
if (!isa<ConstantInt>(CE->getOperand(i)))
|
|
return false;
|
|
return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);
|
|
|
|
case Instruction::Add:
|
|
// We allow simple+cst.
|
|
if (!isa<ConstantInt>(CE->getOperand(1)))
|
|
return false;
|
|
return isSimpleEnoughValueToCommit(CE->getOperand(0), SimpleConstants, DL);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static inline bool
|
|
isSimpleEnoughValueToCommit(Constant *C,
|
|
SmallPtrSetImpl<Constant *> &SimpleConstants,
|
|
const DataLayout &DL) {
|
|
// If we already checked this constant, we win.
|
|
if (!SimpleConstants.insert(C).second)
|
|
return true;
|
|
// Check the constant.
|
|
return isSimpleEnoughValueToCommitHelper(C, SimpleConstants, DL);
|
|
}
|
|
|
|
void Evaluator::MutableValue::clear() {
|
|
if (auto *Agg = dyn_cast_if_present<MutableAggregate *>(Val))
|
|
delete Agg;
|
|
Val = nullptr;
|
|
}
|
|
|
|
Constant *Evaluator::MutableValue::read(Type *Ty, APInt Offset,
|
|
const DataLayout &DL) const {
|
|
TypeSize TySize = DL.getTypeStoreSize(Ty);
|
|
const MutableValue *V = this;
|
|
while (const auto *Agg = dyn_cast_if_present<MutableAggregate *>(V->Val)) {
|
|
Type *AggTy = Agg->Ty;
|
|
std::optional<APInt> Index = DL.getGEPIndexForOffset(AggTy, Offset);
|
|
if (!Index || Index->uge(Agg->Elements.size()) ||
|
|
!TypeSize::isKnownLE(TySize, DL.getTypeStoreSize(AggTy)))
|
|
return nullptr;
|
|
|
|
V = &Agg->Elements[Index->getZExtValue()];
|
|
}
|
|
|
|
return ConstantFoldLoadFromConst(cast<Constant *>(V->Val), Ty, Offset, DL);
|
|
}
|
|
|
|
bool Evaluator::MutableValue::makeMutable() {
|
|
Constant *C = cast<Constant *>(Val);
|
|
Type *Ty = C->getType();
|
|
unsigned NumElements;
|
|
if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
|
|
NumElements = VT->getNumElements();
|
|
} else if (auto *AT = dyn_cast<ArrayType>(Ty))
|
|
NumElements = AT->getNumElements();
|
|
else if (auto *ST = dyn_cast<StructType>(Ty))
|
|
NumElements = ST->getNumElements();
|
|
else
|
|
return false;
|
|
|
|
MutableAggregate *MA = new MutableAggregate(Ty);
|
|
MA->Elements.reserve(NumElements);
|
|
for (unsigned I = 0; I < NumElements; ++I)
|
|
MA->Elements.push_back(C->getAggregateElement(I));
|
|
Val = MA;
|
|
return true;
|
|
}
|
|
|
|
bool Evaluator::MutableValue::write(Constant *V, APInt Offset,
|
|
const DataLayout &DL) {
|
|
Type *Ty = V->getType();
|
|
TypeSize TySize = DL.getTypeStoreSize(Ty);
|
|
MutableValue *MV = this;
|
|
while (Offset != 0 ||
|
|
!CastInst::isBitOrNoopPointerCastable(Ty, MV->getType(), DL)) {
|
|
if (isa<Constant *>(MV->Val) && !MV->makeMutable())
|
|
return false;
|
|
|
|
MutableAggregate *Agg = cast<MutableAggregate *>(MV->Val);
|
|
Type *AggTy = Agg->Ty;
|
|
std::optional<APInt> Index = DL.getGEPIndexForOffset(AggTy, Offset);
|
|
if (!Index || Index->uge(Agg->Elements.size()) ||
|
|
!TypeSize::isKnownLE(TySize, DL.getTypeStoreSize(AggTy)))
|
|
return false;
|
|
|
|
MV = &Agg->Elements[Index->getZExtValue()];
|
|
}
|
|
|
|
Type *MVType = MV->getType();
|
|
MV->clear();
|
|
if (Ty->isIntegerTy() && MVType->isPointerTy())
|
|
MV->Val = ConstantExpr::getIntToPtr(V, MVType);
|
|
else if (Ty->isPointerTy() && MVType->isIntegerTy())
|
|
MV->Val = ConstantExpr::getPtrToInt(V, MVType);
|
|
else if (Ty != MVType)
|
|
MV->Val = ConstantExpr::getBitCast(V, MVType);
|
|
else
|
|
MV->Val = V;
|
|
return true;
|
|
}
|
|
|
|
Constant *Evaluator::MutableAggregate::toConstant() const {
|
|
SmallVector<Constant *, 32> Consts;
|
|
for (const MutableValue &MV : Elements)
|
|
Consts.push_back(MV.toConstant());
|
|
|
|
if (auto *ST = dyn_cast<StructType>(Ty))
|
|
return ConstantStruct::get(ST, Consts);
|
|
if (auto *AT = dyn_cast<ArrayType>(Ty))
|
|
return ConstantArray::get(AT, Consts);
|
|
assert(isa<FixedVectorType>(Ty) && "Must be vector");
|
|
return ConstantVector::get(Consts);
|
|
}
|
|
|
|
/// Return the value that would be computed by a load from P after the stores
|
|
/// reflected by 'memory' have been performed. If we can't decide, return null.
|
|
Constant *Evaluator::ComputeLoadResult(Constant *P, Type *Ty) {
|
|
APInt Offset(DL.getIndexTypeSizeInBits(P->getType()), 0);
|
|
P = cast<Constant>(P->stripAndAccumulateConstantOffsets(
|
|
DL, Offset, /* AllowNonInbounds */ true));
|
|
Offset = Offset.sextOrTrunc(DL.getIndexTypeSizeInBits(P->getType()));
|
|
if (auto *GV = dyn_cast<GlobalVariable>(P))
|
|
return ComputeLoadResult(GV, Ty, Offset);
|
|
return nullptr;
|
|
}
|
|
|
|
Constant *Evaluator::ComputeLoadResult(GlobalVariable *GV, Type *Ty,
|
|
const APInt &Offset) {
|
|
auto It = MutatedMemory.find(GV);
|
|
if (It != MutatedMemory.end())
|
|
return It->second.read(Ty, Offset, DL);
|
|
|
|
if (!GV->hasDefinitiveInitializer())
|
|
return nullptr;
|
|
return ConstantFoldLoadFromConst(GV->getInitializer(), Ty, Offset, DL);
|
|
}
|
|
|
|
static Function *getFunction(Constant *C) {
|
|
if (auto *Fn = dyn_cast<Function>(C))
|
|
return Fn;
|
|
|
|
if (auto *Alias = dyn_cast<GlobalAlias>(C))
|
|
if (auto *Fn = dyn_cast<Function>(Alias->getAliasee()))
|
|
return Fn;
|
|
return nullptr;
|
|
}
|
|
|
|
Function *
|
|
Evaluator::getCalleeWithFormalArgs(CallBase &CB,
|
|
SmallVectorImpl<Constant *> &Formals) {
|
|
auto *V = CB.getCalledOperand()->stripPointerCasts();
|
|
if (auto *Fn = getFunction(getVal(V)))
|
|
return getFormalParams(CB, Fn, Formals) ? Fn : nullptr;
|
|
return nullptr;
|
|
}
|
|
|
|
bool Evaluator::getFormalParams(CallBase &CB, Function *F,
|
|
SmallVectorImpl<Constant *> &Formals) {
|
|
auto *FTy = F->getFunctionType();
|
|
if (FTy != CB.getFunctionType()) {
|
|
LLVM_DEBUG(dbgs() << "Signature mismatch.\n");
|
|
return false;
|
|
}
|
|
|
|
for (Value *Arg : CB.args())
|
|
Formals.push_back(getVal(Arg));
|
|
return true;
|
|
}
|
|
|
|
/// Evaluate all instructions in block BB, returning true if successful, false
|
|
/// if we can't evaluate it. NewBB returns the next BB that control flows into,
|
|
/// or null upon return. StrippedPointerCastsForAliasAnalysis is set to true if
|
|
/// we looked through pointer casts to evaluate something.
|
|
bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, BasicBlock *&NextBB,
|
|
bool &StrippedPointerCastsForAliasAnalysis) {
|
|
// This is the main evaluation loop.
|
|
while (true) {
|
|
Constant *InstResult = nullptr;
|
|
|
|
LLVM_DEBUG(dbgs() << "Evaluating Instruction: " << *CurInst << "\n");
|
|
|
|
if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
|
|
if (SI->isVolatile()) {
|
|
LLVM_DEBUG(dbgs() << "Store is volatile! Can not evaluate.\n");
|
|
return false; // no volatile accesses.
|
|
}
|
|
Constant *Ptr = getVal(SI->getOperand(1));
|
|
Constant *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI);
|
|
if (Ptr != FoldedPtr) {
|
|
LLVM_DEBUG(dbgs() << "Folding constant ptr expression: " << *Ptr);
|
|
Ptr = FoldedPtr;
|
|
LLVM_DEBUG(dbgs() << "; To: " << *Ptr << "\n");
|
|
}
|
|
|
|
APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
|
|
Ptr = cast<Constant>(Ptr->stripAndAccumulateConstantOffsets(
|
|
DL, Offset, /* AllowNonInbounds */ true));
|
|
Offset = Offset.sextOrTrunc(DL.getIndexTypeSizeInBits(Ptr->getType()));
|
|
auto *GV = dyn_cast<GlobalVariable>(Ptr);
|
|
if (!GV || !GV->hasUniqueInitializer()) {
|
|
LLVM_DEBUG(dbgs() << "Store is not to global with unique initializer: "
|
|
<< *Ptr << "\n");
|
|
return false;
|
|
}
|
|
|
|
// If this might be too difficult for the backend to handle (e.g. the addr
|
|
// of one global variable divided by another) then we can't commit it.
|
|
Constant *Val = getVal(SI->getOperand(0));
|
|
if (!isSimpleEnoughValueToCommit(Val, SimpleConstants, DL)) {
|
|
LLVM_DEBUG(dbgs() << "Store value is too complex to evaluate store. "
|
|
<< *Val << "\n");
|
|
return false;
|
|
}
|
|
|
|
auto Res = MutatedMemory.try_emplace(GV, GV->getInitializer());
|
|
if (!Res.first->second.write(Val, Offset, DL))
|
|
return false;
|
|
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
|
|
if (LI->isVolatile()) {
|
|
LLVM_DEBUG(
|
|
dbgs() << "Found a Load! Volatile load, can not evaluate.\n");
|
|
return false; // no volatile accesses.
|
|
}
|
|
|
|
Constant *Ptr = getVal(LI->getOperand(0));
|
|
Constant *FoldedPtr = ConstantFoldConstant(Ptr, DL, TLI);
|
|
if (Ptr != FoldedPtr) {
|
|
Ptr = FoldedPtr;
|
|
LLVM_DEBUG(dbgs() << "Found a constant pointer expression, constant "
|
|
"folding: "
|
|
<< *Ptr << "\n");
|
|
}
|
|
InstResult = ComputeLoadResult(Ptr, LI->getType());
|
|
if (!InstResult) {
|
|
LLVM_DEBUG(
|
|
dbgs() << "Failed to compute load result. Can not evaluate load."
|
|
"\n");
|
|
return false; // Could not evaluate load.
|
|
}
|
|
|
|
LLVM_DEBUG(dbgs() << "Evaluated load: " << *InstResult << "\n");
|
|
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) {
|
|
if (AI->isArrayAllocation()) {
|
|
LLVM_DEBUG(dbgs() << "Found an array alloca. Can not evaluate.\n");
|
|
return false; // Cannot handle array allocs.
|
|
}
|
|
Type *Ty = AI->getAllocatedType();
|
|
AllocaTmps.push_back(std::make_unique<GlobalVariable>(
|
|
Ty, false, GlobalValue::InternalLinkage, UndefValue::get(Ty),
|
|
AI->getName(), /*TLMode=*/GlobalValue::NotThreadLocal,
|
|
AI->getType()->getPointerAddressSpace()));
|
|
InstResult = AllocaTmps.back().get();
|
|
LLVM_DEBUG(dbgs() << "Found an alloca. Result: " << *InstResult << "\n");
|
|
} else if (isa<CallInst>(CurInst) || isa<InvokeInst>(CurInst)) {
|
|
CallBase &CB = *cast<CallBase>(&*CurInst);
|
|
|
|
// Debug info can safely be ignored here.
|
|
if (isa<DbgInfoIntrinsic>(CB)) {
|
|
LLVM_DEBUG(dbgs() << "Ignoring debug info.\n");
|
|
++CurInst;
|
|
continue;
|
|
}
|
|
|
|
// Cannot handle inline asm.
|
|
if (CB.isInlineAsm()) {
|
|
LLVM_DEBUG(dbgs() << "Found inline asm, can not evaluate.\n");
|
|
return false;
|
|
}
|
|
|
|
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&CB)) {
|
|
if (MemSetInst *MSI = dyn_cast<MemSetInst>(II)) {
|
|
if (MSI->isVolatile()) {
|
|
LLVM_DEBUG(dbgs() << "Can not optimize a volatile memset "
|
|
<< "intrinsic.\n");
|
|
return false;
|
|
}
|
|
|
|
auto *LenC = dyn_cast<ConstantInt>(getVal(MSI->getLength()));
|
|
if (!LenC) {
|
|
LLVM_DEBUG(dbgs() << "Memset with unknown length.\n");
|
|
return false;
|
|
}
|
|
|
|
Constant *Ptr = getVal(MSI->getDest());
|
|
APInt Offset(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
|
|
Ptr = cast<Constant>(Ptr->stripAndAccumulateConstantOffsets(
|
|
DL, Offset, /* AllowNonInbounds */ true));
|
|
auto *GV = dyn_cast<GlobalVariable>(Ptr);
|
|
if (!GV) {
|
|
LLVM_DEBUG(dbgs() << "Memset with unknown base.\n");
|
|
return false;
|
|
}
|
|
|
|
Constant *Val = getVal(MSI->getValue());
|
|
// Avoid the byte-per-byte scan if we're memseting a zeroinitializer
|
|
// to zero.
|
|
if (!Val->isNullValue() || MutatedMemory.contains(GV) ||
|
|
!GV->hasDefinitiveInitializer() ||
|
|
!GV->getInitializer()->isNullValue()) {
|
|
APInt Len = LenC->getValue();
|
|
if (Len.ugt(64 * 1024)) {
|
|
LLVM_DEBUG(dbgs() << "Not evaluating large memset of size "
|
|
<< Len << "\n");
|
|
return false;
|
|
}
|
|
|
|
while (Len != 0) {
|
|
Constant *DestVal = ComputeLoadResult(GV, Val->getType(), Offset);
|
|
if (DestVal != Val) {
|
|
LLVM_DEBUG(dbgs() << "Memset is not a no-op at offset "
|
|
<< Offset << " of " << *GV << ".\n");
|
|
return false;
|
|
}
|
|
++Offset;
|
|
--Len;
|
|
}
|
|
}
|
|
|
|
LLVM_DEBUG(dbgs() << "Ignoring no-op memset.\n");
|
|
++CurInst;
|
|
continue;
|
|
}
|
|
|
|
if (II->isLifetimeStartOrEnd()) {
|
|
LLVM_DEBUG(dbgs() << "Ignoring lifetime intrinsic.\n");
|
|
++CurInst;
|
|
continue;
|
|
}
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::invariant_start) {
|
|
// We don't insert an entry into Values, as it doesn't have a
|
|
// meaningful return value.
|
|
if (!II->use_empty()) {
|
|
LLVM_DEBUG(dbgs()
|
|
<< "Found unused invariant_start. Can't evaluate.\n");
|
|
return false;
|
|
}
|
|
ConstantInt *Size = cast<ConstantInt>(II->getArgOperand(0));
|
|
Value *PtrArg = getVal(II->getArgOperand(1));
|
|
Value *Ptr = PtrArg->stripPointerCasts();
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) {
|
|
Type *ElemTy = GV->getValueType();
|
|
if (!Size->isMinusOne() &&
|
|
Size->getValue().getLimitedValue() >=
|
|
DL.getTypeStoreSize(ElemTy)) {
|
|
Invariants.insert(GV);
|
|
LLVM_DEBUG(dbgs() << "Found a global var that is an invariant: "
|
|
<< *GV << "\n");
|
|
} else {
|
|
LLVM_DEBUG(dbgs()
|
|
<< "Found a global var, but can not treat it as an "
|
|
"invariant.\n");
|
|
}
|
|
}
|
|
// Continue even if we do nothing.
|
|
++CurInst;
|
|
continue;
|
|
} else if (II->getIntrinsicID() == Intrinsic::assume) {
|
|
LLVM_DEBUG(dbgs() << "Skipping assume intrinsic.\n");
|
|
++CurInst;
|
|
continue;
|
|
} else if (II->getIntrinsicID() == Intrinsic::sideeffect) {
|
|
LLVM_DEBUG(dbgs() << "Skipping sideeffect intrinsic.\n");
|
|
++CurInst;
|
|
continue;
|
|
} else if (II->getIntrinsicID() == Intrinsic::pseudoprobe) {
|
|
LLVM_DEBUG(dbgs() << "Skipping pseudoprobe intrinsic.\n");
|
|
++CurInst;
|
|
continue;
|
|
} else {
|
|
Value *Stripped = CurInst->stripPointerCastsForAliasAnalysis();
|
|
// Only attempt to getVal() if we've actually managed to strip
|
|
// anything away, or else we'll call getVal() on the current
|
|
// instruction.
|
|
if (Stripped != &*CurInst) {
|
|
InstResult = getVal(Stripped);
|
|
}
|
|
if (InstResult) {
|
|
LLVM_DEBUG(dbgs()
|
|
<< "Stripped pointer casts for alias analysis for "
|
|
"intrinsic call.\n");
|
|
StrippedPointerCastsForAliasAnalysis = true;
|
|
InstResult = ConstantExpr::getBitCast(InstResult, II->getType());
|
|
} else {
|
|
LLVM_DEBUG(dbgs() << "Unknown intrinsic. Cannot evaluate.\n");
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!InstResult) {
|
|
// Resolve function pointers.
|
|
SmallVector<Constant *, 8> Formals;
|
|
Function *Callee = getCalleeWithFormalArgs(CB, Formals);
|
|
if (!Callee || Callee->isInterposable()) {
|
|
LLVM_DEBUG(dbgs() << "Can not resolve function pointer.\n");
|
|
return false; // Cannot resolve.
|
|
}
|
|
|
|
if (Callee->isDeclaration()) {
|
|
// If this is a function we can constant fold, do it.
|
|
if (Constant *C = ConstantFoldCall(&CB, Callee, Formals, TLI)) {
|
|
InstResult = C;
|
|
LLVM_DEBUG(dbgs() << "Constant folded function call. Result: "
|
|
<< *InstResult << "\n");
|
|
} else {
|
|
LLVM_DEBUG(dbgs() << "Can not constant fold function call.\n");
|
|
return false;
|
|
}
|
|
} else {
|
|
if (Callee->getFunctionType()->isVarArg()) {
|
|
LLVM_DEBUG(dbgs()
|
|
<< "Can not constant fold vararg function call.\n");
|
|
return false;
|
|
}
|
|
|
|
Constant *RetVal = nullptr;
|
|
// Execute the call, if successful, use the return value.
|
|
ValueStack.emplace_back();
|
|
if (!EvaluateFunction(Callee, RetVal, Formals)) {
|
|
LLVM_DEBUG(dbgs() << "Failed to evaluate function.\n");
|
|
return false;
|
|
}
|
|
ValueStack.pop_back();
|
|
InstResult = RetVal;
|
|
if (InstResult) {
|
|
LLVM_DEBUG(dbgs() << "Successfully evaluated function. Result: "
|
|
<< *InstResult << "\n\n");
|
|
} else {
|
|
LLVM_DEBUG(dbgs()
|
|
<< "Successfully evaluated function. Result: 0\n\n");
|
|
}
|
|
}
|
|
}
|
|
} else if (CurInst->isTerminator()) {
|
|
LLVM_DEBUG(dbgs() << "Found a terminator instruction.\n");
|
|
|
|
if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {
|
|
if (BI->isUnconditional()) {
|
|
NextBB = BI->getSuccessor(0);
|
|
} else {
|
|
ConstantInt *Cond =
|
|
dyn_cast<ConstantInt>(getVal(BI->getCondition()));
|
|
if (!Cond) return false; // Cannot determine.
|
|
|
|
NextBB = BI->getSuccessor(!Cond->getZExtValue());
|
|
}
|
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
|
|
ConstantInt *Val =
|
|
dyn_cast<ConstantInt>(getVal(SI->getCondition()));
|
|
if (!Val) return false; // Cannot determine.
|
|
NextBB = SI->findCaseValue(Val)->getCaseSuccessor();
|
|
} else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) {
|
|
Value *Val = getVal(IBI->getAddress())->stripPointerCasts();
|
|
if (BlockAddress *BA = dyn_cast<BlockAddress>(Val))
|
|
NextBB = BA->getBasicBlock();
|
|
else
|
|
return false; // Cannot determine.
|
|
} else if (isa<ReturnInst>(CurInst)) {
|
|
NextBB = nullptr;
|
|
} else {
|
|
// invoke, unwind, resume, unreachable.
|
|
LLVM_DEBUG(dbgs() << "Can not handle terminator.");
|
|
return false; // Cannot handle this terminator.
|
|
}
|
|
|
|
// We succeeded at evaluating this block!
|
|
LLVM_DEBUG(dbgs() << "Successfully evaluated block.\n");
|
|
return true;
|
|
} else {
|
|
SmallVector<Constant *> Ops;
|
|
for (Value *Op : CurInst->operands())
|
|
Ops.push_back(getVal(Op));
|
|
InstResult = ConstantFoldInstOperands(&*CurInst, Ops, DL, TLI);
|
|
if (!InstResult) {
|
|
LLVM_DEBUG(dbgs() << "Cannot fold instruction: " << *CurInst << "\n");
|
|
return false;
|
|
}
|
|
LLVM_DEBUG(dbgs() << "Folded instruction " << *CurInst << " to "
|
|
<< *InstResult << "\n");
|
|
}
|
|
|
|
if (!CurInst->use_empty()) {
|
|
InstResult = ConstantFoldConstant(InstResult, DL, TLI);
|
|
setVal(&*CurInst, InstResult);
|
|
}
|
|
|
|
// If we just processed an invoke, we finished evaluating the block.
|
|
if (InvokeInst *II = dyn_cast<InvokeInst>(CurInst)) {
|
|
NextBB = II->getNormalDest();
|
|
LLVM_DEBUG(dbgs() << "Found an invoke instruction. Finished Block.\n\n");
|
|
return true;
|
|
}
|
|
|
|
// Advance program counter.
|
|
++CurInst;
|
|
}
|
|
}
|
|
|
|
/// 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 Evaluator::EvaluateFunction(Function *F, Constant *&RetVal,
|
|
const SmallVectorImpl<Constant*> &ActualArgs) {
|
|
assert(ActualArgs.size() == F->arg_size() && "wrong number of arguments");
|
|
|
|
// Check to see if this function is already executing (recursion). If so,
|
|
// bail out. TODO: we might want to accept limited recursion.
|
|
if (is_contained(CallStack, F))
|
|
return false;
|
|
|
|
CallStack.push_back(F);
|
|
|
|
// Initialize arguments to the incoming values specified.
|
|
for (const auto &[ArgNo, Arg] : llvm::enumerate(F->args()))
|
|
setVal(&Arg, ActualArgs[ArgNo]);
|
|
|
|
// ExecutedBlocks - We only handle non-looping, non-recursive code. As such,
|
|
// we can only evaluate any one basic block at most once. This set keeps
|
|
// track of what we have executed so we can detect recursive cases etc.
|
|
SmallPtrSet<BasicBlock*, 32> ExecutedBlocks;
|
|
|
|
// CurBB - The current basic block we're evaluating.
|
|
BasicBlock *CurBB = &F->front();
|
|
|
|
BasicBlock::iterator CurInst = CurBB->begin();
|
|
|
|
while (true) {
|
|
BasicBlock *NextBB = nullptr; // Initialized to avoid compiler warnings.
|
|
LLVM_DEBUG(dbgs() << "Trying to evaluate BB: " << *CurBB << "\n");
|
|
|
|
bool StrippedPointerCastsForAliasAnalysis = false;
|
|
|
|
if (!EvaluateBlock(CurInst, NextBB, StrippedPointerCastsForAliasAnalysis))
|
|
return false;
|
|
|
|
if (!NextBB) {
|
|
// Successfully running until there's no next block means that we found
|
|
// the return. Fill it the return value and pop the call stack.
|
|
ReturnInst *RI = cast<ReturnInst>(CurBB->getTerminator());
|
|
if (RI->getNumOperands()) {
|
|
// The Evaluator can look through pointer casts as long as alias
|
|
// analysis holds because it's just a simple interpreter and doesn't
|
|
// skip memory accesses due to invariant group metadata, but we can't
|
|
// let users of Evaluator use a value that's been gleaned looking
|
|
// through stripping pointer casts.
|
|
if (StrippedPointerCastsForAliasAnalysis &&
|
|
!RI->getReturnValue()->getType()->isVoidTy()) {
|
|
return false;
|
|
}
|
|
RetVal = getVal(RI->getOperand(0));
|
|
}
|
|
CallStack.pop_back();
|
|
return true;
|
|
}
|
|
|
|
// Okay, we succeeded in evaluating this control flow. See if we have
|
|
// executed the new block before. If so, we have a looping function,
|
|
// which we cannot evaluate in reasonable time.
|
|
if (!ExecutedBlocks.insert(NextBB).second)
|
|
return false; // looped!
|
|
|
|
// Okay, we have never been in this block before. Check to see if there
|
|
// are any PHI nodes. If so, evaluate them with information about where
|
|
// we came from.
|
|
PHINode *PN = nullptr;
|
|
for (CurInst = NextBB->begin();
|
|
(PN = dyn_cast<PHINode>(CurInst)); ++CurInst)
|
|
setVal(PN, getVal(PN->getIncomingValueForBlock(CurBB)));
|
|
|
|
// Advance to the next block.
|
|
CurBB = NextBB;
|
|
}
|
|
}
|