// visitCallInst - This converts all LLVM call instructions into invoke // instructions. The except part of the invoke goes to the "LongJmpBlkPre" // that grabs the exception and proceeds to determine if it's a longjmp // exception or not. void LowerSetJmp::visitCallInst(CallInst& CI) { if (CI.getCalledFunction()) if (!IsTransformableFunction(CI.getCalledFunction()->getName()) || CI.getCalledFunction()->isIntrinsic()) return; BasicBlock* OldBB = CI.getParent(); // If not reachable from a setjmp call, don't transform. if (!DFSBlocks.count(OldBB)) return; BasicBlock* NewBB = OldBB->splitBasicBlock(CI); assert(NewBB && "Couldn't split BB of \"call\" instruction!!"); DFSBlocks.insert(NewBB); NewBB->setName("Call2Invoke"); Function* Func = OldBB->getParent(); // Construct the new "invoke" instruction. TerminatorInst* Term = OldBB->getTerminator(); std::vector<Value*> Params(CI.op_begin() + 1, CI.op_end()); InvokeInst* II = InvokeInst::Create(CI.getCalledValue(), NewBB, PrelimBBMap[Func], Params.begin(), Params.end(), CI.getName(), Term); II->setCallingConv(CI.getCallingConv()); II->setParamAttrs(CI.getParamAttrs()); // Replace the old call inst with the invoke inst and remove the call. CI.replaceAllUsesWith(II); CI.getParent()->getInstList().erase(&CI); // The old terminator is useless now that we have the invoke inst. Term->getParent()->getInstList().erase(Term); ++CallsTransformed; }
bool CallLowering::lowerCall( MachineIRBuilder &MIRBuilder, const CallInst &CI, unsigned ResReg, ArrayRef<unsigned> ArgRegs, std::function<unsigned()> GetCalleeReg) const { auto &DL = CI.getParent()->getParent()->getParent()->getDataLayout(); // First step is to marshall all the function's parameters into the correct // physregs and memory locations. Gather the sequence of argument types that // we'll pass to the assigner function. SmallVector<ArgInfo, 8> OrigArgs; unsigned i = 0; for (auto &Arg : CI.arg_operands()) { ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{}}; setArgFlags(OrigArg, i + 1, DL, CI); OrigArgs.push_back(OrigArg); ++i; } MachineOperand Callee = MachineOperand::CreateImm(0); if (Function *F = CI.getCalledFunction()) Callee = MachineOperand::CreateGA(F, 0); else Callee = MachineOperand::CreateReg(GetCalleeReg(), false); ArgInfo OrigRet{ResReg, CI.getType(), ISD::ArgFlagsTy{}}; if (!OrigRet.Ty->isVoidTy()) setArgFlags(OrigRet, AttributeSet::ReturnIndex, DL, CI); return lowerCall(MIRBuilder, Callee, OrigRet, OrigArgs); }
void SelectionDAGBuilder::visitGCResult(const CallInst &CI) { // The result value of the gc_result is simply the result of the actual // call. We've already emitted this, so just grab the value. Instruction *I = cast<Instruction>(CI.getArgOperand(0)); assert(isStatepoint(I) && "first argument must be a statepoint token"); if (I->getParent() != CI.getParent()) { // Statepoint is in different basic block so we should have stored call // result in a virtual register. // We can not use default getValue() functionality to copy value from this // register because statepoint and actuall call return types can be // different, and getValue() will use CopyFromReg of the wrong type, // which is always i32 in our case. PointerType *CalleeType = cast<PointerType>( ImmutableStatepoint(I).getCalledValue()->getType()); Type *RetTy = cast<FunctionType>(CalleeType->getElementType())->getReturnType(); SDValue CopyFromReg = getCopyFromRegs(I, RetTy); assert(CopyFromReg.getNode()); setValue(&CI, CopyFromReg); } else { setValue(&CI, getValue(I)); } }
/// Extract in a new basic block the omp fork call int SplitOMPCall(Module *mod, Function *F, Pass *P, std::string RegionName) { std::string functionCall; int t = 0; CallInst *iFirst; Instruction *iSecond; // XXX To optimize with a single run trough the instructions for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { if (t) { Instruction *instru = dyn_cast<Instruction>(&*I); iSecond = instru; break; } if (CallInst *callInst = dyn_cast<CallInst>(&*I)) { if (callInst->getCalledFunction()) { functionCall = callInst->getCalledFunction()->getName(); if (ChooseExtract(functionCall, RegionName, callInst, F)) { t = 1; iFirst = callInst; } } } } if (t) { SplitBlock(iFirst->getParent(), iFirst, P); SplitBlock(iSecond->getParent(), iSecond, P); } return t; }
// // Function: makeFSParameterCallsComplete() // // Description: // Finds calls to sc.fsparameter and fills in the completeness byte which // is the last argument to such call. The second argument to the function // is the one which is analyzed for completeness. // // Inputs: // M - Reference to the the module to analyze // void CompleteChecks::makeFSParameterCallsComplete(Module &M) { Function *sc_fsparameter = M.getFunction("sc.fsparameter"); if (sc_fsparameter == NULL) return; std::set<CallInst *> toComplete; // // Iterate over all uses of sc.fsparameter and discover which have a complete // pointer argument. // for (Function::use_iterator i = sc_fsparameter->use_begin(); i != sc_fsparameter->use_end(); ++i) { CallInst *CI; CI = dyn_cast<CallInst>(*i); if (CI == 0 || CI->getCalledFunction() != sc_fsparameter) continue; // // Get the parent function to which this call belongs. // Function *P = CI->getParent()->getParent(); Value *PtrOperand = CI->getOperand(2); DSNode *N = getDSNodeHandle(PtrOperand, P).getNode(); if (N == 0 || N->isExternalNode() || N->isIncompleteNode() || N->isUnknownNode() || N->isPtrToIntNode() || N->isIntToPtrNode()) { continue; } toComplete.insert(CI); } // // Fill in a 1 for each call instruction that has a complete pointer // argument. // Type *int8 = Type::getInt8Ty(M.getContext()); Constant *complete = ConstantInt::get(int8, 1); for (std::set<CallInst *>::iterator i = toComplete.begin(); i != toComplete.end(); ++i) { CallInst *CI = *i; CI->setOperand(4, complete); } return; }
void PoolRegisterElimination::removeTypeSafeRegistrations (const char * name) { // // Scan through all uses of the registration function and see if it can be // safely removed. If so, schedule it for removal. // std::vector<CallInst*> toBeRemoved; Function * F = intrinsic->getIntrinsic(name).F; // // Look for and record all registrations that can be deleted. // for (Value::use_iterator UI=F->use_begin(), UE=F->use_end(); UI != UE; ++UI) { // // Get the pointer to the registered object. // CallInst * CI = cast<CallInst>(*UI); Value * Ptr = intrinsic->getValuePointer(CI); // Lookup the DSNode for the value in the function's DSGraph. // DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent())); DSNodeHandle DSH = TDG->getNodeForValue(Ptr); assert ((!(DSH.isNull())) && "No DSNode for Value!\n"); // // If the DSNode is type-safe and is never used as an array, then there // will never be a need to look it up in a splay tree, so remove its // registration. // DSNode * N = DSH.getNode(); if(!N->isArrayNode() && TS->isTypeSafe(Ptr, F)){ toBeRemoved.push_back(CI); } } // // Update the statistics. // if (toBeRemoved.size()) { RemovedRegistration += toBeRemoved.size(); TypeSafeRegistrations += toBeRemoved.size(); } // // Remove the unnecesary registrations. // std::vector<CallInst*>::iterator it, end; for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) { (*it)->eraseFromParent(); } }
/// rewriteExpensiveInvoke - Insert code and hack the function to replace the /// specified invoke instruction with a call. void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, AllocaInst *InvokeNum, AllocaInst *StackPtr, SwitchInst *CatchSwitch) { ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()), InvokeNo); // If the unwind edge has phi nodes, split the edge. if (isa<PHINode>(II->getUnwindDest()->begin())) { SplitCriticalEdge(II, 1, this); // If there are any phi nodes left, they must have a single predecessor. while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) { PN->replaceAllUsesWith(PN->getIncomingValue(0)); PN->eraseFromParent(); } } // Insert a store of the invoke num before the invoke and store zero into the // location afterward. new StoreInst(InvokeNoC, InvokeNum, true, II); // volatile // Insert a store of the stack ptr before the invoke, so we can restore it // later in the exception case. CallInst* StackSaveRet = CallInst::Create(StackSaveFn, "ssret", II); new StoreInst(StackSaveRet, StackPtr, true, II); // volatile BasicBlock::iterator NI = II->getNormalDest()->getFirstInsertionPt(); // nonvolatile. new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), InvokeNum, false, NI); Instruction* StackPtrLoad = new LoadInst(StackPtr, "stackptr.restore", true, II->getUnwindDest()->getFirstInsertionPt()); CallInst::Create(StackRestoreFn, StackPtrLoad, "")->insertAfter(StackPtrLoad); // Add a switch case to our unwind block. CatchSwitch->addCase(InvokeNoC, II->getUnwindDest()); // Insert a normal call instruction. SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs, "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); NewCall->setDebugLoc(II->getDebugLoc()); II->replaceAllUsesWith(NewCall); // Replace the invoke with an uncond branch. BranchInst::Create(II->getNormalDest(), NewCall->getParent()); II->eraseFromParent(); }
void AMDGPUAnnotateKernelFeatures::addAttrToCallers(Function *Intrin, StringRef AttrName) { SmallPtrSet<Function *, 4> SeenFuncs; for (User *U : Intrin->users()) { // CallInst is the only valid user for an intrinsic. CallInst *CI = cast<CallInst>(U); Function *CallingFunction = CI->getParent()->getParent(); if (SeenFuncs.insert(CallingFunction).second) CallingFunction->addFnAttr(AttrName); } }
void ExtractContracts::visitCallInst(CallInst &I) { if (auto F = I.getCalledFunction()) { auto name = F->getName(); if (name == Naming::CONTRACT_REQUIRES || name == Naming::CONTRACT_ENSURES || name == Naming::CONTRACT_INVARIANT) { validateAnnotation(I); if (auto J = dyn_cast<CallInst>(I.getArgOperand(0))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(0), I.getParent()); I.setArgOperand(0, CallInst::Create(EF, Args, "", &I)); modified = true; // TODO can we somehow force LLVM to consider calls to the obsoleted // forall, exists, etc., to be dead code? } else if (name == Naming::CONTRACT_FORALL || name == Naming::CONTRACT_EXISTS) { if (auto J = dyn_cast<CallInst>(I.getArgOperand(1))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(1), I.getParent()); I.setArgOperand(1, CallInst::Create(EF, Args, "", &I)); modified = true; } } }
bool DINOTaskBoundaries::getTaskBoundariesFromCall (CallInst &CI, DINOGlobal::BasicBlockSet &TBs) { /*TBs Collects the Task Boundaries for this store instruction*/ IsTaskBoundaryPredicate collect = IsTaskBoundaryPredicate(); IsTaskBoundaryOrFunctionEntryPredicate stop = IsTaskBoundaryOrFunctionEntryPredicate(); BasicBlock *CB = CI.getParent(); DINOGlobal::BasicBlockList visited = DINOGlobal::BasicBlockList(); DINOGlobal::CollectBBsPredicated(*CB, visited, TBs, collect, /*Collection Predicate*/ stop);/*Traversal Stop Predicate*/ return !stop.hitTaskBoundary; }
void LLSTDebuggingPass::insertSelfInSendMessageCheck(Function& F) { Value* BrokenSelfMessage = m_builder->CreateGlobalStringPtr("\nself is broken\n"); InstructionVector Calls; for (Function::iterator BB = F.begin(); BB != F.end(); ++BB) { for(BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { if (CallInst* Call = dyn_cast<CallInst>(II)) { if (Call->getCalledFunction()->getName() == "sendMessage") Calls.push_back(Call); } } } for(std::size_t i = 0; i < Calls.size(); i++) { CallInst* Call = dyn_cast<CallInst>(Calls[i]); BasicBlock* PointerIsOkBB = Call->getParent()->splitBasicBlock( static_cast<BasicBlock::iterator>(Call) ); BasicBlock* PointerIsBrokenBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsOkBB); BasicBlock* PointerIsNotSmallIntBB = BasicBlock::Create(m_module->getContext(), "", &F, PointerIsBrokenBB); Instruction* branchToPointerIsOkBB = & PointerIsOkBB->getSinglePredecessor()->back(); m_builder->SetInsertPoint(branchToPointerIsOkBB); Value* argsPtr = m_builder->CreateBitCast( Call->getArgOperand(2), m_baseTypes.object->getPointerTo()); Value* self = m_builder->CreateCall2(getObjectField, argsPtr, m_builder->getInt32(0)); Value* isSmallInt = m_builder->CreateCall(isSmallInteger, self); m_builder->CreateCondBr(isSmallInt, PointerIsOkBB, PointerIsNotSmallIntBB); m_builder->SetInsertPoint(PointerIsNotSmallIntBB); Value* klassPtr = m_builder->CreateCall(getObjectClass, self); Value* pointerIsNull = m_builder->CreateICmpEQ(klassPtr, ConstantPointerNull::get(m_baseTypes.klass->getPointerTo()) ); m_builder->CreateCondBr(pointerIsNull, PointerIsBrokenBB, PointerIsOkBB); branchToPointerIsOkBB->eraseFromParent(); m_builder->SetInsertPoint(PointerIsBrokenBB); m_builder->CreateCall(_printf, BrokenSelfMessage); m_builder->CreateBr(PointerIsOkBB); } }
Value * StringAllocatorInfo::getOrCreateAllocSize (Value * AllocSite) const { // // See if this is a call to the allocator. If not, return NULL. // CallInst * CI = dyn_cast<CallInst>(AllocSite); if (!CI) return NULL; Function * F = dyn_cast<Function>(CI->getCalledValue()->stripPointerCasts()); if (!F || F->getName() != allocCallName) return NULL; // // See if this call has an argument. If not, ignore it. We do this because // autoconf configure scripts will create calls to string functions with zero // arguments just to see if the function exists. // CallSite CS(CI); if (CS.arg_size() == 0) return NULL; // // Insert a call to strlen() to determine the length of the string that was // allocated. Use a version of strlen() in the SAFECode library that can // handle NULL pointers. // Module * M = CI->getParent()->getParent()->getParent(); Function * Strlen = M->getFunction ("nullstrlen"); assert (Strlen && "No nullstrlen function in the module"); BasicBlock::iterator InsertPt = CI; ++InsertPt; Instruction * Length = CallInst::Create (Strlen, CS.getInstruction(), "", InsertPt); // // The size of the allocation is the string length plus one. // IntegerType * LengthType = dyn_cast<IntegerType>(Length->getType()); assert (LengthType && "nullstrlen doesn't return an integer?"); Value * One = ConstantInt::get (LengthType, 1); Instruction * Size = BinaryOperator::Create (Instruction::Add, Length, One); Size->insertAfter (Length); return Size; }
/// rewriteExpensiveInvoke - Insert code and hack the function to replace the /// specified invoke instruction with a call. void LowerInvoke::rewriteExpensiveInvoke(InvokeInst *II, unsigned InvokeNo, AllocaInst *InvokeNum, SwitchInst *CatchSwitch) { ConstantInt *InvokeNoC = ConstantInt::get(Type::getInt32Ty(II->getContext()), InvokeNo); // If the unwind edge has phi nodes, split the edge. if (isa<PHINode>(II->getUnwindDest()->begin())) { SplitCriticalEdge(II, 1, this); // If there are any phi nodes left, they must have a single predecessor. while (PHINode *PN = dyn_cast<PHINode>(II->getUnwindDest()->begin())) { PN->replaceAllUsesWith(PN->getIncomingValue(0)); PN->eraseFromParent(); } } // Insert a store of the invoke num before the invoke and store zero into the // location afterward. new StoreInst(InvokeNoC, InvokeNum, true, II); // volatile BasicBlock::iterator NI = II->getNormalDest()->getFirstNonPHI(); // nonvolatile. new StoreInst(Constant::getNullValue(Type::getInt32Ty(II->getContext())), InvokeNum, false, NI); // Add a switch case to our unwind block. CatchSwitch->addCase(InvokeNoC, II->getUnwindDest()); // Insert a normal call instruction. std::vector<Value*> CallArgs(II->op_begin()+3, II->op_end()); CallInst *NewCall = CallInst::Create(II->getCalledValue(), CallArgs.begin(), CallArgs.end(), "", II); NewCall->takeName(II); NewCall->setCallingConv(II->getCallingConv()); NewCall->setAttributes(II->getAttributes()); II->replaceAllUsesWith(NewCall); // Replace the invoke with an uncond branch. BranchInst::Create(II->getNormalDest(), NewCall->getParent()); II->eraseFromParent(); }
void ArgumentRecovery::fixCallSites(Function& base, Function& newTarget, const CallInformation& ci) { auto targetInfo = TargetInfo::getTargetInfo(*base.getParent()); // loop over callers and transform call sites. while (!base.use_empty()) { CallInst* call = cast<CallInst>(base.user_back()); Function* caller = call->getParent()->getParent(); auto registers = getRegisterPtr(*caller); auto newCall = createCallSite(*targetInfo, ci, newTarget, *registers, *call); // replace call newCall->takeName(call); call->eraseFromParent(); md::incrementFunctionVersion(*caller); } }
void ExtractContracts::validateAnnotation(CallInst &I) { assert(I.getCalledFunction() && "Unexpected virtual function."); assert(I.getNumArgOperands() == 1 && "Unexpected operands."); auto B = I.getParent(); auto F = B->getParent(); auto& DT = getAnalysis<DominatorTreeWrapperPass>(*F).getDomTree(); auto& LI = getAnalysis<LoopInfoWrapperPass>(*F).getLoopInfo(); if (I.getCalledFunction()->getName() == Naming::CONTRACT_INVARIANT) { auto L = LI[B]; if (!L) { llvm_unreachable("Loop invariants must occur inside loops."); } } else { for (auto L : LI) { auto& J = L->getHeader()->getInstList().front(); if (DT.dominates(&J, &I)) { llvm_unreachable("Procedure specifications must occur before loops."); } } } }
void insertCallToAccessFunctionSequential(Function *F, Function *cF) { CallInst *I; BasicBlock *b; Value::user_iterator i = F->user_begin(), e = F->user_end(); while (i != e) { if (isa<CallInst>(*i)) { I = dyn_cast<CallInst>(*i); b = I->getParent(); BasicBlock::iterator helper(I); CallInst *ci = dyn_cast<CallInst>(I->clone()); ci->setCalledFunction(cF); b->getInstList().insertAfter(helper, ci); i++; I->replaceAllUsesWith(ci); insertCallToPAPI(I, ci); } } }
void PoolRegisterElimination::removeSingletonRegistrations (const char * name) { // // Scan through all uses of the registration function and see if it can be // safely removed. If so, schedule it for removal. // std::vector<CallInst*> toBeRemoved; Function * F = intrinsic->getIntrinsic(name).F; // // Look for and record all registrations that can be deleted. // for (Value::use_iterator UI=F->use_begin(), UE=F->use_end(); UI != UE; ++UI) { // // Get the pointer to the registered object. // CallInst * CI = cast<CallInst>(*UI); Value * Ptr = intrinsic->getValuePointer(CI); // // Lookup the DSNode for the value in the function's DSGraph. // DSGraph * TDG = dsaPass->getDSGraph(*(CI->getParent()->getParent())); DSNodeHandle DSH = TDG->getNodeForValue(Ptr); assert ((!(DSH.isNull())) && "No DSNode for Value!\n"); // // If the object being registered is the same size as that found in the // DSNode, then we know it's a singleton object. The run-time doesn't need // such objects registered in the splay trees, so we can remove the // registration function. // DSNode * N = DSH.getNode(); Value * Size = intrinsic->getObjectSize (Ptr->stripPointerCasts()); if (Size) { if (ConstantInt * C = dyn_cast<ConstantInt>(Size)) { unsigned long size = C->getZExtValue(); if (size == N->getSize()) { toBeRemoved.push_back(CI); continue; } } } } // // Update the statistics. // if (toBeRemoved.size()) { RemovedRegistration += toBeRemoved.size(); SingletonRegistrations += toBeRemoved.size(); } // // Remove the unnecesary registrations. // std::vector<CallInst*>::iterator it, end; for (it = toBeRemoved.begin(), end = toBeRemoved.end(); it != end; ++it) { (*it)->eraseFromParent(); } }
bool SjLjEHPass::insertSjLjEHSupport(Function &F) { SmallVector<ReturnInst*,16> Returns; SmallVector<UnwindInst*,16> Unwinds; SmallVector<InvokeInst*,16> Invokes; // Look through the terminators of the basic blocks to find invokes, returns // and unwinds. for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { // Remember all return instructions in case we insert an invoke into this // function. Returns.push_back(RI); } else if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) { Invokes.push_back(II); } else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) { Unwinds.push_back(UI); } } NumInvokes += Invokes.size(); NumUnwinds += Unwinds.size(); // If we don't have any invokes, there's nothing to do. if (Invokes.empty()) return false; // Find the eh.selector.*, eh.exception and alloca calls. // // Remember any allocas() that aren't in the entry block, as the // jmpbuf saved SP will need to be updated for them. // // We'll use the first eh.selector to determine the right personality // function to use. For SJLJ, we always use the same personality for the // whole function, not on a per-selector basis. // FIXME: That's a bit ugly. Better way? SmallVector<CallInst*,16> EH_Selectors; SmallVector<CallInst*,16> EH_Exceptions; SmallVector<Instruction*,16> JmpbufUpdatePoints; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { // Note: Skip the entry block since there's nothing there that interests // us. eh.selector and eh.exception shouldn't ever be there, and we // want to disregard any allocas that are there. // // FIXME: This is awkward. The new EH scheme won't need to skip the entry // block. if (BB == F.begin()) { if (InvokeInst *II = dyn_cast<InvokeInst>(F.begin()->getTerminator())) { // FIXME: This will be always non-NULL in the new EH. if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn(); } continue; } for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (CallInst *CI = dyn_cast<CallInst>(I)) { if (CI->getCalledFunction() == SelectorFn) { if (!PersonalityFn) PersonalityFn = CI->getArgOperand(1); EH_Selectors.push_back(CI); } else if (CI->getCalledFunction() == ExceptionFn) { EH_Exceptions.push_back(CI); } else if (CI->getCalledFunction() == StackRestoreFn) { JmpbufUpdatePoints.push_back(CI); } } else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { JmpbufUpdatePoints.push_back(AI); } else if (InvokeInst *II = dyn_cast<InvokeInst>(I)) { // FIXME: This will be always non-NULL in the new EH. if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) if (!PersonalityFn) PersonalityFn = LPI->getPersonalityFn(); } } } // If we don't have any eh.selector calls, we can't determine the personality // function. Without a personality function, we can't process exceptions. if (!PersonalityFn) return false; // We have invokes, so we need to add register/unregister calls to get this // function onto the global unwind stack. // // First thing we need to do is scan the whole function for values that are // live across unwind edges. Each value that is live across an unwind edge we // spill into a stack location, guaranteeing that there is nothing live across // the unwind edge. This process also splits all critical edges coming out of // invoke's. splitLiveRangesAcrossInvokes(Invokes); SmallVector<LandingPadInst*, 16> LandingPads; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) // FIXME: This will be always non-NULL in the new EH. if (LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst()) LandingPads.push_back(LPI); } BasicBlock *EntryBB = F.begin(); // Create an alloca for the incoming jump buffer ptr and the new jump buffer // that needs to be restored on all exits from the function. This is an // alloca because the value needs to be added to the global context list. unsigned Align = 4; // FIXME: Should be a TLI check? AllocaInst *FunctionContext = new AllocaInst(FunctionContextTy, 0, Align, "fcn_context", F.begin()->begin()); Value *Idxs[2]; Type *Int32Ty = Type::getInt32Ty(F.getContext()); Value *Zero = ConstantInt::get(Int32Ty, 0); // We need to also keep around a reference to the call_site field Idxs[0] = Zero; Idxs[1] = ConstantInt::get(Int32Ty, 1); CallSite = GetElementPtrInst::Create(FunctionContext, Idxs, "call_site", EntryBB->getTerminator()); // The exception selector comes back in context->data[1] Idxs[1] = ConstantInt::get(Int32Ty, 2); Value *FCData = GetElementPtrInst::Create(FunctionContext, Idxs, "fc_data", EntryBB->getTerminator()); Idxs[1] = ConstantInt::get(Int32Ty, 1); Value *SelectorAddr = GetElementPtrInst::Create(FCData, Idxs, "exc_selector_gep", EntryBB->getTerminator()); // The exception value comes back in context->data[0] Idxs[1] = Zero; Value *ExceptionAddr = GetElementPtrInst::Create(FCData, Idxs, "exception_gep", EntryBB->getTerminator()); // The result of the eh.selector call will be replaced with a a reference to // the selector value returned in the function context. We leave the selector // itself so the EH analysis later can use it. for (int i = 0, e = EH_Selectors.size(); i < e; ++i) { CallInst *I = EH_Selectors[i]; Value *SelectorVal = new LoadInst(SelectorAddr, "select_val", true, I); I->replaceAllUsesWith(SelectorVal); } // eh.exception calls are replaced with references to the proper location in // the context. Unlike eh.selector, the eh.exception calls are removed // entirely. for (int i = 0, e = EH_Exceptions.size(); i < e; ++i) { CallInst *I = EH_Exceptions[i]; // Possible for there to be duplicates, so check to make sure the // instruction hasn't already been removed. if (!I->getParent()) continue; Value *Val = new LoadInst(ExceptionAddr, "exception", true, I); Type *Ty = Type::getInt8PtrTy(F.getContext()); Val = CastInst::Create(Instruction::IntToPtr, Val, Ty, "", I); I->replaceAllUsesWith(Val); I->eraseFromParent(); } for (unsigned i = 0, e = LandingPads.size(); i != e; ++i) ReplaceLandingPadVal(F, LandingPads[i], ExceptionAddr, SelectorAddr); // The entry block changes to have the eh.sjlj.setjmp, with a conditional // branch to a dispatch block for non-zero returns. If we return normally, // we're not handling an exception and just register the function context and // continue. // Create the dispatch block. The dispatch block is basically a big switch // statement that goes to all of the invoke landing pads. BasicBlock *DispatchBlock = BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); // Insert a load of the callsite in the dispatch block, and a switch on its // value. By default, we issue a trap statement. BasicBlock *TrapBlock = BasicBlock::Create(F.getContext(), "trapbb", &F); CallInst::Create(Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap), "", TrapBlock); new UnreachableInst(F.getContext(), TrapBlock); Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, DispatchBlock); SwitchInst *DispatchSwitch = SwitchInst::Create(DispatchLoad, TrapBlock, Invokes.size(), DispatchBlock); // Split the entry block to insert the conditional branch for the setjmp. BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), "eh.sjlj.setjmp.cont"); // Populate the Function Context // 1. LSDA address // 2. Personality function address // 3. jmpbuf (save SP, FP and call eh.sjlj.setjmp) // LSDA address Idxs[0] = Zero; Idxs[1] = ConstantInt::get(Int32Ty, 4); Value *LSDAFieldPtr = GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep", EntryBB->getTerminator()); Value *LSDA = CallInst::Create(LSDAAddrFn, "lsda_addr", EntryBB->getTerminator()); new StoreInst(LSDA, LSDAFieldPtr, true, EntryBB->getTerminator()); Idxs[1] = ConstantInt::get(Int32Ty, 3); Value *PersonalityFieldPtr = GetElementPtrInst::Create(FunctionContext, Idxs, "lsda_gep", EntryBB->getTerminator()); new StoreInst(PersonalityFn, PersonalityFieldPtr, true, EntryBB->getTerminator()); // Save the frame pointer. Idxs[1] = ConstantInt::get(Int32Ty, 5); Value *JBufPtr = GetElementPtrInst::Create(FunctionContext, Idxs, "jbuf_gep", EntryBB->getTerminator()); Idxs[1] = ConstantInt::get(Int32Ty, 0); Value *FramePtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_fp_gep", EntryBB->getTerminator()); Value *Val = CallInst::Create(FrameAddrFn, ConstantInt::get(Int32Ty, 0), "fp", EntryBB->getTerminator()); new StoreInst(Val, FramePtr, true, EntryBB->getTerminator()); // Save the stack pointer. Idxs[1] = ConstantInt::get(Int32Ty, 2); Value *StackPtr = GetElementPtrInst::Create(JBufPtr, Idxs, "jbuf_sp_gep", EntryBB->getTerminator()); Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator()); new StoreInst(Val, StackPtr, true, EntryBB->getTerminator()); // Call the setjmp instrinsic. It fills in the rest of the jmpbuf. Value *SetjmpArg = CastInst::Create(Instruction::BitCast, JBufPtr, Type::getInt8PtrTy(F.getContext()), "", EntryBB->getTerminator()); Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg, "dispatch", EntryBB->getTerminator()); // Add a call to dispatch_setup after the setjmp call. This is expanded to any // target-specific setup that needs to be done. CallInst::Create(DispatchSetupFn, DispatchVal, "", EntryBB->getTerminator()); // check the return value of the setjmp. non-zero goes to dispatcher. Value *IsNormal = new ICmpInst(EntryBB->getTerminator(), ICmpInst::ICMP_EQ, DispatchVal, Zero, "notunwind"); // Nuke the uncond branch. EntryBB->getTerminator()->eraseFromParent(); // Put in a new condbranch in its place. BranchInst::Create(ContBlock, DispatchBlock, IsNormal, EntryBB); // Register the function context and make sure it's known to not throw CallInst *Register = CallInst::Create(RegisterFn, FunctionContext, "", ContBlock->getTerminator()); Register->setDoesNotThrow(); // At this point, we are all set up, update the invoke instructions to mark // their call_site values, and fill in the dispatch switch accordingly. for (unsigned i = 0, e = Invokes.size(); i != e; ++i) markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch); // Mark call instructions that aren't nounwind as no-action (call_site == // -1). Skip the entry block, as prior to then, no function context has been // created for this function and any unexpected exceptions thrown will go // directly to the caller's context, which is what we want anyway, so no need // to do anything here. for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) { for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I) if (CallInst *CI = dyn_cast<CallInst>(I)) { // Ignore calls to the EH builtins (eh.selector, eh.exception) Constant *Callee = CI->getCalledFunction(); if (Callee != SelectorFn && Callee != ExceptionFn && !CI->doesNotThrow()) insertCallSiteStore(CI, -1, CallSite); } else if (ResumeInst *RI = dyn_cast<ResumeInst>(I)) { insertCallSiteStore(RI, -1, CallSite); } } // Replace all unwinds with a branch to the unwind handler. // ??? Should this ever happen with sjlj exceptions? for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { BranchInst::Create(TrapBlock, Unwinds[i]); Unwinds[i]->eraseFromParent(); } // Following any allocas not in the entry block, update the saved SP in the // jmpbuf to the new value. for (unsigned i = 0, e = JmpbufUpdatePoints.size(); i != e; ++i) { Instruction *AI = JmpbufUpdatePoints[i]; Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp"); StackAddr->insertAfter(AI); Instruction *StoreStackAddr = new StoreInst(StackAddr, StackPtr, true); StoreStackAddr->insertAfter(StackAddr); } // Finally, for any returns from this function, if this function contains an // invoke, add a call to unregister the function context. for (unsigned i = 0, e = Returns.size(); i != e; ++i) CallInst::Create(UnregisterFn, FunctionContext, "", Returns[i]); return true; }
// // Function: makeCStdLibCallsComplete() // // Description: // Fills in completeness information for all calls of a given CStdLib function // assumed to be of the form: // // pool_X(POOL *p1, ..., POOL *pN, void *a1, ..., void *aN, ..., uint8_t c); // // Specifically, this function assumes that there are as many pointer arguments // to check as there are initial pool arguments, and the pointer arguments // follow the pool arguments in corresponding order. Also, it is assumed that // the final argument to the function is a byte sized bit vector. // // This function fills in this final byte with a constant value whose ith // bit is set exactly when the ith pointer argument is complete. // // Inputs: // // F - A pointer to the CStdLib function appearing in the module // (non-null). // PoolArgs - The number of initial pool arguments for which a // corresponding pointer value requires a completeness check // (required to be at most 8). // void CompleteChecks::makeCStdLibCallsComplete(Function *F, unsigned PoolArgs) { assert(F != 0 && "Null function argument!"); assert(PoolArgs <= 8 && \ "Only up to 8 arguments are supported by CStdLib completeness checks!"); Value::use_iterator U = F->use_begin(); Value::use_iterator E = F->use_end(); // // Hold the call instructions that need changing. // typedef std::pair<CallInst *, uint8_t> VectorReplacement; std::set<VectorReplacement> callsToChange; Type *int8ty = Type::getInt8Ty(F->getContext()); FunctionType *F_type = F->getFunctionType(); // // Verify the type of the function is as expected. // // There should be as many pointer parameters to check for completeness // as there are pool parameters. The last parameter should be a byte. // assert(F_type->getNumParams() >= PoolArgs * 2 && \ "Not enough arguments to transformed CStdLib function call!"); for (unsigned arg = PoolArgs; arg < PoolArgs * 2; ++arg) assert(isa<PointerType>(F_type->getParamType(arg)) && \ "Expected pointer argument to function!"); // // This is the position of the vector operand in the call. // unsigned vect_position = F_type->getNumParams(); assert(F_type->getParamType(vect_position - 1) == int8ty && \ "Last parameter to the function should be a byte!"); // // Iterate over all calls of the function in the module, computing the // vectors for each call as it is found. // for (; U != E; ++U) { CallInst *CI; if ((CI = dyn_cast<CallInst>(*U)) && \ CI->getCalledValue()->stripPointerCasts() == F) { uint8_t vector = 0x0; // // Get the parent function to which this instruction belongs. // Function *P = CI->getParent()->getParent(); // // Iterate over the pointer arguments that need completeness checking // and build the completeness vector. // for (unsigned arg = 0; arg < PoolArgs; ++arg) { bool complete = true; // // Go past all the pool arguments to get the pointer to check. // Value *V = CI->getOperand(1 + PoolArgs + arg); // // Check for completeness of the pointer using DSA and // set the bit in the vector accordingly. // DSNode *N; if ((N = getDSNodeHandle(V, P).getNode()) && (N->isExternalNode() || N->isIncompleteNode() || N->isUnknownNode() || N->isIntToPtrNode() || N->isPtrToIntNode()) ) { complete = false; } if (complete) vector |= (1 << arg); } // // Add the instruction and vector to the set of instructions to change. // callsToChange.insert(VectorReplacement(CI, vector)); } } // // Iterate over all call instructions that need changing, modifying the // final operand of the call to hold the bit vector value. // std::set<VectorReplacement>::iterator change = callsToChange.begin(); std::set<VectorReplacement>::iterator change_end = callsToChange.end(); while (change != change_end) { Constant *vect_value = ConstantInt::get(int8ty, change->second); change->first->setOperand(vect_position, vect_value); ++change; } return; }
bool RangedAddressSanitizer::runOnFunction(Function &F) { if (getenv("FASAN_DISABLE")) { SPM_DEBUG( dbgs() << "FASan : disabled\n" ); return false; } DL_ = &getAnalysis<DataLayout>(); DT_ = &getAnalysis<DominatorTree>(); LI_ = &getAnalysis<LoopInfo>(); RI_ = &getAnalysis<ReduceIndexation>(); #ifdef ENABLE_REUSE RE_ = &getAnalysis<RelativeExecutions>(); #endif RMM_ = &getAnalysis<RelativeMinMax>(); Module_ = F.getParent(); Context_ = &Module_->getContext(); Type *VoidTy = Type::getVoidTy(*Context_); IntegerType *IntTy = IntegerType::getInt64Ty(*Context_); IntegerType *BoolTy = IntegerType::getInt1Ty(*Context_); PointerType *IntPtrTy = PointerType::getUnqual(IntTy); PointerType *VoidPtrTy = PointerType::getInt8PtrTy(*Context_); SPM_DEBUG( F.dump() ); outs() << "[IterationInfo]\n"; for (Loop * loop : *LI_) { ii_visitLoop(loop); } outs() << "[EndOfIterationInfo]\n"; #if 0 // disabled initialization,shutdown sequence for FASan if (F.getName() == "main") { SPM_DEBUG(dbgs() << "RangedAddressSanitizer: inserting hwloc calls into " "main function\n"); FunctionType *FnType = FunctionType::get(VoidTy, ArrayRef<Type*>(), false); IRBuilder<> IRB(&(*F.getEntryBlock().begin())); Constant *Init = Module_->getOrInsertFunction("__spm_init", FnType); IRB.CreateCall(Init); Constant *End = Module_->getOrInsertFunction("__spm_end", FnType); for (auto &BB : F) { TerminatorInst *TI = BB.getTerminator(); if (isa<ReturnInst>(TI)) { IRB.SetInsertPoint(TI); IRB.CreateCall(End); } } } #endif if (!ClFunc.empty() && F.getName() != ClFunc) { SPM_DEBUG(dbgs() << "RangedAddressSanitizer: skipping function " << F.getName() << "\n"); return false; } Calls_.clear(); SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing function " << F.getName() << "\n"); std::vector<Type*> ReuseFnFormals = { VoidPtrTy, IntTy, IntTy, IntTy }; FunctionType *ReuseFnType = FunctionType::get(BoolTy, ReuseFnFormals, false); ReuseFn_ = F.getParent()->getOrInsertFunction("__fasan_check", ReuseFnType); ReuseFnDestroy_ = F.getParent()->getOrInsertFunction("__spm_give", ReuseFnType); // Visit all loops in bottom-up order (innter-most loops first) std::set<BasicBlock*> Processed; auto Entry = DT_->getRootNode(); for (auto ET = po_begin(Entry), EE = po_end(Entry); ET != EE; ++ET) { BasicBlock *Header = (*ET)->getBlock(); if (LI_->isLoopHeader(Header)) { SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing loop at " << Header->getName() << "\n"); Loop *L = LI_->getLoopFor(Header); if (L->getNumBackEdges() != 1 || std::distance(pred_begin(Header), pred_end(Header)) != 2) { SPM_DEBUG(dbgs() << "RangedAddressSanitizer: loop has multiple " << "backedges or multiple incoming outer blocks\n"); continue; } SPM_DEBUG(dbgs() << "RangedAddressSanitizer: processing loop at " << Header->getName() << "\n"); // visit all memory acccesses in this loop for (auto BB = L->block_begin(), BE = L->block_end(); BB != BE; ++BB) { if (!Processed.count(*BB)) { Processed.insert(*BB); for (auto &I : *(*BB)) generateCallFor(L, &I); } } } } // FAsan logic goes here std::map<const BasicBlock*,BasicBlock*> clonedBlockMap; // keeps track of cloned regions to avoid redundant cloning std::vector<CallInst*> ToInline; for (auto &CI : Calls_) { BasicBlock * Preheader = CI.Preheader; // TODO decide whether it is worthwhile to optimize for this case // insert range check IRBuilder<> IRB(Preheader->getTerminator()); Value *VoidArray = IRB.CreateBitCast(CI.Array, VoidPtrTy); std::vector<Value*> Args = { VoidArray, CI.Min, CI.Max, CI.Reuse }; CallInst *CR = IRB.CreateCall(ReuseFn_, Args); ToInline.push_back(CR); // verify if this loop was already instrumented TerminatorInst * preHeaderTerm = CR->getParent()->getTerminator(); BranchInst * preHeaderBranch = dyn_cast<BranchInst>(preHeaderTerm); if (preHeaderBranch && preHeaderBranch->isConditional()) { // discover the structure of the instrumented code (safe and default region) // abort, if this does not look like instrumented code BasicBlock * firstTarget = preHeaderBranch->getSuccessor(0); BasicBlock * secondTarget = preHeaderBranch->getSuccessor(1); BasicBlock * safeHeader, * defHeader; if (clonedBlockMap.count(firstTarget)) { defHeader = firstTarget; safeHeader = clonedBlockMap[firstTarget]; assert(safeHeader == secondTarget); } else { assert(clonedBlockMap.count(secondTarget)); defHeader = secondTarget; safeHeader = clonedBlockMap[secondTarget]; assert(safeHeader == firstTarget); } SPM_DEBUG( dbgs() << "FASan: (Unsupported) second array in safe region controlled by " << * preHeaderBranch << "\n" ); Loop * defLoop = LI_->getLoopFor(defHeader); assert(defLoop && "default region is not a loop!"); Loop::block_iterator itBodyBlock,S,E; S = defLoop->block_begin(); E = defLoop->block_end(); // mark accesses in cloned region as safe for (itBodyBlock = S;itBodyBlock != E; ++itBodyBlock) { BasicBlock * defBodyBlock = *itBodyBlock; BasicBlock * safeBodyBlock = clonedBlockMap[defBodyBlock]; for(auto & inst : *safeBodyBlock) { markSafeArrayUse(&inst, CI.Array); } } // add conjunctive test Value * oldCond = preHeaderBranch->getCondition(); Value * joinedCond = IRB.CreateAnd(oldCond, CR, "allsafe"); preHeaderBranch->setCondition(joinedCond); } else { // get loop Loop* finalLoop = CI.FinalLoop; Loop::block_iterator itBodyBlock,S,E; S = finalLoop->block_begin(); E = finalLoop->block_end(); // clone loop body (cloned loop will run unchecked) ValueToValueMapTy cloneMap; BasicBlock * clonedHeader = 0; std::vector<BasicBlock*> clonedBlocks; for (itBodyBlock = S;itBodyBlock != E; ++itBodyBlock) { const BasicBlock * bodyBlock = *itBodyBlock; BasicBlock * clonedBlock = CloneBasicBlock(bodyBlock, cloneMap, "_checked", &F, 0); cloneMap[bodyBlock] = clonedBlock; clonedBlockMap[bodyBlock] = clonedBlock; clonedBlocks.push_back(clonedBlock); if (bodyBlock == finalLoop->getHeader()) { clonedHeader = clonedBlock; SPM_DEBUG( dbgs() << "FASan: loop header case at " << bodyBlock->getName() << "\n" ); } else { SPM_DEBUG( dbgs() << "FASan: non-header block at " << bodyBlock->getName() << "\n" ); } } if (!clonedHeader) { // TODO run clean-up code SPM_DEBUG( dbgs() << "FASan: could not find header!\n"); abort(); } // Remap uses inside cloned region (mark pointers in the region as unguarded) for (BasicBlock * block : clonedBlocks) { for(auto & inst : *block) { RemapInstruction(&inst, cloneMap, RF_IgnoreMissingEntries); markSafeArrayUse(&inst, CI.Array); } } // TODO fix PHI-nodes in exit blocks // Rewire terminator of the range check to branch to the cloned region TerminatorInst * checkTermInst = CR->getParent()->getTerminator(); if (BranchInst * checkBranchInst = dyn_cast<BranchInst>(checkTermInst)) { if (checkBranchInst->isUnconditional()) { BasicBlock * defTarget = checkBranchInst->getSuccessor(0); BranchInst * modifiedBranchInst = BranchInst::Create(clonedHeader, defTarget, CR, checkBranchInst); checkBranchInst->replaceAllUsesWith(modifiedBranchInst); checkBranchInst->eraseFromParent(); } else { SPM_DEBUG( dbgs() << "FASan: Unexpected conditional branch (preheader should branch unconditional, other array checks will introduce conditional branches) " << * checkTermInst << "\n" ); abort(); } } else { SPM_DEBUG( dbgs() << "FASan: unsupported terminator type " << * checkTermInst << "\n" ); abort(); } } #if 0 IRB.SetInsertPoint(&(*CI.Final->begin())); IRB.CreateCall(ReuseFnDestroy_, Args); #endif SPM_DEBUG(dbgs() << "RangedAddressSanitizer: call instruction: " << *CR << "\n"); } // inline calls #ifdef FASAN_INLINE_RUNTIME for (CallInst * call : ToInline) { assert(call); InlineFunctionInfo IFI; InlineFunction(call, IFI, false); } #endif SPM_DEBUG( F.dump() ); return true; }
// // Function: insertPoolFrees() // // Description: // This function takes a list of alloca instructions and inserts code to // unregister them at every unwind and return instruction. // // Inputs: // PoolRegisters - The list of calls to poolregister() inserted for stack // objects. // ExitPoints - The list of instructions that can cause the function to // return. // Context - The LLVM Context in which to insert instructions. // void RegisterStackObjPass::insertPoolFrees (const std::vector<CallInst *> & PoolRegisters, const std::vector<Instruction *> & ExitPoints, LLVMContext * Context) { // List of alloca instructions we create to store the pointers to be // deregistered. std::vector<AllocaInst *> PtrList; // List of pool handles; this is a parallel array to PtrList std::vector<Value *> PHList; // The infamous void pointer type PointerType * VoidPtrTy = getVoidPtrType(*Context); // // Create alloca instructions for every registered alloca. These will hold // a pointer to the registered stack objects and will be referenced by // poolunregister(). // for (unsigned index = 0; index < PoolRegisters.size(); ++index) { // // Take the first element off of the worklist. // CallInst * CI = PoolRegisters[index]; CallSite CS(CI); // // Get the pool handle and allocated pointer from the poolregister() call. // Value * PH = CS.getArgument(0); Value * Ptr = CS.getArgument(1); // // Create a place to store the pointer returned from alloca. Initialize it // with a null pointer. // BasicBlock & EntryBB = CI->getParent()->getParent()->getEntryBlock(); Instruction * InsertPt = &(EntryBB.front()); AllocaInst * PtrLoc = new AllocaInst (VoidPtrTy, Ptr->getName() + ".st", InsertPt); Value * NullPointer = ConstantPointerNull::get(VoidPtrTy); new StoreInst (NullPointer, PtrLoc, InsertPt); // // Store the registered pointer into the memory we allocated in the entry // block. // new StoreInst (Ptr, PtrLoc, CI); // // Record the alloca that stores the pointer to deregister. // Record the pool handle with it. // PtrList.push_back (PtrLoc); PHList.push_back (PH); } // // For each point where the function can exit, insert code to deregister all // stack objects. // for (unsigned index = 0; index < ExitPoints.size(); ++index) { // // Take the first element off of the worklist. // Instruction * Return = ExitPoints[index]; // // Deregister each registered stack object. // for (unsigned i = 0; i < PtrList.size(); ++i) { // // Get the location holding the pointer and the pool handle associated // with it. // AllocaInst * PtrLoc = PtrList[i]; Value * PH = PHList[i]; // // Generate a load instruction to get the registered pointer. // LoadInst * Ptr = new LoadInst (PtrLoc, "", Return); // // Create the call to poolunregister(). // std::vector<Value *> args; args.push_back (PH); args.push_back (Ptr); CallInst::Create (StackFree, args, "", Return); } } // // Lastly, promote the allocas we created into LLVM virtual registers. // PromoteMemToReg(PtrList, *DT); }
static void InsertSafepointPoll(DominatorTree &DT, Instruction *term, std::vector<CallSite> &ParsePointsNeeded /*rval*/) { Module *M = term->getParent()->getParent()->getParent(); assert(M); // Inline the safepoint poll implementation - this will get all the branch, // control flow, etc.. Most importantly, it will introduce the actual slow // path call - where we need to insert a safepoint (parsepoint). FunctionType *ftype = FunctionType::get(Type::getVoidTy(M->getContext()), false); assert(ftype && "null?"); // Note: This cast can fail if there's a function of the same name with a // different type inserted previously Function *F = dyn_cast<Function>(M->getOrInsertFunction("gc.safepoint_poll", ftype)); assert(F && !F->empty() && "definition must exist"); CallInst *poll = CallInst::Create(F, "", term); // Record some information about the call site we're replacing BasicBlock *OrigBB = term->getParent(); BasicBlock::iterator before(poll), after(poll); bool isBegin(false); if (before == term->getParent()->begin()) { isBegin = true; } else { before--; } after++; assert(after != poll->getParent()->end() && "must have successor"); assert(DT.dominates(before, after) && "trivially true"); // do the actual inlining InlineFunctionInfo IFI; bool inlineStatus = InlineFunction(poll, IFI); assert(inlineStatus && "inline must succeed"); (void)inlineStatus; // suppress warning in release-asserts // Check post conditions assert(IFI.StaticAllocas.empty() && "can't have allocs"); std::vector<CallInst *> calls; // new calls std::set<BasicBlock *> BBs; // new BBs + insertee // Include only the newly inserted instructions, Note: begin may not be valid // if we inserted to the beginning of the basic block BasicBlock::iterator start; if (isBegin) { start = OrigBB->begin(); } else { start = before; start++; } // If your poll function includes an unreachable at the end, that's not // valid. Bugpoint likes to create this, so check for it. assert(isPotentiallyReachable(&*start, &*after, nullptr, nullptr) && "malformed poll function"); scanInlinedCode(&*(start), &*(after), calls, BBs); // Recompute since we've invalidated cached data. Conceptually we // shouldn't need to do this, but implementation wise we appear to. Needed // so we can insert safepoints correctly. // TODO: update more cheaply DT.recalculate(*after->getParent()->getParent()); assert(!calls.empty() && "slow path not found for safepoint poll"); // Record the fact we need a parsable state at the runtime call contained in // the poll function. This is required so that the runtime knows how to // parse the last frame when we actually take the safepoint (i.e. execute // the slow path) assert(ParsePointsNeeded.empty()); for (size_t i = 0; i < calls.size(); i++) { // No safepoint needed or wanted if (!needsStatepoint(calls[i])) { continue; } // These are likely runtime calls. Should we assert that via calling // convention or something? ParsePointsNeeded.push_back(CallSite(calls[i])); } assert(ParsePointsNeeded.size() <= calls.size()); }
/// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return /// instructions to the predecessor to enable tail call optimizations. The /// case it is currently looking for is: /// bb0: /// %tmp0 = tail call i32 @f0() /// br label %return /// bb1: /// %tmp1 = tail call i32 @f1() /// br label %return /// bb2: /// %tmp2 = tail call i32 @f2() /// br label %return /// return: /// %retval = phi i32 [ %tmp0, %bb0 ], [ %tmp1, %bb1 ], [ %tmp2, %bb2 ] /// ret i32 %retval /// /// => /// /// bb0: /// %tmp0 = tail call i32 @f0() /// ret i32 %tmp0 /// bb1: /// %tmp1 = tail call i32 @f1() /// ret i32 %tmp1 /// bb2: /// %tmp2 = tail call i32 @f2() /// ret i32 %tmp2 /// bool CodeGenPrepare::DupRetToEnableTailCallOpts(ReturnInst *RI) { if (!TLI) return false; Value *V = RI->getReturnValue(); PHINode *PN = V ? dyn_cast<PHINode>(V) : NULL; if (V && !PN) return false; BasicBlock *BB = RI->getParent(); if (PN && PN->getParent() != BB) return false; // It's not safe to eliminate the sign / zero extension of the return value. // See llvm::isInTailCallPosition(). const Function *F = BB->getParent(); Attributes CallerRetAttr = F->getAttributes().getRetAttributes(); if ((CallerRetAttr & Attribute::ZExt) || (CallerRetAttr & Attribute::SExt)) return false; // Make sure there are no instructions between the PHI and return, or that the // return is the first instruction in the block. if (PN) { BasicBlock::iterator BI = BB->begin(); do { ++BI; } while (isa<DbgInfoIntrinsic>(BI)); if (&*BI != RI) return false; } else { BasicBlock::iterator BI = BB->begin(); while (isa<DbgInfoIntrinsic>(BI)) ++BI; if (&*BI != RI) return false; } /// Only dup the ReturnInst if the CallInst is likely to be emitted as a tail /// call. SmallVector<CallInst*, 4> TailCalls; if (PN) { for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) { CallInst *CI = dyn_cast<CallInst>(PN->getIncomingValue(I)); // Make sure the phi value is indeed produced by the tail call. if (CI && CI->hasOneUse() && CI->getParent() == PN->getIncomingBlock(I) && TLI->mayBeEmittedAsTailCall(CI)) TailCalls.push_back(CI); } } else { SmallPtrSet<BasicBlock*, 4> VisitedBBs; for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) { if (!VisitedBBs.insert(*PI)) continue; BasicBlock::InstListType &InstList = (*PI)->getInstList(); BasicBlock::InstListType::reverse_iterator RI = InstList.rbegin(); BasicBlock::InstListType::reverse_iterator RE = InstList.rend(); do { ++RI; } while (RI != RE && isa<DbgInfoIntrinsic>(&*RI)); if (RI == RE) continue; CallInst *CI = dyn_cast<CallInst>(&*RI); if (CI && CI->use_empty() && TLI->mayBeEmittedAsTailCall(CI)) TailCalls.push_back(CI); } } bool Changed = false; for (unsigned i = 0, e = TailCalls.size(); i != e; ++i) { CallInst *CI = TailCalls[i]; CallSite CS(CI); // Conservatively require the attributes of the call to match those of the // return. Ignore noalias because it doesn't affect the call sequence. Attributes CalleeRetAttr = CS.getAttributes().getRetAttributes(); if ((CalleeRetAttr ^ CallerRetAttr) & ~Attribute::NoAlias) continue; // Make sure the call instruction is followed by an unconditional branch to // the return block. BasicBlock *CallBB = CI->getParent(); BranchInst *BI = dyn_cast<BranchInst>(CallBB->getTerminator()); if (!BI || !BI->isUnconditional() || BI->getSuccessor(0) != BB) continue; // Duplicate the return into CallBB. (void)FoldReturnIntoUncondBranch(RI, BB, CallBB); ModifiedDT = Changed = true; ++NumRetsDup; } // If we eliminated all predecessors of the block, delete the block now. if (Changed && pred_begin(BB) == pred_end(BB)) BB->eraseFromParent(); return Changed; }
bool TypeChecksOpt::runOnModule(Module &M) { TS = &getAnalysis<dsa::TypeSafety<TDDataStructures> >(); // Create the necessary prototypes VoidTy = IntegerType::getVoidTy(M.getContext()); Int8Ty = IntegerType::getInt8Ty(M.getContext()); Int32Ty = IntegerType::getInt32Ty(M.getContext()); Int64Ty = IntegerType::getInt64Ty(M.getContext()); VoidPtrTy = PointerType::getUnqual(Int8Ty); TypeTagTy = Int8Ty; TypeTagPtrTy = PointerType::getUnqual(TypeTagTy); Constant *memsetF = M.getOrInsertFunction ("llvm.memset.i64", VoidTy, VoidPtrTy, Int8Ty, Int64Ty, Int32Ty, NULL); trackGlobal = M.getOrInsertFunction("trackGlobal", VoidTy, VoidPtrTy,/*ptr*/ TypeTagTy,/*type*/ Int64Ty,/*size*/ Int32Ty,/*tag*/ NULL); trackInitInst = M.getOrInsertFunction("trackInitInst", VoidTy, VoidPtrTy,/*ptr*/ Int64Ty,/*size*/ Int32Ty,/*tag*/ NULL); trackUnInitInst = M.getOrInsertFunction("trackUnInitInst", VoidTy, VoidPtrTy,/*ptr*/ Int64Ty,/*size*/ Int32Ty,/*tag*/ NULL); trackStoreInst = M.getOrInsertFunction("trackStoreInst", VoidTy, VoidPtrTy,/*ptr*/ TypeTagTy,/*type*/ Int64Ty,/*size*/ Int32Ty,/*tag*/ NULL); checkTypeInst = M.getOrInsertFunction("checkType", VoidTy, TypeTagTy,/*type*/ Int64Ty,/*size*/ TypeTagPtrTy, VoidPtrTy,/*ptr*/ Int32Ty,/*tag*/ NULL); copyTypeInfo = M.getOrInsertFunction("copyTypeInfo", VoidTy, VoidPtrTy,/*dest ptr*/ VoidPtrTy,/*src ptr*/ Int64Ty,/*size*/ Int32Ty,/*tag*/ NULL); setTypeInfo = M.getOrInsertFunction("setTypeInfo", VoidTy, VoidPtrTy,/*dest ptr*/ TypeTagPtrTy,/*metadata*/ Int64Ty,/*size*/ TypeTagTy, VoidPtrTy, Int32Ty,/*tag*/ NULL); trackStringInput = M.getOrInsertFunction("trackStringInput", VoidTy, VoidPtrTy, Int32Ty, NULL); getTypeTag = M.getOrInsertFunction("getTypeTag", VoidTy, VoidPtrTy, /*ptr*/ Int64Ty, /*size*/ TypeTagPtrTy, /*dest for type tag*/ Int32Ty, /*tag*/ NULL); MallocFunc = M.getFunction("malloc"); for(Value::use_iterator User = trackGlobal->use_begin(); User != trackGlobal->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { std::vector<Value*>Args; Args.push_back(CI->getOperand(1)); Args.push_back(CI->getOperand(3)); Args.push_back(CI->getOperand(4)); CallInst::Create(trackInitInst, Args, "", CI); toDelete.push_back(CI); } } for(Value::use_iterator User = checkTypeInst->use_begin(); User != checkTypeInst->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(4)->stripPointerCasts(), CI->getParent()->getParent())) { toDelete.push_back(CI); } } for(Value::use_iterator User = trackStoreInst->use_begin(); User != trackStoreInst->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { toDelete.push_back(CI); } } // for alloca's if they are type known // assume initialized with TOP for(Value::use_iterator User = trackUnInitInst->use_begin(); User != trackUnInitInst->use_end(); ) { CallInst *CI = dyn_cast<CallInst>(*(User++)); assert(CI); // check if operand is an alloca inst. if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { CI->setCalledFunction(trackInitInst); if(AllocaInst *AI = dyn_cast<AllocaInst>(CI->getOperand(1)->stripPointerCasts())) { // Initialize the allocation to NULL std::vector<Value *> Args2; Args2.push_back(CI->getOperand(1)); Args2.push_back(ConstantInt::get(Int8Ty, 0)); Args2.push_back(CI->getOperand(2)); Args2.push_back(ConstantInt::get(Int32Ty, AI->getAlignment())); CallInst::Create(memsetF, Args2, "", CI); } } } if(MallocFunc) { for(Value::use_iterator User = MallocFunc->use_begin(); User != MallocFunc->use_end(); User ++) { CallInst *CI = dyn_cast<CallInst>(*User); if(!CI) continue; if(TS->isTypeSafe(CI, CI->getParent()->getParent())){ CastInst *BCI = BitCastInst::CreatePointerCast(CI, VoidPtrTy); CastInst *Size = CastInst::CreateSExtOrBitCast(CI->getOperand(1), Int64Ty); Size->insertAfter(CI); BCI->insertAfter(Size); std::vector<Value *>Args; Args.push_back(BCI); Args.push_back(Size); Args.push_back(ConstantInt::get(Int32Ty, 0)); CallInst *CINew = CallInst::Create(trackInitInst, Args); CINew->insertAfter(BCI); } } } // also do for mallocs/calloc/other allocators??? // other allocators?? for(Value::use_iterator User = copyTypeInfo->use_begin(); User != copyTypeInfo->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { std::vector<Value*> Args; Args.push_back(CI->getOperand(1)); Args.push_back(CI->getOperand(3)); // size Args.push_back(CI->getOperand(4)); CallInst::Create(trackInitInst, Args, "", CI); toDelete.push_back(CI); } } for(Value::use_iterator User = setTypeInfo->use_begin(); User != setTypeInfo->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { std::vector<Value*> Args; Args.push_back(CI->getOperand(1)); Args.push_back(CI->getOperand(3)); // size Args.push_back(CI->getOperand(6)); CallInst::Create(trackInitInst, Args, "", CI); toDelete.push_back(CI); } } for(Value::use_iterator User = getTypeTag->use_begin(); User != getTypeTag->use_end(); ++User) { CallInst *CI = dyn_cast<CallInst>(*User); assert(CI); if(TS->isTypeSafe(CI->getOperand(1)->stripPointerCasts(), CI->getParent()->getParent())) { AllocaInst *AI = dyn_cast<AllocaInst>(CI->getOperand(3)->stripPointerCasts()); assert(AI); std::vector<Value*>Args; Args.push_back(CI->getOperand(3)); Args.push_back(ConstantInt::get(Int8Ty, 255)); Args.push_back(CI->getOperand(2)); Args.push_back(ConstantInt::get(Int32Ty, AI->getAlignment())); CallInst::Create(memsetF, Args, "", CI); toDelete.push_back(CI); } } numSafe += toDelete.size(); while(!toDelete.empty()) { Instruction *I = toDelete.back(); toDelete.pop_back(); I->eraseFromParent(); } return (numSafe > 0); }