FunctionList DSNodeEquivs::getCallees(CallSite &CS) { const Function *CalledFunc = CS.getCalledFunction(); // If the called function is casted from one function type to another, peer // into the cast instruction and pull out the actual function being called. if (ConstantExpr *CExpr = dyn_cast<ConstantExpr>(CS.getCalledValue())) { if (CExpr->getOpcode() == Instruction::BitCast && isa<Function>(CExpr->getOperand(0))) CalledFunc = cast<Function>(CExpr->getOperand(0)); } FunctionList Callees; // Direct calls are simple. if (CalledFunc) { Callees.push_back(CalledFunc); return Callees; } // Okay, indirect call. // Ask the DSCallGraph what this calls... TDDataStructures &TDDS = getAnalysis<TDDataStructures>(); const DSCallGraph &DSCG = TDDS.getCallGraph(); DSCallGraph::callee_iterator CalleeIt = DSCG.callee_begin(CS); DSCallGraph::callee_iterator CalleeItEnd = DSCG.callee_end(CS); for (; CalleeIt != CalleeItEnd; ++CalleeIt) Callees.push_back(*CalleeIt); // If the callgraph doesn't give us what we want, query the DSGraph // ourselves. if (Callees.empty()) { Instruction *Inst = CS.getInstruction(); Function *Parent = Inst->getParent()->getParent(); Value *CalledValue = CS.getCalledValue(); DSNodeHandle &NH = TDDS.getDSGraph(*Parent)->getNodeForValue(CalledValue); if (!NH.isNull()) { DSNode *Node = NH.getNode(); Node->addFullFunctionList(Callees); } } // For debugging, dump out the callsites we are unable to get callees for. DEBUG( if (Callees.empty()) { errs() << "Failed to get callees for callsite:\n"; CS.getInstruction()->dump(); });
// look for a very simple pattern // coro.save // no other calls // resume or destroy call // coro.suspend // // If there are other calls between coro.save and coro.suspend, they can // potentially resume or destroy the coroutine, so it is unsafe to eliminate a // suspend point. static bool simplifySuspendPoint(CoroSuspendInst *Suspend, CoroBeginInst *CoroBegin) { auto *Save = Suspend->getCoroSave(); auto *BB = Suspend->getParent(); if (BB != Save->getParent()) return false; CallSite SingleCallSite; // Check that we have only one CallSite. for (Instruction *I = Save->getNextNode(); I != Suspend; I = I->getNextNode()) { if (isa<CoroFrameInst>(I)) continue; if (isa<CoroSubFnInst>(I)) continue; if (CallSite CS = CallSite(I)) { if (SingleCallSite) return false; else SingleCallSite = CS; } } auto *CallInstr = SingleCallSite.getInstruction(); if (!CallInstr) return false; auto *Callee = SingleCallSite.getCalledValue()->stripPointerCasts(); // See if the callsite is for resumption or destruction of the coroutine. auto *SubFn = dyn_cast<CoroSubFnInst>(Callee); if (!SubFn) return false; // Does not refer to the current coroutine, we cannot do anything with it. if (SubFn->getFrame() != CoroBegin) return false; // Replace llvm.coro.suspend with the value that results in resumption over // the resume or cleanup path. Suspend->replaceAllUsesWith(SubFn->getRawIndex()); Suspend->eraseFromParent(); Save->eraseFromParent(); // No longer need a call to coro.resume or coro.destroy. CallInstr->eraseFromParent(); if (SubFn->user_empty()) SubFn->eraseFromParent(); return true; }
CallSite GNUstep::IMPCacher::SplitSend(CallSite msgSend) { BasicBlock *lookupBB = msgSend->getParent(); Function *F = lookupBB->getParent(); Module *M = F->getParent(); Function *send = M->getFunction("objc_msgSend"); Function *send_stret = M->getFunction("objc_msgSend_stret"); Function *send_fpret = M->getFunction("objc_msgSend_fpret"); Value *self; Value *cmd; int selfIndex = 0; if ((msgSend.getCalledFunction() == send) || (msgSend.getCalledFunction() == send_fpret)) { self = msgSend.getArgument(0); cmd = msgSend.getArgument(1); } else if (msgSend.getCalledFunction() == send_stret) { selfIndex = 1; self = msgSend.getArgument(1); cmd = msgSend.getArgument(2); } else { abort(); return CallSite(); } CGBuilder B(&F->getEntryBlock(), F->getEntryBlock().begin()); Value *selfPtr = B.CreateAlloca(self->getType()); B.SetInsertPoint(msgSend.getInstruction()); B.CreateStore(self, selfPtr, true); LLVMType *impTy = msgSend.getCalledValue()->getType(); LLVMType *slotTy = PointerType::getUnqual(StructType::get(PtrTy, PtrTy, PtrTy, IntTy, impTy, PtrTy, NULL)); Value *slot; Constant *lookupFn = M->getOrInsertFunction("objc_msg_lookup_sender", slotTy, selfPtr->getType(), cmd->getType(), PtrTy, NULL); if (msgSend.isCall()) { slot = B.CreateCall3(lookupFn, selfPtr, cmd, Constant::getNullValue(PtrTy)); } else { InvokeInst *inv = cast<InvokeInst>(msgSend.getInstruction()); BasicBlock *callBB = SplitBlock(lookupBB, msgSend.getInstruction(), Owner); removeTerminator(lookupBB); B.SetInsertPoint(lookupBB); slot = B.CreateInvoke3(lookupFn, callBB, inv->getUnwindDest(), selfPtr, cmd, Constant::getNullValue(PtrTy)); addPredecssor(inv->getUnwindDest(), msgSend->getParent(), lookupBB); B.SetInsertPoint(msgSend.getInstruction()); } Value *imp = B.CreateLoad(B.CreateStructGEP(slot, 4)); msgSend.setArgument(selfIndex, B.CreateLoad(selfPtr, true)); msgSend.setCalledFunction(imp); return CallSite(slot); }
// Checks to see if a given CallSite is making an indirect call, including // cases where the indirect call is made through a bitcast. static bool isIndirectCall(CallSite &CS) { if (CS.getCalledFunction()) return false; // Check the value to see if it is merely a bitcast of a function. In // this case, it will translate to a direct function call in the resulting // assembly, so we won't treat it as an indirect call here. const Value *V = CS.getCalledValue(); if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) { return !(CE->isCast() && isa<Function>(CE->getOperand(0))); } // Otherwise, since we know it's a call, it must be an indirect call return true; }
/// OptimizeInlineAsmInst - If there are any memory operands, use /// OptimizeMemoryInst to sink their address computing into the block when /// possible / profitable. bool CodeGenPrepare::OptimizeInlineAsmInst(Instruction *I, CallSite CS, DenseMap<Value*,Value*> &SunkAddrs) { bool MadeChange = false; InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue()); // Do a prepass over the constraints, canonicalizing them, and building up the // ConstraintOperands list. std::vector<InlineAsm::ConstraintInfo> ConstraintInfos = IA->ParseConstraints(); /// ConstraintOperands - Information about all of the constraints. std::vector<TargetLowering::AsmOperandInfo> ConstraintOperands; unsigned ArgNo = 0; // ArgNo - The argument of the CallInst. for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) { ConstraintOperands. push_back(TargetLowering::AsmOperandInfo(ConstraintInfos[i])); TargetLowering::AsmOperandInfo &OpInfo = ConstraintOperands.back(); // Compute the value type for each operand. switch (OpInfo.Type) { case InlineAsm::isOutput: if (OpInfo.isIndirect) OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; case InlineAsm::isInput: OpInfo.CallOperandVal = CS.getArgument(ArgNo++); break; case InlineAsm::isClobber: // Nothing to do. break; } // Compute the constraint code and ConstraintType to use. TLI->ComputeConstraintToUse(OpInfo, SDValue(), OpInfo.ConstraintType == TargetLowering::C_Memory); if (OpInfo.ConstraintType == TargetLowering::C_Memory && OpInfo.isIndirect) { Value *OpVal = OpInfo.CallOperandVal; MadeChange |= OptimizeMemoryInst(I, OpVal, OpVal->getType(), SunkAddrs); } } return MadeChange; }
// Add calls to the registration functions around this call site. void RegisterVarargCallSites::registerCallSite(Module &M, CallSite &CS) { // Insert the registration intrinsics. if (registrationFunc == 0 || unregistrationFunc == 0) makeRegistrationFunctions(M); Instruction *inst = CS.getInstruction(); LLVMContext &C = M.getContext(); Type *VoidPtrTy = Type::getInt8PtrTy(C); Type *Int32Ty = Type::getInt32Ty(C); // Build the argument vector to vacallregister. vector<Value *> vaCallRegisterArgs(2); Value *dest = CS.getCalledValue(); Value *destPtr; // Get the function pointer casted to i8*. if (isa<Constant>(dest)) destPtr = ConstantExpr::getPointerCast(cast<Constant>(dest), VoidPtrTy); else destPtr = new BitCastInst(dest, VoidPtrTy, "", inst); vaCallRegisterArgs[0] = destPtr; vaCallRegisterArgs[1] = ConstantInt::get(Int32Ty, CS.arg_size()); // Register all the pointer arguments to this function call as well. set<Value *> pointerArguments; CallSite::arg_iterator arg = CS.arg_begin(); CallSite::arg_iterator end = CS.arg_end(); for (; arg != end; ++arg) { Value *argval = *arg; if (isa<PointerType>(argval->getType())) { if (pointerArguments.find(argval) == pointerArguments.end()) { pointerArguments.insert(argval); vaCallRegisterArgs.push_back(argval); } } } // End the argument list with a NULL parameter. vaCallRegisterArgs.push_back( ConstantPointerNull::get(cast<PointerType>(VoidPtrTy)) ); // Add the registration call before the call site. CallInst::Create(registrationFunc, vaCallRegisterArgs, "", inst); // Add the unregistration call after the call site. Instruction *unreg = CallInst::Create(unregistrationFunc); unreg->insertAfter(inst); return; }
// // Method: visitCallSite() // // Description: // Examine the specified call site. If it is an indirect call, mark it for // transformation into a direct call. // void Devirtualize::visitCallSite (CallSite &CS) { // // First, determine if this is a direct call. If so, then just ignore it. // Value * CalledValue = CS.getCalledValue(); if (isa<Function>(CalledValue->stripPointerCasts())) return; // // Second, we will only transform those call sites which are complete (i.e., // for which we know all of the call targets). // if (!(CTF->isComplete(CS))) return; // // This is an indirect call site. Put it in the worklist of call sites to // transforms. // Worklist.push_back (CS.getInstruction()); return; }
void Preparer::expandCallSite(CallSite CS) { // Skip the callsites that are not calling a va function. Value *Callee = CS.getCalledValue(); FunctionType *CalleeType = cast<FunctionType>( cast<PointerType>(Callee->getType())->getElementType()); if (!CalleeType->isVarArg()) { return; } vector<Value *> Args; for (CallSite::arg_iterator ArgI = CS.arg_begin(); ArgI != CS.arg_end(); ArgI++) { Args.push_back(*ArgI); } Args.push_back(ConstantInt::get( IntegerType::get(CS.getInstruction()->getContext(), 8), 0)); string InstName = ""; if (CS.getInstruction()->getName() != "") InstName = CS.getInstruction()->getName().str() + ".padded"; if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) { CallInst *NewCI = CallInst::Create(Callee, Args, InstName, CI); NewCI->setAttributes(CI->getAttributes()); CI->replaceAllUsesWith(NewCI); CI->eraseFromParent(); } else if (InvokeInst *II = dyn_cast<InvokeInst>(CS.getInstruction())) { InvokeInst *NewII = InvokeInst::Create(Callee, II->getNormalDest(), II->getUnwindDest(), Args, InstName, II); NewII->setAttributes(II->getAttributes()); II->replaceAllUsesWith(NewII); II->eraseFromParent(); } }
/*! * This method identify which is value sym and which is object sym */ void SymbolTableInfo::buildMemModel(llvm::Module& module) { analysisUtil::increaseStackSize(); prePassSchedule(module); mod = &module; maxFieldLimit = maxFieldNumLimit; // Object #0 is black hole the object that may point to any object assert(totalSymNum == BlackHole && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, BlackHole)); createBlkOrConstantObj(BlackHole); // Object #1 always represents the constant assert(totalSymNum == ConstantObj && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, ConstantObj)); createBlkOrConstantObj(ConstantObj); // Pointer #2 always represents the pointer points-to black hole. assert(totalSymNum == BlkPtr && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum++, BlkPtr)); // Pointer #3 always represents the null pointer. assert(totalSymNum == NullPtr && "Something changed!"); symTyMap.insert(std::make_pair(totalSymNum, NullPtr)); // Add symbols for all the globals . for (Module::global_iterator I = module.global_begin(), E = module.global_end(); I != E; ++I) { collectSym(&*I); } // Add symbols for all the global aliases for (Module::alias_iterator I = module.alias_begin(), E = module.alias_end(); I != E; I++) { collectSym(&*I); } // Add symbols for all of the functions and the instructions in them. for (Module::iterator F = module.begin(), E = module.end(); F != E; ++F) { collectSym(&*F); collectRet(&*F); if (F->getFunctionType()->isVarArg()) collectVararg(&*F); // Add symbols for all formal parameters. for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { collectSym(&*I); } // collect and create symbols inside the function body for (inst_iterator II = inst_begin(&*F), E = inst_end(&*F); II != E; ++II) { const Instruction *inst = &*II; collectSym(inst); // initialization for some special instructions //{@ if (const StoreInst *st = dyn_cast<StoreInst>(inst)) { collectSym(st->getPointerOperand()); collectSym(st->getValueOperand()); } else if (const LoadInst *ld = dyn_cast<LoadInst>(inst)) { collectSym(ld->getPointerOperand()); } else if (const PHINode *phi = dyn_cast<PHINode>(inst)) { for (u32_t i = 0; i < phi->getNumIncomingValues(); ++i) { collectSym(phi->getIncomingValue(i)); } } else if (const GetElementPtrInst *gep = dyn_cast<GetElementPtrInst>( inst)) { collectSym(gep->getPointerOperand()); } else if (const SelectInst *sel = dyn_cast<SelectInst>(inst)) { collectSym(sel->getTrueValue()); collectSym(sel->getFalseValue()); } else if (const CastInst *cast = dyn_cast<CastInst>(inst)) { collectSym(cast->getOperand(0)); } else if (const ReturnInst *ret = dyn_cast<ReturnInst>(inst)) { if(ret->getReturnValue()) collectSym(ret->getReturnValue()); } else if (isCallSite(inst) && isInstrinsicDbgInst(inst)==false) { CallSite cs = analysisUtil::getLLVMCallSite(inst); callSiteSet.insert(cs); for (CallSite::arg_iterator it = cs.arg_begin(); it != cs.arg_end(); ++it) { collectSym(*it); } // Calls to inline asm need to be added as well because the callee isn't // referenced anywhere else. const Value *Callee = cs.getCalledValue(); collectSym(Callee); //TODO handle inlineAsm ///if (isa<InlineAsm>(Callee)) } //@} } } }
// // Method: visitCallSite() // // Description: // This method transforms a call site. A call site may either be a call // instruction or an invoke instruction. // // Inputs: // CS - The call site representing the instruction that should be transformed. // void FuncTransform::visitCallSite(CallSite& CS) { const Function *CF = CS.getCalledFunction(); Instruction *TheCall = CS.getInstruction(); bool thread_creation_point = false; // // Get the value that is called at this call site. Strip away any pointer // casts that do not change the representation of the data (i.e., are // lossless casts). // Value * CalledValue = CS.getCalledValue()->stripPointerCasts(); // // The CallSite::getCalledFunction() method is not guaranteed to strip off // pointer casts. If no called function was found, manually strip pointer // casts off of the called value and see if we get a function. If so, this // is a direct call, and we want to update CF accordingly. // if (!CF) CF = dyn_cast<Function>(CalledValue); // // Do not change any inline assembly code. // if (isa<InlineAsm>(TheCall->getOperand(0))) { errs() << "INLINE ASM: ignoring. Hoping that's safe.\n"; return; } // // Ignore calls to NULL pointers or undefined values. // if ((isa<ConstantPointerNull>(CalledValue)) || (isa<UndefValue>(CalledValue))) { errs() << "WARNING: Ignoring call using NULL/Undef function pointer.\n"; return; } // If this function is one of the memory manipulating functions built into // libc, emulate it with pool calls as appropriate. if (CF && CF->isDeclaration()) { std::string Name = CF->getName(); if (Name == "free" || Name == "cfree") { visitFreeCall(CS); return; } else if (Name == "malloc") { visitMallocCall(CS); return; } else if (Name == "calloc") { visitCallocCall(CS); return; } else if (Name == "realloc") { visitReallocCall(CS); return; } else if (Name == "memalign" || Name == "posix_memalign") { visitMemAlignCall(CS); return; } else if (Name == "strdup") { visitStrdupCall(CS); return; } else if (Name == "valloc") { errs() << "VALLOC USED BUT NOT HANDLED!\n"; abort(); } else if (unsigned PoolArgc = PAInfo.getNumInitialPoolArguments(Name)) { visitRuntimeCheck(CS, PoolArgc); return; } else if (Name == "pthread_create") { thread_creation_point = true; // // Get DSNode representing the DSNode of the function pointer Value of // the pthread_create call // DSNode* thread_callee_node = G->getNodeForValue(CS.getArgument(2)).getNode(); if (!thread_callee_node) { assert(0 && "apparently you need this code"); FuncInfo *CFI = PAInfo.getFuncInfo(*CF); thread_callee_node = G->getNodeForValue(CFI->MapValueToOriginal(CS.getArgument(2))).getNode(); } // Fill in CF with the name of one of the functions in thread_callee_node CF = const_cast<Function*>(dyn_cast<Function>(*thread_callee_node->globals_begin())); } } // // We need to figure out which local pool descriptors correspond to the pool // descriptor arguments passed into the function call. Calculate a mapping // from callee DSNodes to caller DSNodes. We construct a partial isomophism // between the graphs to figure out which pool descriptors need to be passed // in. The roots of this mapping is found from arguments and return values. // DataStructures& Graphs = PAInfo.getGraphs(); DSGraph::NodeMapTy NodeMapping; Instruction *NewCall; Value *NewCallee; std::vector<const DSNode*> ArgNodes; DSGraph *CalleeGraph; // The callee graph // For indirect callees, find any callee since all DS graphs have been // merged. if (CF) { // Direct calls are nice and simple. DEBUG(errs() << " Handling direct call: " << *TheCall << "\n"); // // Do not try to add pool handles to the function if it: // a) Already calls a cloned function; or // b) Calls a function which was never cloned. // // For such a call, just replace any arguments that take original functions // with their cloned function poiner values. // FuncInfo *CFI = PAInfo.getFuncInfo(*CF); if (CFI == 0 || CFI->Clone == 0) { // Nothing to transform... visitInstruction(*TheCall); return; } // // Oh, dear. We must add pool descriptors to this direct call. // NewCallee = CFI->Clone; ArgNodes = CFI->ArgNodes; assert ((Graphs.hasDSGraph (*CF)) && "Function has no ECGraph!\n"); CalleeGraph = Graphs.getDSGraph(*CF); } else { DEBUG(errs() << " Handling indirect call: " << *TheCall << "\n"); DSGraph *G = Graphs.getGlobalsGraph(); DSGraph::ScalarMapTy& SM = G->getScalarMap(); // Here we fill in CF with one of the possible called functions. Because we // merged together all of the arguments to all of the functions in the // equivalence set, it doesn't really matter which one we pick. // (If the function was cloned, we have to map the cloned call instruction // in CS back to the original call instruction.) Instruction *OrigInst = cast<Instruction>(getOldValueIfAvailable(CS.getInstruction())); // // Attempt to get one of the function targets of this indirect call site by // looking at the call graph constructed by the points-to analysis. Be // sure to use the original call site from the original function; the // points-to analysis has no information on the clones we've created. // // Also, look for the target that has the greatest number of arguments that // have associated DSNodes. This ensures that we pass the maximum number // of pools possible and prevents us from eliding a pool because we're // examining a target that doesn't need it. // const DSCallGraph & callGraph = Graphs.getCallGraph(); DSCallGraph::callee_iterator I = callGraph.callee_begin(OrigInst); for (; I != callGraph.callee_end(OrigInst); ++I) { for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(*I), sccee = callGraph.scc_end(*I); sccii != sccee; ++sccii){ if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end()) continue; // // Get the information for this function. Since this is coming from // DSA, it should be an original function. // // This call site calls a function, that is not defined in this module if (!(Graphs.hasDSGraph(**sccii))) return; // For all other cases Func Info must exist. PAInfo.getFuncInfo(**sccii); // // If this target takes more DSNodes than the last one we found, then // make *this* target our canonical target. // CF = *sccii; break; } } if(!CF){ const Function *F1 = OrigInst->getParent()->getParent(); F1 = callGraph.sccLeader(&*F1); for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(F1), sccee = callGraph.scc_end(F1); sccii != sccee; ++sccii){ if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end()) continue; // // Get the information for this function. Since this is coming from DSA, // it should be an original function. // // This call site calls a function, that is not defined in this module if (!(Graphs.hasDSGraph(**sccii))) return; // For all other cases Func Info must exist. PAInfo.getFuncInfo(**sccii); // // If this target takes more DSNodes than the last one we found, then // make *this* target our canonical target. // CF = *sccii; } } // Assuming the call graph is always correct. And if the call graph reports, // no callees, we can assume that it is right. // // If we didn't find the callee in the constructed call graph, try // checking in the DSNode itself. // This isn't ideal as it means that this call site didn't have inlining // happen. // // // If we still haven't been able to find a target function of the call site // to transform, do nothing. // // One may be tempted to think that we should always have at least one // target, but this is not true. There are perfectly acceptable (but // strange) programs for which no function targets exist. Function // pointers loaded from undef values, for example, will have no targets. // if (!CF) return; // // It's possible that this program has indirect call targets that are // not defined in this module. Do not transformation for such functions. // if (!(Graphs.hasDSGraph(*CF))) return; // // Get the common graph for the set of functions this call may invoke. // assert ((Graphs.hasDSGraph(*CF)) && "Function has no DSGraph!\n"); CalleeGraph = Graphs.getDSGraph(*CF); #ifndef NDEBUG // Verify that all potential callees at call site have the same DS graph. DSCallGraph::callee_iterator E = Graphs.getCallGraph().callee_end(OrigInst); for (; I != E; ++I) { const Function * F = *I; assert (F); if (!(F)->isDeclaration()) assert(CalleeGraph == Graphs.getDSGraph(**I) && "Callees at call site do not have a common graph!"); } #endif // Find the DS nodes for the arguments that need to be added, if any. FuncInfo *CFI = PAInfo.getFuncInfo(*CF); assert(CFI && "No function info for callee at indirect call?"); ArgNodes = CFI->ArgNodes; if (ArgNodes.empty()) return; // No arguments to add? Transformation is a noop! // Cast the function pointer to an appropriate type! std::vector<Type*> ArgTys(ArgNodes.size(), PoolAllocate::PoolDescPtrTy); for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) ArgTys.push_back((*I)->getType()); FunctionType *FTy = FunctionType::get(TheCall->getType(), ArgTys, false); PointerType *PFTy = PointerType::getUnqual(FTy); // If there are any pool arguments cast the func ptr to the right type. NewCallee = CastInst::CreatePointerCast(CS.getCalledValue(), PFTy, "tmp", TheCall); } // // FIXME: Why do we disable strict checking when calling the // DSGraph::computeNodeMapping() method? // Function::const_arg_iterator FAI = CF->arg_begin(), E = CF->arg_end(); CallSite::arg_iterator AI = CS.arg_begin() + (thread_creation_point ? 3 : 0); CallSite::arg_iterator AE = CS.arg_end(); for ( ; FAI != E && AI != AE; ++FAI, ++AI) if (!isa<Constant>(*AI)) { DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(FAI), getDSNodeHFor(*AI), NodeMapping, false); } //assert(AI == AE && "Varargs calls not handled yet!"); // Map the return value as well... if (isa<PointerType>(TheCall->getType())) DSGraph::computeNodeMapping(CalleeGraph->getReturnNodeFor(*CF), getDSNodeHFor(TheCall), NodeMapping, false); // This code seems redundant (and crashes occasionally) // There is no reason to map globals here, since they are not passed as // arguments // // Map the nodes that are pointed to by globals. // DSScalarMap &CalleeSM = CalleeGraph->getScalarMap(); // for (DSScalarMap::global_iterator GI = G.getScalarMap().global_begin(), // E = G.getScalarMap().global_end(); GI != E; ++GI) // if (CalleeSM.count(*GI)) // DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(*GI), // getDSNodeHFor(*GI), // NodeMapping, false); // // Okay, now that we have established our mapping, we can figure out which // pool descriptors to pass in... // // Note: // There used to be code here that would create a new pool before the // function call and destroy it after the function call. This could would // get triggered if bounds checking was disbled or the DSNode for the // argument was an array value. // // I believe that code was incorrect; an argument may have a NULL pool handle // (i.e., no pool handle) because the pool allocation heuristic used simply // decided not to assign that value a pool. The argument may alias data // that should not be freed after the function call is complete, so calling // pooldestroy() after the call would free data, causing dangling pointer // dereference errors. // std::vector<Value*> Args; for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) { Value *ArgVal = Constant::getNullValue(PoolAllocate::PoolDescPtrTy); if (NodeMapping.count(ArgNodes[i])) { if (DSNode *LocalNode = NodeMapping[ArgNodes[i]].getNode()) if (FI.PoolDescriptors.count(LocalNode)) ArgVal = FI.PoolDescriptors.find(LocalNode)->second; } Args.push_back(ArgVal); } // Add the rest of the arguments unless we're a thread creation point, in which case we only need the pools if(!thread_creation_point) Args.insert(Args.end(), CS.arg_begin(), CS.arg_end()); // // There are circumstances where a function is casted to another type and // then called (que horible). We need to perform a similar cast if the // type doesn't match the number of arguments. // if (Function * NewFunction = dyn_cast<Function>(NewCallee)) { FunctionType * NewCalleeType = NewFunction->getFunctionType(); if (NewCalleeType->getNumParams() != Args.size()) { std::vector<Type *> Types; Type * FuncTy = FunctionType::get (NewCalleeType->getReturnType(), Types, true); FuncTy = PointerType::getUnqual (FuncTy); NewCallee = new BitCastInst (NewCallee, FuncTy, "", TheCall); } } std::string Name = TheCall->getName(); TheCall->setName(""); if(thread_creation_point) { Module *M = CS.getInstruction()->getParent()->getParent()->getParent(); Value* pthread_replacement = M->getFunction("poolalloc_pthread_create"); std::vector<Value*> thread_args; //Push back original thread arguments through the callee thread_args.push_back(CS.getArgument(0)); thread_args.push_back(CS.getArgument(1)); thread_args.push_back(CS.getArgument(2)); //Push back the integer argument saying how many uses there are thread_args.push_back(Constant::getIntegerValue(llvm::Type::getInt32Ty(M->getContext()),APInt(32,Args.size()))); thread_args.insert(thread_args.end(),Args.begin(),Args.end()); thread_args.push_back(CS.getArgument(3)); //Make the thread creation call NewCall = CallInst::Create(pthread_replacement, thread_args, Name,TheCall); } else if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) { NewCall = InvokeInst::Create (NewCallee, II->getNormalDest(), II->getUnwindDest(), Args, Name, TheCall); } else { NewCall = CallInst::Create (NewCallee, Args, Name, TheCall); } // Add all of the uses of the pool descriptor for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) AddPoolUse(*NewCall, Args[i], PoolUses); TheCall->replaceAllUsesWith(NewCall); DEBUG(errs() << " Result Call: " << *NewCall << "\n"); if (!TheCall->getType()->isVoidTy()) { // If we are modifying the original function, update the DSGraph... DSGraph::ScalarMapTy &SM = G->getScalarMap(); DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall); if (CII != SM.end()) { SM[NewCall] = CII->second; SM.erase(CII); // Destroy the CallInst } else if (!FI.NewToOldValueMap.empty()) { // Otherwise, if this is a clone, update the NewToOldValueMap with the new // CI return value. UpdateNewToOldValueMap(TheCall, NewCall); } } else if (!FI.NewToOldValueMap.empty()) { UpdateNewToOldValueMap(TheCall, NewCall); } // // Copy over the calling convention and attributes of the original call // instruction to the new call instruction. // CallSite(NewCall).setCallingConv(CallSite(TheCall).getCallingConv()); TheCall->eraseFromParent(); visitInstruction(*NewCall); }
void Lint::visitCallSite(CallSite CS) { Instruction &I = *CS.getInstruction(); Value *Callee = CS.getCalledValue(); visitMemoryReference(I, Callee, MemoryLocation::UnknownSize, 0, nullptr, MemRef::Callee); if (Function *F = dyn_cast<Function>(findValue(Callee, /*OffsetOk=*/false))) { Assert(CS.getCallingConv() == F->getCallingConv(), "Undefined behavior: Caller and callee calling convention differ", &I); FunctionType *FT = F->getFunctionType(); unsigned NumActualArgs = CS.arg_size(); Assert(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs : FT->getNumParams() == NumActualArgs, "Undefined behavior: Call argument count mismatches callee " "argument count", &I); Assert(FT->getReturnType() == I.getType(), "Undefined behavior: Call return type mismatches " "callee return type", &I); // Check argument types (in case the callee was casted) and attributes. // TODO: Verify that caller and callee attributes are compatible. Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end(); CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); for (; AI != AE; ++AI) { Value *Actual = *AI; if (PI != PE) { Argument *Formal = &*PI++; Assert(Formal->getType() == Actual->getType(), "Undefined behavior: Call argument type mismatches " "callee parameter type", &I); // Check that noalias arguments don't alias other arguments. This is // not fully precise because we don't know the sizes of the dereferenced // memory regions. if (Formal->hasNoAliasAttr() && Actual->getType()->isPointerTy()) for (CallSite::arg_iterator BI = CS.arg_begin(); BI != AE; ++BI) if (AI != BI && (*BI)->getType()->isPointerTy()) { AliasResult Result = AA->alias(*AI, *BI); Assert(Result != MustAlias && Result != PartialAlias, "Unusual: noalias argument aliases another argument", &I); } // Check that an sret argument points to valid memory. if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { Type *Ty = cast<PointerType>(Formal->getType())->getElementType(); visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty), DL->getABITypeAlignment(Ty), Ty, MemRef::Read | MemRef::Write); } } } } if (CS.isCall() && cast<CallInst>(CS.getInstruction())->isTailCall()) for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); AI != AE; ++AI) { Value *Obj = findValue(*AI, /*OffsetOk=*/true); Assert(!isa<AllocaInst>(Obj), "Undefined behavior: Call with \"tail\" keyword references " "alloca", &I); } if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) switch (II->getIntrinsicID()) { default: break; // TODO: Check more intrinsics case Intrinsic::memcpy: { MemCpyInst *MCI = cast<MemCpyInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MCI->getDest(), MemoryLocation::UnknownSize, MCI->getAlignment(), nullptr, MemRef::Write); visitMemoryReference(I, MCI->getSource(), MemoryLocation::UnknownSize, MCI->getAlignment(), nullptr, MemRef::Read); // Check that the memcpy arguments don't overlap. The AliasAnalysis API // isn't expressive enough for what we really want to do. Known partial // overlap is not distinguished from the case where nothing is known. uint64_t Size = 0; if (const ConstantInt *Len = dyn_cast<ConstantInt>(findValue(MCI->getLength(), /*OffsetOk=*/false))) if (Len->getValue().isIntN(32)) Size = Len->getValue().getZExtValue(); Assert(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != MustAlias, "Undefined behavior: memcpy source and destination overlap", &I); break; } case Intrinsic::memmove: { MemMoveInst *MMI = cast<MemMoveInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MMI->getDest(), MemoryLocation::UnknownSize, MMI->getAlignment(), nullptr, MemRef::Write); visitMemoryReference(I, MMI->getSource(), MemoryLocation::UnknownSize, MMI->getAlignment(), nullptr, MemRef::Read); break; } case Intrinsic::memset: { MemSetInst *MSI = cast<MemSetInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MSI->getDest(), MemoryLocation::UnknownSize, MSI->getAlignment(), nullptr, MemRef::Write); break; } case Intrinsic::vastart: Assert(I.getParent()->getParent()->isVarArg(), "Undefined behavior: va_start called in a non-varargs function", &I); visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; case Intrinsic::vacopy: visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Write); visitMemoryReference(I, CS.getArgument(1), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read); break; case Intrinsic::vaend: visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; case Intrinsic::stackrestore: // Stackrestore doesn't read or write memory, but it sets the // stack pointer, which the compiler may read from or write to // at any time, so check it for both readability and writeability. visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; } }
bool CallAnalyzer::visitCallSite(CallSite CS) { if (CS.isCall() && cast<CallInst>(CS.getInstruction())->canReturnTwice() && !F.getAttributes().hasAttribute(AttributeSet::FunctionIndex, Attribute::ReturnsTwice)) { // This aborts the entire analysis. ExposesReturnsTwice = true; return false; } if (CS.isCall() && cast<CallInst>(CS.getInstruction())->hasFnAttr(Attribute::NoDuplicate)) ContainsNoDuplicateCall = true; if (Function *F = CS.getCalledFunction()) { // When we have a concrete function, first try to simplify it directly. if (simplifyCallSite(F, CS)) return true; // Next check if it is an intrinsic we know about. // FIXME: Lift this into part of the InstVisitor. if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) { switch (II->getIntrinsicID()) { default: return Base::visitCallSite(CS); case Intrinsic::memset: case Intrinsic::memcpy: case Intrinsic::memmove: // SROA can usually chew through these intrinsics, but they aren't free. return false; } } if (F == CS.getInstruction()->getParent()->getParent()) { // This flag will fully abort the analysis, so don't bother with anything // else. IsRecursiveCall = true; return false; } if (!callIsSmall(CS)) { // We account for the average 1 instruction per call argument setup // here. Cost += CS.arg_size() * InlineConstants::InstrCost; // Everything other than inline ASM will also have a significant cost // merely from making the call. if (!isa<InlineAsm>(CS.getCalledValue())) Cost += InlineConstants::CallPenalty; } return Base::visitCallSite(CS); } // Otherwise we're in a very special case -- an indirect function call. See // if we can be particularly clever about this. Value *Callee = CS.getCalledValue(); // First, pay the price of the argument setup. We account for the average // 1 instruction per call argument setup here. Cost += CS.arg_size() * InlineConstants::InstrCost; // Next, check if this happens to be an indirect function call to a known // function in this inline context. If not, we've done all we can. Function *F = dyn_cast_or_null<Function>(SimplifiedValues.lookup(Callee)); if (!F) return Base::visitCallSite(CS); // If we have a constant that we are calling as a function, we can peer // through it and see the function target. This happens not infrequently // during devirtualization and so we want to give it a hefty bonus for // inlining, but cap that bonus in the event that inlining wouldn't pan // out. Pretend to inline the function, with a custom threshold. CallAnalyzer CA(TD, *F, InlineConstants::IndirectCallThreshold); if (CA.analyzeCall(CS)) { // We were able to inline the indirect call! Subtract the cost from the // bonus we want to apply, but don't go below zero. Cost -= std::max(0, InlineConstants::IndirectCallThreshold - CA.getCost()); } return Base::visitCallSite(CS); }
/// analyzeBasicBlock - Fill in the current structure with information gleaned /// from the specified block. void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { ++NumBlocks; unsigned NumInstsBeforeThisBB = NumInsts; for (BasicBlock::const_iterator II = BB->begin(), E = BB->end(); II != E; ++II) { if (isa<PHINode>(II)) continue; // PHI nodes don't count. // Special handling for calls. if (isa<CallInst>(II) || isa<InvokeInst>(II)) { if (isa<DbgInfoIntrinsic>(II)) continue; // Debug intrinsics don't count as size. CallSite CS = CallSite::get(const_cast<Instruction*>(&*II)); // If this function contains a call to setjmp or _setjmp, never inline // it. This is a hack because we depend on the user marking their local // variables as volatile if they are live across a setjmp call, and they // probably won't do this in callers. if (Function *F = CS.getCalledFunction()) { if (F->isDeclaration() && (F->getName() == "setjmp" || F->getName() == "_setjmp")) callsSetJmp = true; // If this call is to function itself, then the function is recursive. // Inlining it into other functions is a bad idea, because this is // basically just a form of loop peeling, and our metrics aren't useful // for that case. if (F == BB->getParent()) isRecursive = true; } if (!isa<IntrinsicInst>(II) && !callIsSmall(CS.getCalledFunction())) { // Each argument to a call takes on average one instruction to set up. NumInsts += CS.arg_size(); // We don't want inline asm to count as a call - that would prevent loop // unrolling. The argument setup cost is still real, though. if (!isa<InlineAsm>(CS.getCalledValue())) ++NumCalls; } } if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) { if (!AI->isStaticAlloca()) this->usesDynamicAlloca = true; } if (isa<ExtractElementInst>(II) || II->getType()->isVectorTy()) ++NumVectorInsts; if (const CastInst *CI = dyn_cast<CastInst>(II)) { // Noop casts, including ptr <-> int, don't count. if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) || isa<PtrToIntInst>(CI)) continue; // Result of a cmp instruction is often extended (to be used by other // cmp instructions, logical or return instructions). These are usually // nop on most sane targets. if (isa<CmpInst>(CI->getOperand(0))) continue; } else if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(II)){ // If a GEP has all constant indices, it will probably be folded with // a load/store. if (GEPI->hasAllConstantIndices()) continue; } ++NumInsts; } if (isa<ReturnInst>(BB->getTerminator())) ++NumRets; // We never want to inline functions that contain an indirectbr. This is // incorrect because all the blockaddress's (in static global initializers // for example) would be referring to the original function, and this indirect // jump would jump from the inlined copy of the function into the original // function which is extremely undefined behavior. if (isa<IndirectBrInst>(BB->getTerminator())) containsIndirectBr = true; // Remember NumInsts for this BB. NumBBInsts[BB] = NumInsts - NumInstsBeforeThisBB; }
bool CSDataRando::processCallSite(CallSite CS, FuncInfo &FI, PointerEquivalenceAnalysis &P, DSGraph *G) { bool IndirectCall = !isa<Function>(CS.getCalledValue()->stripPointerCasts()); if (IndirectCall) { NumIndirectCalls++; } CallSite OriginalCS = originalCallSite(FI, CS); if (!DSA->canEncryptCall(OriginalCS)) { if (IndirectCall) { NumIndirectCantEncrypt++; } return false; } DSCallSite DSCS = G->getDSCallSiteForCallSite(OriginalCS); const Function *Callee = getEffectiveCallee(DSCS, FI, G); if (!Callee) { if (IndirectCall) { NumIndirectCantEncrypt++; } return false; } FuncInfo &CalleeInfo = FunctionInfo[Callee]; Value *Clone = getCloneCalledValue(CS, CalleeInfo); if (!Clone || CalleeInfo.ArgNodes.empty()) { if (IndirectCall) { NumIndirectCantEncrypt++; } return false; } // We create a mapping of the formal argument nodes in the callee function and // actual argument nodes in the caller function's graph. DSGraph::NodeMapTy NodeMap; DSGraph *CalleeG = DSA->getDSGraph(*Callee); // getArgNodesForCall places the return node and the vanode in the // first two slots of the vector, followed by the nodes for the regular // pointer arguments. std::vector<DSNodeHandle> ArgNodes; getArgNodesForCall(CalleeG, DSCS, ArgNodes); // First the return value DSNodeHandle CalleeRetNode = ArgNodes[0]; DSGraph::computeNodeMapping(CalleeRetNode, DSCS.getRetVal(), NodeMap); // Then VarArgs DSNodeHandle CalleeVarArgNode = ArgNodes[1]; DSGraph::computeNodeMapping(CalleeVarArgNode, DSCS.getVAVal(), NodeMap); // And last the regular arguments. for (unsigned int i = 0; i < DSCS.getNumPtrArgs() && i + 2 < ArgNodes.size(); i++) { DSGraph::computeNodeMapping(ArgNodes[i + 2], DSCS.getPtrArg(i), NodeMap); } // Collect the arguments and masks to pass to call SmallVector<Value*, 8> Args; unsigned int i = 0; for (unsigned int e = CS.getFunctionType()->getNumParams(); i < e; i++) { Args.push_back(CS.getArgOperand(i)); } for (const DSNode *N : CalleeInfo.ArgNodes) { Value *Mask = P.getMaskForNode(NodeMap[N]); Args.push_back(Mask); } // VarArgs go after masks for (unsigned int e = CS.arg_size(); i < e; i++) { Args.push_back(CS.getArgOperand(i)); } // Do replacement Instruction *CI = CS.getInstruction(); Value *Call; if (CS.isCall()) { Call = CallInst::Create(Clone, Args, "", CI); } else { InvokeInst *II = cast<InvokeInst>(CI); Call = InvokeInst::Create(Clone, II->getNormalDest(), II->getUnwindDest(), Args, "", II); } CallSite NewCS(Call); NewCS.setCallingConv(CS.getCallingConv()); CI->replaceAllUsesWith(Call); P.replace(CI, Call); CI->eraseFromParent(); return true; }
void GraphBuilder::visitCallSite(CallSite CS) { // // Get the called value. Strip off any casts which are lossless. // Value *Callee = CS.getCalledValue()->stripPointerCasts(); // Special case handling of certain libc allocation functions here. if (Function *F = dyn_cast<Function>(Callee)) if (F->isIntrinsic() && visitIntrinsic(CS, F)) return; //Can't do much about inline asm (yet!) if (isa<InlineAsm> (Callee)) { ++NumAsmCall; DSNodeHandle RetVal; Instruction *I = CS.getInstruction(); if (isa<PointerType > (I->getType())) RetVal = getValueDest(I); // Calculate the arguments vector... for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) if (isa<PointerType > ((*I)->getType())) RetVal.mergeWith(getValueDest(*I)); if (!RetVal.isNull()) RetVal.getNode()->foldNodeCompletely(); return; } // Set up the return value... DSNodeHandle RetVal; Instruction *I = CS.getInstruction(); if (isa<PointerType>(I->getType())) RetVal = getValueDest(I); DSNode *CalleeNode = 0; if (!isa<Function>(Callee)) { CalleeNode = getValueDest(Callee).getNode(); if (CalleeNode == 0) { DEBUG(errs() << "WARNING: Program is calling through a null pointer?\n" << *I); return; // Calling a null pointer? } } // NOTE: This code is identical to 'DSGraph::getDSCallSiteForCallSite', // the reason it's duplicated is because this calls getValueDest instead // of getNodeForValue to get the DSNodes for the arguments. Since we're in // local it's possible that we need to create a DSNode for the argument, as // opposed to getNodeForValue which simply retrieves the existing node. //Get the FunctionType for the called function const FunctionType *CalleeFuncType = DSCallSite::FunctionTypeOfCallSite(CS); int NumFixedArgs = CalleeFuncType->getNumParams(); // Sanity check--this really, really shouldn't happen if (!CalleeFuncType->isVarArg()) assert(CS.arg_size() == static_cast<unsigned>(NumFixedArgs) && "Too many arguments/incorrect function signature!"); std::vector<DSNodeHandle> Args; Args.reserve(CS.arg_end()-CS.arg_begin()); DSNodeHandle VarArgNH; // Calculate the arguments vector... // Add all fixed pointer arguments, then merge the rest together for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) if (isa<PointerType>((*I)->getType())) { DSNodeHandle ArgNode = getValueDest(*I); if (I - CS.arg_begin() < NumFixedArgs) { Args.push_back(ArgNode); } else { VarArgNH.mergeWith(ArgNode); } } // Add a new function call entry... if (CalleeNode) { ++NumIndirectCall; G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, VarArgNH, CalleeNode, Args)); } else { ++NumDirectCall; G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, VarArgNH, cast<Function>(Callee), Args)); } }
void Lint::visitCallSite(CallSite CS) { Instruction &I = *CS.getInstruction(); Value *Callee = CS.getCalledValue(); // TODO: Check function alignment? visitMemoryReference(I, Callee, 0, 0); if (Function *F = dyn_cast<Function>(Callee->stripPointerCasts())) { Assert1(CS.getCallingConv() == F->getCallingConv(), "Undefined behavior: Caller and callee calling convention differ", &I); const FunctionType *FT = F->getFunctionType(); unsigned NumActualArgs = unsigned(CS.arg_end()-CS.arg_begin()); Assert1(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs : FT->getNumParams() == NumActualArgs, "Undefined behavior: Call argument count mismatches callee " "argument count", &I); // TODO: Check argument types (in case the callee was casted) // TODO: Check ABI-significant attributes. // TODO: Check noalias attribute. // TODO: Check sret attribute. } // TODO: Check the "tail" keyword constraints. if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) switch (II->getIntrinsicID()) { default: break; // TODO: Check more intrinsics case Intrinsic::memcpy: { MemCpyInst *MCI = cast<MemCpyInst>(&I); visitMemoryReference(I, MCI->getSource(), MCI->getAlignment(), 0); visitMemoryReference(I, MCI->getDest(), MCI->getAlignment(), 0); // Check that the memcpy arguments don't overlap. The AliasAnalysis API // isn't expressive enough for what we really want to do. Known partial // overlap is not distinguished from the case where nothing is known. unsigned Size = 0; if (const ConstantInt *Len = dyn_cast<ConstantInt>(MCI->getLength()->stripPointerCasts())) if (Len->getValue().isIntN(32)) Size = Len->getValue().getZExtValue(); Assert1(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != AliasAnalysis::MustAlias, "Undefined behavior: memcpy source and destination overlap", &I); break; } case Intrinsic::memmove: { MemMoveInst *MMI = cast<MemMoveInst>(&I); visitMemoryReference(I, MMI->getSource(), MMI->getAlignment(), 0); visitMemoryReference(I, MMI->getDest(), MMI->getAlignment(), 0); break; } case Intrinsic::memset: { MemSetInst *MSI = cast<MemSetInst>(&I); visitMemoryReference(I, MSI->getDest(), MSI->getAlignment(), 0); break; } case Intrinsic::vastart: Assert1(I.getParent()->getParent()->isVarArg(), "Undefined behavior: va_start called in a non-varargs function", &I); visitMemoryReference(I, CS.getArgument(0), 0, 0); break; case Intrinsic::vacopy: visitMemoryReference(I, CS.getArgument(0), 0, 0); visitMemoryReference(I, CS.getArgument(1), 0, 0); break; case Intrinsic::vaend: visitMemoryReference(I, CS.getArgument(0), 0, 0); break; case Intrinsic::stackrestore: visitMemoryReference(I, CS.getArgument(0), 0, 0); break; } }
void RTAssociate::replaceCall(CallSite CS, FuncInfo& FI, DataStructures* DS) { const Function *CF = CS.getCalledFunction(); Instruction *TheCall = CS.getInstruction(); // If the called function is casted from one function type to another, peer // into the cast instruction and pull out the actual function being called. if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CS.getCalledValue())) if (CE->getOpcode() == Instruction::BitCast && isa<Function>(CE->getOperand(0))) CF = cast<Function>(CE->getOperand(0)); if (isa<InlineAsm>(TheCall->getOperand(0))) { errs() << "INLINE ASM: ignoring. Hoping that's safe.\n"; return; } // Ignore calls to NULL pointers. if (isa<ConstantPointerNull>(CS.getCalledValue())) { errs() << "WARNING: Ignoring call using NULL function pointer.\n"; return; } // We need to figure out which local pool descriptors correspond to the pool // descriptor arguments passed into the function call. Calculate a mapping // from callee DSNodes to caller DSNodes. We construct a partial isomophism // between the graphs to figure out which pool descriptors need to be passed // in. The roots of this mapping is found from arguments and return values. // DSGraph::NodeMapTy NodeMapping; Instruction *NewCall; Value *NewCallee; std::vector<const DSNode*> ArgNodes; DSGraph *CalleeGraph; // The callee graph // For indirect callees, find any callee since all DS graphs have been // merged. if (CF) { // Direct calls are nice and simple. DEBUG(errs() << " Handling direct call: " << *TheCall); FuncInfo *CFI = getFuncInfo(CF); if (CFI == 0 || CFI->Clone == 0) // Nothing to transform... return; NewCallee = CFI->Clone; ArgNodes = CFI->ArgNodes; assert ((DS->hasDSGraph (*CF)) && "Function has no ECGraph!\n"); CalleeGraph = DS->getDSGraph(*CF); } else { DEBUG(errs() << " Handling indirect call: " << *TheCall); // Here we fill in CF with one of the possible called functions. Because we // merged together all of the arguments to all of the functions in the // equivalence set, it doesn't really matter which one we pick. // (If the function was cloned, we have to map the cloned call instruction // in CS back to the original call instruction.) Instruction *OrigInst = cast<Instruction>(FI.getOldValueIfAvailable(CS.getInstruction())); DSCallGraph::callee_iterator I = DS->getCallGraph().callee_begin(CS); if (I != DS->getCallGraph().callee_end(CS)) CF = *I; // If we didn't find the callee in the constructed call graph, try // checking in the DSNode itself. // This isn't ideal as it means that this call site didn't have inlining // happen. if (!CF) { DSGraph* dg = DS->getDSGraph(*OrigInst->getParent()->getParent()); DSNode* d = dg->getNodeForValue(OrigInst->getOperand(0)).getNode(); assert (d && "No DSNode!\n"); std::vector<const Function*> g; d->addFullFunctionList(g); if (g.size()) { EquivalenceClasses< const GlobalValue *> & EC = dg->getGlobalECs(); for(std::vector<const Function*>::const_iterator ii = g.begin(), ee = g.end(); !CF && ii != ee; ++ii) { for (EquivalenceClasses<const GlobalValue *>::member_iterator MI = EC.findLeader(*ii); MI != EC.member_end(); ++MI) // Loop over members in this set. if ((CF = dyn_cast<Function>(*MI))) { break; } } } } // // Do an assert unless we're bugpointing something. // // if ((UsingBugpoint) && (!CF)) return; if (!CF) errs() << "No Graph for CallSite in " << TheCall->getParent()->getParent()->getName().str() << " originally " << OrigInst->getParent()->getParent()->getName().str() << "\n"; assert (CF && "No call graph info"); // Get the common graph for the set of functions this call may invoke. // if (UsingBugpoint && (!(Graphs.hasDSGraph(*CF)))) return; assert ((DS->hasDSGraph(*CF)) && "Function has no DSGraph!\n"); CalleeGraph = DS->getDSGraph(*CF); #ifndef NDEBUG // Verify that all potential callees at call site have the same DS graph. DSCallGraph::callee_iterator E = DS->getCallGraph().callee_end(CS); for (; I != E; ++I) if (!(*I)->isDeclaration()) assert(CalleeGraph == DS->getDSGraph(**I) && "Callees at call site do not have a common graph!"); #endif // Find the DS nodes for the arguments that need to be added, if any. FuncInfo *CFI = getFuncInfo(CF); assert(CFI && "No function info for callee at indirect call?"); ArgNodes = CFI->ArgNodes; if (ArgNodes.empty()) return; // No arguments to add? Transformation is a noop! // Cast the function pointer to an appropriate type! std::vector<Type*> ArgTys(ArgNodes.size(), PoolDescPtrTy); for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) ArgTys.push_back((*I)->getType()); FunctionType *FTy = FunctionType::get(TheCall->getType(), ArgTys, false); PointerType *PFTy = PointerType::getUnqual(FTy); // If there are any pool arguments cast the func ptr to the right type. NewCallee = CastInst::CreatePointerCast(CS.getCalledValue(), PFTy, "tmp", TheCall); } Function::const_arg_iterator FAI = CF->arg_begin(), E = CF->arg_end(); CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); for ( ; FAI != E && AI != AE; ++FAI, ++AI) if (!isa<Constant>(*AI)) DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(FAI), FI.getDSNodeHFor(*AI), NodeMapping, false); assert(AI == AE && "Varargs calls not handled yet!"); // Map the return value as well... if (isa<PointerType>(TheCall->getType())) DSGraph::computeNodeMapping(CalleeGraph->getReturnNodeFor(*CF), FI.getDSNodeHFor(TheCall), NodeMapping, false); // Okay, now that we have established our mapping, we can figure out which // pool descriptors to pass in... std::vector<Value*> Args; for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) { Value *ArgVal = Constant::getNullValue(PoolDescPtrTy); if (NodeMapping.count(ArgNodes[i])) if (DSNode *LocalNode = NodeMapping[ArgNodes[i]].getNode()) if (FI.PoolDescriptors.count(LocalNode)) ArgVal = FI.PoolDescriptors.find(LocalNode)->second; if (isa<Constant > (ArgVal) && cast<Constant > (ArgVal)->isNullValue()) errs() << "WARNING: NULL POOL ARGUMENTS ARE PASSED IN!\n"; Args.push_back(ArgVal); } // Add the rest of the arguments... Args.insert(Args.end(), CS.arg_begin(), CS.arg_end()); // // There are circumstances where a function is casted to another type and // then called (que horible). We need to perform a similar cast if the // type doesn't match the number of arguments. // if (Function * NewFunction = dyn_cast<Function>(NewCallee)) { FunctionType * NewCalleeType = NewFunction->getFunctionType(); if (NewCalleeType->getNumParams() != Args.size()) { std::vector<Type *> Types; Type * FuncTy = FunctionType::get (NewCalleeType->getReturnType(), Types, true); FuncTy = PointerType::getUnqual (FuncTy); NewCallee = new BitCastInst (NewCallee, FuncTy, "", TheCall); } } std::string Name = TheCall->getName(); TheCall->setName(""); if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) { NewCall = InvokeInst::Create (NewCallee, II->getNormalDest(), II->getUnwindDest(), Args, Name, TheCall); } else { NewCall = CallInst::Create (NewCallee, Args, Name, TheCall); } TheCall->replaceAllUsesWith(NewCall); DEBUG(errs() << " Result Call: " << *NewCall); if (TheCall->getType()->getTypeID() != Type::VoidTyID) { // If we are modifying the original function, update the DSGraph... DSGraph::ScalarMapTy &SM = FI.G->getScalarMap(); DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall); if (CII != SM.end()) { SM[NewCall] = CII->second; SM.erase(CII); // Destroy the CallInst } else if (!FI.NewToOldValueMap.empty()) { // Otherwise, if this is a clone, update the NewToOldValueMap with the new // CI return value. FI.UpdateNewToOldValueMap(TheCall, NewCall); } } else if (!FI.NewToOldValueMap.empty()) { FI.UpdateNewToOldValueMap(TheCall, NewCall); } //FIXME: attributes on call? CallSite(NewCall).setCallingConv(CallSite(TheCall).getCallingConv()); TheCall->eraseFromParent(); }