本文整理汇总了C++中FunctionType::param_end方法的典型用法代码示例。如果您正苦于以下问题:C++ FunctionType::param_end方法的具体用法?C++ FunctionType::param_end怎么用?C++ FunctionType::param_end使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类FunctionType
的用法示例。
在下文中一共展示了FunctionType::param_end方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: Builder
// 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));
}
示例2: getSignature
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;
}
示例3: CloneFunctionInto
// 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;
}
示例4: ExpandVarArgFunc
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;
}
示例5: DeleteDeadVarargs
/// 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.
//.........这里部分代码省略.........
示例6: ExpandVarArgCall
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;
//.........这里部分代码省略.........
示例7: DeleteDeadVarargs
/// 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.
//.........这里部分代码省略.........
示例8: MakeFunctionClone
// 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;
}
示例9: mergeWithParams
/// 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;
}
}
示例10: LLVMGetParamTypes
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);
}