// Get the value we should change this callsite to call instead. Value *CSDataRando::getCloneCalledValue(CallSite CS, FuncInfo &CalleeInfo) { if (CalleeInfo.ArgNodes.size() == 0) { return nullptr; } // Find the function type we want based on how many args need to be added. We // do this in case the original function has been cast to a different type. FunctionType *FT = CS.getFunctionType(); SmallVector<Type*, 8> Params; Params.insert(Params.end(), FT->param_begin(), FT->param_end()); Params.insert(Params.end(), CalleeInfo.ArgNodes.size(), MaskTy); FunctionType *TargetType = FunctionType::get(FT->getReturnType(), Params, FT->isVarArg()); IRBuilder<> Builder(CS.getInstruction()); // Direct call, find the clone and cast it to what we want. if (Function *F = dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts())) { Value *Clone = OldToNewFuncMap[F]; if (Clone) { Clone = Builder.CreateBitCast(Clone, PointerType::getUnqual(TargetType)); } return Clone; } // Indirect calls, cast the called value to the type we want. Value *CalledValue = CS.getCalledValue(); return Builder.CreateBitCast(CalledValue, PointerType::getUnqual(TargetType)); }
Function *WebAssemblyLowerEmscriptenEHSjLj::getInvokeWrapper(CallOrInvoke *CI) { Module *M = CI->getModule(); SmallVector<Type *, 16> ArgTys; Value *Callee = CI->getCalledValue(); FunctionType *CalleeFTy; if (auto *F = dyn_cast<Function>(Callee)) CalleeFTy = F->getFunctionType(); else { auto *CalleeTy = cast<PointerType>(Callee->getType())->getElementType(); CalleeFTy = dyn_cast<FunctionType>(CalleeTy); } std::string Sig = getSignature(CalleeFTy); if (InvokeWrappers.find(Sig) != InvokeWrappers.end()) return InvokeWrappers[Sig]; // Put the pointer to the callee as first argument ArgTys.push_back(PointerType::getUnqual(CalleeFTy)); // Add argument types ArgTys.append(CalleeFTy->param_begin(), CalleeFTy->param_end()); FunctionType *FTy = FunctionType::get(CalleeFTy->getReturnType(), ArgTys, CalleeFTy->isVarArg()); Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, InvokePrefix + Sig, M); InvokeWrappers[Sig] = F; return F; }
// Maybe make a clone, if a clone is made, return a pointer to it, if a clone // was not made return nullptr. Function *CSDataRando::makeFunctionClone(Function *F) { // Now we know how many arguments need to be passed, so we make the clones FuncInfo &FI = FunctionInfo[F]; if (FI.ArgNodes.size() == 0) { // No additional args to pass, no need to clone. return nullptr; } // Determine the type of the new function, we insert the new parameters for // the masks after the normal arguments, but before any va_args Type *MaskTy = TypeBuilder<mask_t, false>::get(F->getContext()); FunctionType *OldFuncTy = F->getFunctionType(); std::vector<Type*> ArgTys; ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end()); ArgTys.insert(ArgTys.end(), FI.ArgNodes.size(), MaskTy); FunctionType *CloneFuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); Function *Clone = Function::Create(CloneFuncTy, Function::InternalLinkage, F->getName() + "_CONTEXT_SENSITIVE"); F->getParent()->getFunctionList().insert(F->getIterator(), Clone); Function::arg_iterator CI = Clone->arg_begin(), CE = Clone->arg_end(); // Map the old arguments to the clone arguments and set the name of the // clone arguments the same as the original. for (Function::arg_iterator i = F->arg_begin(), e = F->arg_end(); i != e && CI != CE; i++, CI++) { FI.OldToNewMap[&*i] = &*CI; CI->setName(i->getName()); } // Set the name of the arg masks and associate them with the nodes they are // the masks for. for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++CI) { CI->setName("arg_mask"); FI.ArgMaskMap[FI.ArgNodes[i]] = &*CI; } SmallVector<ReturnInst*, 8> Returns; CloneFunctionInto(Clone, F, FI.OldToNewMap, false, Returns); Clone->setCallingConv(F->getCallingConv()); // Invert OldToNewMap for (auto I : FI.OldToNewMap) { FI.NewToOldMap[I.second] = I.first; } NumClones++; return Clone; }
static bool ExpandVarArgFunc(Module *M, Function *Func) { if (isEmscriptenJSArgsFunc(M, Func->getName())) return false; Type *PtrType = Type::getInt8PtrTy(Func->getContext()); FunctionType *FTy = Func->getFunctionType(); SmallVector<Type *, 8> Params(FTy->param_begin(), FTy->param_end()); Params.push_back(PtrType); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, /*isVarArg=*/false); Function *NewFunc = RecreateFunction(Func, NFTy); // Declare the new argument as "noalias". NewFunc->setAttributes(Func->getAttributes().addAttribute( Func->getContext(), FTy->getNumParams() + 1, Attribute::NoAlias)); // Move the arguments across to the new function. auto NewArg = NewFunc->arg_begin(); for (Argument &Arg : Func->args()) { Arg.replaceAllUsesWith(NewArg); NewArg->takeName(&Arg); ++NewArg; } // The last argument is the new `i8 * noalias %varargs`. NewArg->setName("varargs"); Func->eraseFromParent(); // Expand out uses of llvm.va_start in this function. for (BasicBlock &BB : *NewFunc) { for (auto BI = BB.begin(), BE = BB.end(); BI != BE;) { Instruction *I = BI++; if (auto *VAS = dyn_cast<VAStartInst>(I)) { IRBuilder<> IRB(VAS); Value *Cast = IRB.CreateBitCast(VAS->getArgList(), PtrType->getPointerTo(), "arglist"); IRB.CreateStore(NewArg, Cast); VAS->eraseFromParent(); } } } return true; }
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if /// llvm.vastart is never called, the varargs list is dead for the function. bool DAE::DeleteDeadVarargs(Function &Fn) { assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!"); if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false; // Ensure that the function is only directly called. if (Fn.hasAddressTaken()) return false; // Don't touch naked functions. The assembly might be using an argument, or // otherwise rely on the frame layout in a way that this analysis will not // see. if (Fn.hasFnAttribute(Attribute::Naked)) { return false; } // Okay, we know we can transform this function if safe. Scan its body // looking for calls marked musttail or calls to llvm.vastart. for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { CallInst *CI = dyn_cast<CallInst>(I); if (!CI) continue; if (CI->isMustTailCall()) return false; if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) { if (II->getIntrinsicID() == Intrinsic::vastart) return false; } } } // If we get here, there are no calls to llvm.vastart in the function body, // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as // the old function, but doesn't have isVarArg set. FunctionType *FTy = Fn.getFunctionType(); std::vector<Type*> Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); unsigned NumArgs = Params.size(); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, Fn.getLinkage()); NF->copyAttributesFrom(&Fn); Fn.getParent()->getFunctionList().insert(Fn.getIterator(), NF); NF->takeName(&Fn); // Loop over all of the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector<Value*> Args; for (Value::user_iterator I = Fn.user_begin(), E = Fn.user_end(); I != E; ) { CallSite CS(*I++); if (!CS) continue; Instruction *Call = CS.getInstruction(); // Pass all the same arguments. Args.assign(CS.arg_begin(), CS.arg_begin() + NumArgs); // Drop any attributes that were on the vararg arguments. AttributeSet PAL = CS.getAttributes(); if (!PAL.isEmpty() && PAL.getSlotIndex(PAL.getNumSlots() - 1) > NumArgs) { SmallVector<AttributeSet, 8> AttributesVec; for (unsigned i = 0; PAL.getSlotIndex(i) <= NumArgs; ++i) AttributesVec.push_back(PAL.getSlotAttributes(i)); if (PAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(Fn.getContext(), PAL.getFnAttributes())); PAL = AttributeSet::get(Fn.getContext(), AttributesVec); } Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(PAL); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(PAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); if (!Call->use_empty()) Call->replaceAllUsesWith(New); New->takeName(Call); // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. While we're at // it, remove the dead arguments from the DeadArguments list. // for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++I2) { // Move the name and users over to the new version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); } // Patch the pointer to LLVM function in debug info descriptor. NF->setSubprogram(Fn.getSubprogram()); // Fix up any BlockAddresses that refer to the function. Fn.replaceAllUsesWith(ConstantExpr::getBitCast(NF, Fn.getType())); // Delete the bitcast that we just created, so that NF does not // appear to be address-taken. NF->removeDeadConstantUsers(); // Finally, nuke the old function. Fn.eraseFromParent(); return true; }
static bool ExpandVarArgCall(Module *M, InstType *Call, DataLayout *DL) { FunctionType *FuncType = cast<FunctionType>( Call->getCalledValue()->getType()->getPointerElementType()); if (!FuncType->isFunctionVarArg()) return false; if (auto *F = dyn_cast<Function>(Call->getCalledValue())) if (isEmscriptenJSArgsFunc(M, F->getName())) return false; Function *F = Call->getParent()->getParent(); LLVMContext &Ctx = M->getContext(); SmallVector<AttributeSet, 8> Attrs; Attrs.push_back(Call->getAttributes().getFnAttributes()); Attrs.push_back(Call->getAttributes().getRetAttributes()); // Split argument list into fixed and variable arguments. SmallVector<Value *, 8> FixedArgs; SmallVector<Value *, 8> VarArgs; SmallVector<Type *, 8> VarArgsTypes; for (unsigned I = 0, E = FuncType->getNumParams(); I < E; ++I) { FixedArgs.push_back(Call->getArgOperand(I)); // AttributeSets use 1-based indexing. Attrs.push_back(Call->getAttributes().getParamAttributes(I + 1)); } for (unsigned I = FuncType->getNumParams(), E = Call->getNumArgOperands(); I < E; ++I) { Value *ArgVal = Call->getArgOperand(I); VarArgs.push_back(ArgVal); bool isByVal = Call->getAttributes().hasAttribute(I + 1, Attribute::ByVal); // For "byval" arguments we must dereference the pointer. VarArgsTypes.push_back(isByVal ? ArgVal->getType()->getPointerElementType() : ArgVal->getType()); } if (VarArgsTypes.size() == 0) { // Some buggy code (e.g. 176.gcc in Spec2k) uses va_arg on an // empty argument list, which gives undefined behaviour in C. To // work around such programs, we create a dummy varargs buffer on // the stack even though there are no arguments to put in it. // This allows va_arg to read an undefined value from the stack // rather than crashing by reading from an uninitialized pointer. // An alternative would be to pass a null pointer to catch the // invalid use of va_arg. VarArgsTypes.push_back(Type::getInt32Ty(Ctx)); } // Create struct type for packing variable arguments into. StructType *VarArgsTy = StructType::get(Ctx, VarArgsTypes); // Allocate space for the variable argument buffer. Do this at the // start of the function so that we don't leak space if the function // is called in a loop. IRBuilder<> IRB(F->getEntryBlock().getFirstInsertionPt()); auto *Buf = IRB.CreateAlloca(VarArgsTy, nullptr, "vararg_buffer"); // Call llvm.lifetime.start/end intrinsics to indicate that Buf is // only used for the duration of the function call, so that the // stack space can be reused elsewhere. auto LifetimeStart = Intrinsic::getDeclaration(M, Intrinsic::lifetime_start); auto LifetimeEnd = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end); auto *I8Ptr = Type::getInt8Ty(Ctx)->getPointerTo(); auto *BufPtr = IRB.CreateBitCast(Buf, I8Ptr, "vararg_lifetime_bitcast"); auto *BufSize = ConstantInt::get(Ctx, APInt(64, DL->getTypeAllocSize(VarArgsTy))); IRB.CreateCall2(LifetimeStart, BufSize, BufPtr); // Copy variable arguments into buffer. int Index = 0; IRB.SetInsertPoint(Call); for (Value *Arg : VarArgs) { Value *Indexes[] = {ConstantInt::get(Ctx, APInt(32, 0)), ConstantInt::get(Ctx, APInt(32, Index))}; Value *Ptr = IRB.CreateInBoundsGEP(Buf, Indexes, "vararg_ptr"); bool isByVal = Call->getAttributes().hasAttribute( FuncType->getNumParams() + Index + 1, Attribute::ByVal); if (isByVal) IRB.CreateMemCpy(Ptr, Arg, DL->getTypeAllocSize( Arg->getType()->getPointerElementType()), /*Align=*/1); else IRB.CreateStore(Arg, Ptr); ++Index; } // Cast function to new type to add our extra pointer argument. SmallVector<Type *, 8> ArgTypes(FuncType->param_begin(), FuncType->param_end()); ArgTypes.push_back(VarArgsTy->getPointerTo()); FunctionType *NFTy = FunctionType::get(FuncType->getReturnType(), ArgTypes, /*isVarArg=*/false); Value *CastFunc = IRB.CreateBitCast(Call->getCalledValue(), NFTy->getPointerTo(), "vararg_func"); // Create the converted function call. FixedArgs.push_back(Buf); Instruction *NewCall; if (auto *C = dyn_cast<CallInst>(Call)) { auto *N = IRB.CreateCall(CastFunc, FixedArgs); N->setAttributes(AttributeSet::get(Ctx, Attrs)); NewCall = N; IRB.CreateCall2(LifetimeEnd, BufSize, BufPtr); } else if (auto *C = dyn_cast<InvokeInst>(Call)) { auto *N = IRB.CreateInvoke(CastFunc, C->getNormalDest(), C->getUnwindDest(), FixedArgs, C->getName()); N->setAttributes(AttributeSet::get(Ctx, Attrs)); (IRBuilder<>(C->getNormalDest()->getFirstInsertionPt())) .CreateCall2(LifetimeEnd, BufSize, BufPtr); (IRBuilder<>(C->getUnwindDest()->getFirstInsertionPt())) .CreateCall2(LifetimeEnd, BufSize, BufPtr); NewCall = N; } else { llvm_unreachable("not a call/invoke"); } NewCall->takeName(Call); Call->replaceAllUsesWith(NewCall); Call->eraseFromParent(); return true; }
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if /// llvm.vastart is never called, the varargs list is dead for the function. bool DAE::DeleteDeadVarargs(Function &Fn) { assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!"); if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false; // Ensure that the function is only directly called. if (Fn.hasAddressTaken()) return false; // Okay, we know we can transform this function if safe. Scan its body // looking for calls to llvm.vastart. for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { if (II->getIntrinsicID() == Intrinsic::vastart) return false; } } } // If we get here, there are no calls to llvm.vastart in the function body, // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as // the old function, but doesn't have isVarArg set. FunctionType *FTy = Fn.getFunctionType(); std::vector<Type*> Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); unsigned NumArgs = Params.size(); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, Fn.getLinkage()); NF->copyAttributesFrom(&Fn); Fn.getParent()->getFunctionList().insert(&Fn, NF); NF->takeName(&Fn); // Loop over all of the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector<Value*> Args; while (!Fn.use_empty()) { CallSite CS(Fn.use_back()); Instruction *Call = CS.getInstruction(); // Pass all the same arguments. Args.assign(CS.arg_begin(), CS.arg_begin() + NumArgs); // Drop any attributes that were on the vararg arguments. AttrListPtr PAL = CS.getAttributes(); if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) { SmallVector<AttributeWithIndex, 8> AttributesVec; for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i) AttributesVec.push_back(PAL.getSlot(i)); if (Attributes FnAttrs = PAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); PAL = AttrListPtr::get(AttributesVec); } Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(PAL); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(PAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); if (!Call->use_empty()) Call->replaceAllUsesWith(New); New->takeName(Call); // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. While we're at // it, remove the dead arguments from the DeadArguments list. // for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++I2) { // Move the name and users over to the new version. I->replaceAllUsesWith(I2); I2->takeName(I); } // Finally, nuke the old function. Fn.eraseFromParent(); return true; }
// MakeFunctionClone - If the specified function needs to be modified for pool // allocation support, make a clone of it, adding additional arguments as // necessary, and return it. If not, just return null. // Function* RTAssociate::MakeFunctionClone(Function &F, FuncInfo& FI, DSGraph* G) { if (G->node_begin() == G->node_end()) return 0; if (FI.ArgNodes.empty()) return 0; // No need to clone if no pools need to be passed in! // Update statistics.. NumArgsAdded += FI.ArgNodes.size(); if (MaxArgsAdded < FI.ArgNodes.size()) MaxArgsAdded = FI.ArgNodes.size(); ++NumCloned; // Figure out what the arguments are to be for the new version of the // function FunctionType *OldFuncTy = F.getFunctionType(); std::vector<Type*> ArgTys(FI.ArgNodes.size(), PoolDescPtrTy); ArgTys.reserve(OldFuncTy->getNumParams() + FI.ArgNodes.size()); ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end()); // Create the new function prototype FunctionType *FuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); // Create the new function... Function *New = Function::Create(FuncTy, Function::InternalLinkage, F.getName()); New->copyAttributesFrom(&F); F.getParent()->getFunctionList().insert(&F, New); // Set the rest of the new arguments names to be PDa<n> and add entries to the // pool descriptors map Function::arg_iterator NI = New->arg_begin(); for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) { FI.PoolDescriptors[FI.ArgNodes[i]] = CreateArgPool(FI.ArgNodes[i], NI); NI->setName("PDa"); } // Map the existing arguments of the old function to the corresponding // arguments of the new function, and copy over the names. ValueToValueMapTy ValueMap; for (Function::arg_iterator I = F.arg_begin(); NI != New->arg_end(); ++I, ++NI) { ValueMap[I] = NI; NI->setName(I->getName()); } // Perform the cloning. SmallVector<ReturnInst*,100> Returns; // TODO: review the boolean flag here CloneFunctionInto(New, &F, ValueMap, true, Returns); // // The CloneFunctionInto() function will copy the parameter attributes // verbatim. This is incorrect; each attribute should be shifted one so // that the pool descriptor has no attributes. // const AttributeSet OldAttrs = New->getAttributes(); if (!OldAttrs.isEmpty()) { AttributeSet NewAttrs; for (unsigned index = 0; index < OldAttrs.getNumSlots(); ++index) { const AttributeSet & PAWI = OldAttrs.getSlotAttributes(index); unsigned argIndex = OldAttrs.getSlotIndex(index); // If it's not the return value, move the attribute to the next // parameter. if (argIndex) ++argIndex; // Add the parameter to the new list. NewAttrs = NewAttrs.addAttributes(F.getContext(), argIndex, PAWI); } // Assign the new attributes to the function clone New->setAttributes(NewAttrs); } for (ValueToValueMapTy::iterator I = ValueMap.begin(), E = ValueMap.end(); I != E; ++I) FI.NewToOldValueMap.insert(std::make_pair(I->second, const_cast<Value*>(I->first))); return FI.Clone = New; }
/// Merge all functions in \p FInfos by creating thunks which call the single /// merged function with additional parameters. void SwiftMergeFunctions::mergeWithParams(const FunctionInfos &FInfos, ParamInfos &Params) { // We reuse the body of the first function for the new merged function. Function *FirstF = FInfos.front().F; // Build the type for the merged function. This will be the type of the // original function (FirstF) but with the additional parameter which are // needed to parameterize the merged function. FunctionType *OrigTy = FirstF->getFunctionType(); SmallVector<Type *, 8> ParamTypes(OrigTy->param_begin(), OrigTy->param_end()); for (const ParamInfo &PI : Params) { ParamTypes.push_back(PI.Values[0]->getType()); } FunctionType *funcType = FunctionType::get(OrigTy->getReturnType(), ParamTypes, false); // Create the new function. // TODO: Use a better name than just adding a suffix. Ideally it would be // a name which can be demangled in a meaningful way. Function *NewFunction = Function::Create(funcType, FirstF->getLinkage(), FirstF->getName() + "Tm"); NewFunction->copyAttributesFrom(FirstF); // NOTE: this function is not externally available, do ensure that we reset // the DLL storage NewFunction->setDLLStorageClass(GlobalValue::DefaultStorageClass); NewFunction->setLinkage(GlobalValue::InternalLinkage); // Insert the new function after the last function in the equivalence class. FirstF->getParent()->getFunctionList().insert( std::next(FInfos[1].F->getIterator()), NewFunction); LLVM_DEBUG(dbgs() << " Merge into " << NewFunction->getName() << '\n'); // Move the body of FirstF into the NewFunction. NewFunction->getBasicBlockList().splice(NewFunction->begin(), FirstF->getBasicBlockList()); auto NewArgIter = NewFunction->arg_begin(); for (Argument &OrigArg : FirstF->args()) { Argument &NewArg = *NewArgIter++; OrigArg.replaceAllUsesWith(&NewArg); } SmallPtrSet<Function *, 8> SelfReferencingFunctions; // Replace all differing operands with a parameter. for (const ParamInfo &PI : Params) { Argument *NewArg = &*NewArgIter++; for (const OpLocation &OL : PI.Uses) { OL.I->setOperand(OL.OpIndex, NewArg); } ParamTypes.push_back(PI.Values[0]->getType()); // Collect all functions which are referenced by any parameter. for (Value *V : PI.Values) { if (auto *F = dyn_cast<Function>(V)) SelfReferencingFunctions.insert(F); } } for (unsigned FIdx = 0, NumFuncs = FInfos.size(); FIdx < NumFuncs; ++FIdx) { Function *OrigFunc = FInfos[FIdx].F; // Don't try to replace all callers of functions which are used as // parameters because we must not delete such functions. if (SelfReferencingFunctions.count(OrigFunc) == 0 && replaceDirectCallers(OrigFunc, NewFunction, Params, FIdx)) { // We could replace all uses (and the function is not externally visible), // so we can delete the original function. auto Iter = FuncEntries.find(OrigFunc); assert(Iter != FuncEntries.end()); assert(!isInEquivalenceClass(&*Iter->second)); Iter->second->F = nullptr; FuncEntries.erase(Iter); LLVM_DEBUG(dbgs() << " Erase " << OrigFunc->getName() << '\n'); OrigFunc->eraseFromParent(); } else { // Otherwise we need a thunk which calls the merged function. writeThunk(NewFunction, OrigFunc, Params, FIdx); } ++NumSwiftFunctionsMerged; } }
void LLVMGetParamTypes(LLVMTypeRef FunctionTy, LLVMTypeRef *Dest) { FunctionType *Ty = unwrap<FunctionType>(FunctionTy); for (FunctionType::param_iterator I = Ty->param_begin(), E = Ty->param_end(); I != E; ++I) *Dest++ = wrap(*I); }