From 6e4134459bdb1e537731a16123f75c8d2ec66c5a Mon Sep 17 00:00:00 2001 From: Eugene Leviant Date: Sun, 1 Jul 2018 11:02:07 +0000 Subject: [Evaluator] Improve evaluation of call instruction Recommit of r335324 after buildbot failure fix llvm-svn: 336059 --- llvm/lib/Transforms/Utils/Evaluator.cpp | 69 +++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 7 deletions(-) (limited to 'llvm/lib/Transforms') diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 9440ae3ef2a..264bc21d604 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -217,6 +217,60 @@ Constant *Evaluator::ComputeLoadResult(Constant *P) { return nullptr; // don't know how to evaluate. } +Function * +Evaluator::getCalleeWithFormalArgs(CallSite &CS, + SmallVector &Formals) { + auto *V = CS.getCalledValue(); + if (auto *Fn = dyn_cast(getVal(V))) + return getFormalParams(CS, Fn, Formals) ? Fn : nullptr; + + auto *CE = dyn_cast(V); + if (!CE || CE->getOpcode() != Instruction::BitCast || + !getFormalParams(CS, cast(CE->getOperand(0)), Formals)) + return nullptr; + + return dyn_cast( + ConstantFoldLoadThroughBitcast(CE, CE->getOperand(0)->getType(), DL)); +} + +bool Evaluator::getFormalParams(CallSite &CS, Function *F, + SmallVector &Formals) { + auto *FTy = F->getFunctionType(); + if (FTy->getNumParams() > CS.getNumArgOperands()) { + LLVM_DEBUG(dbgs() << "Too few arguments for function.\n"); + return false; + } + + auto ArgI = CS.arg_begin(); + for (auto ParI = FTy->param_begin(), ParE = FTy->param_end(); ParI != ParE; + ++ParI) { + auto *ArgC = ConstantFoldLoadThroughBitcast(getVal(*ArgI), *ParI, DL); + if (!ArgC) { + LLVM_DEBUG(dbgs() << "Can not convert function argument.\n"); + return false; + } + Formals.push_back(ArgC); + ++ArgI; + } + return true; +} + +/// If call expression contains bitcast then we may need to cast +/// evaluated return value to a type of the call expression. +Constant *Evaluator::castCallResultIfNeeded(Value *CallExpr, Constant *RV) { + ConstantExpr *CE = dyn_cast(CallExpr); + if (!RV || !CE || CE->getOpcode() != Instruction::BitCast) + return RV; + + if (auto *FT = + dyn_cast(CE->getType()->getPointerElementType())) { + RV = ConstantFoldLoadThroughBitcast(RV, FT->getReturnType(), DL); + if (!RV) + LLVM_DEBUG(dbgs() << "Failed to fold bitcast call expr\n"); + } + return RV; +} + /// 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. @@ -465,20 +519,19 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, } // Resolve function pointers. - Function *Callee = dyn_cast(getVal(CS.getCalledValue())); + SmallVector Formals; + Function *Callee = getCalleeWithFormalArgs(CS, Formals); if (!Callee || Callee->isInterposable()) { LLVM_DEBUG(dbgs() << "Can not resolve function pointer.\n"); return false; // Cannot resolve. } - SmallVector Formals; - for (User::op_iterator i = CS.arg_begin(), e = CS.arg_end(); i != e; ++i) - Formals.push_back(getVal(*i)); - if (Callee->isDeclaration()) { // If this is a function we can constant fold, do it. if (Constant *C = ConstantFoldCall(CS, Callee, Formals, TLI)) { - InstResult = C; + InstResult = castCallResultIfNeeded(CS.getCalledValue(), C); + if (!InstResult) + return false; LLVM_DEBUG(dbgs() << "Constant folded function call. Result: " << *InstResult << "\n"); } else { @@ -499,7 +552,9 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, return false; } ValueStack.pop_back(); - InstResult = RetVal; + InstResult = castCallResultIfNeeded(CS.getCalledValue(), RetVal); + if (RetVal && !InstResult) + return false; if (InstResult) { LLVM_DEBUG(dbgs() << "Successfully evaluated function. Result: " -- cgit v1.2.3