void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const { ManglerPrefixTy PrefixTy = Default; if (GV->hasPrivateLinkage()) { if (CannotUsePrivateLabel) PrefixTy = LinkerPrivate; else PrefixTy = Private; } const DataLayout &DL = GV->getParent()->getDataLayout(); if (!GV->hasName()) { // Get the ID for the global, assigning a new one if we haven't got one // already. unsigned &ID = AnonGlobalIDs[GV]; if (ID == 0) ID = AnonGlobalIDs.size(); // Must mangle the global into a unique ID. getNameWithPrefixImpl(OS, "__unnamed_" + Twine(ID), DL, PrefixTy); return; } StringRef Name = GV->getName(); char Prefix = DL.getGlobalPrefix(); // Mangle functions with Microsoft calling conventions specially. Only do // this mangling for x86_64 vectorcall and 32-bit x86. const Function *MSFunc = dyn_cast<Function>(GV); if (Name.startswith("\01")) MSFunc = nullptr; // Don't mangle when \01 is present. CallingConv::ID CC = MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C; if (!DL.hasMicrosoftFastStdCallMangling() && CC != CallingConv::X86_VectorCall) MSFunc = nullptr; if (MSFunc) { if (CC == CallingConv::X86_FastCall) Prefix = '@'; // fastcall functions have an @ prefix instead of _. else if (CC == CallingConv::X86_VectorCall) Prefix = '\0'; // vectorcall functions have no prefix. } getNameWithPrefixImpl(OS, Name, PrefixTy, DL, Prefix); if (!MSFunc) return; // If we are supposed to add a microsoft-style suffix for stdcall, fastcall, // or vectorcall, add it. These functions have a suffix of @N where N is the // cumulative byte size of all of the parameters to the function in decimal. if (CC == CallingConv::X86_VectorCall) OS << '@'; // vectorcall functions use a double @ suffix. FunctionType *FT = MSFunc->getFunctionType(); if (hasByteCountSuffix(CC) && // "Pure" variadic functions do not receive @0 suffix. (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr()))) addByteCountSuffix(OS, MSFunc, DL); }
void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, bool CannotUsePrivateLabel) const { ManglerPrefixTy PrefixTy = Mangler::Default; if (GV->hasPrivateLinkage()) { if (CannotUsePrivateLabel) PrefixTy = Mangler::LinkerPrivate; else PrefixTy = Mangler::Private; } if (!GV->hasName()) { // Get the ID for the global, assigning a new one if we haven't got one // already. unsigned &ID = AnonGlobalIDs[GV]; if (ID == 0) ID = NextAnonGlobalID++; // Must mangle the global into a unique ID. getNameWithPrefix(OS, "__unnamed_" + Twine(ID), PrefixTy); return; } StringRef Name = GV->getName(); // No need to do anything special if the global has the special "do not // mangle" flag in the name. if (Name[0] == '\1') { OS << Name.substr(1); return; } bool UseAt = false; const Function *MSFunc = nullptr; CallingConv::ID CC; if (DL->hasMicrosoftFastStdCallMangling()) { if ((MSFunc = dyn_cast<Function>(GV))) { CC = MSFunc->getCallingConv(); // fastcall functions need to start with @ instead of _. if (CC == CallingConv::X86_FastCall) UseAt = true; } } getNameWithPrefixx(OS, Name, PrefixTy, *DL, UseAt); if (!MSFunc) return; // If we are supposed to add a microsoft-style suffix for stdcall/fastcall, // add it. // fastcall and stdcall functions usually need @42 at the end to specify // the argument info. FunctionType *FT = MSFunc->getFunctionType(); if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) && // "Pure" variadic functions do not receive @0 suffix. (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr()))) AddFastCallStdCallSuffix(OS, MSFunc, *DL); }
/// getNameWithPrefix - Fill OutName with the name of the appropriate prefix /// and the specified global variable's name. If the global variable doesn't /// have a name, this fills in a unique name for the global. void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV) { ManglerPrefixTy PrefixTy = Mangler::Default; if (GV->hasPrivateLinkage()) PrefixTy = Mangler::Private; else if (GV->hasLinkerPrivateLinkage() || GV->hasLinkerPrivateWeakLinkage()) PrefixTy = Mangler::LinkerPrivate; // If this global has a name, handle it simply. if (GV->hasName()) { StringRef Name = GV->getName(); getNameWithPrefix(OutName, Name, PrefixTy); // No need to do anything else if the global has the special "do not mangle" // flag in the name. if (Name[0] == 1) return; } else { // Get the ID for the global, assigning a new one if we haven't got one // already. unsigned &ID = AnonGlobalIDs[GV]; if (ID == 0) ID = NextAnonGlobalID++; // Must mangle the global into a unique ID. getNameWithPrefix(OutName, "__unnamed_" + Twine(ID), PrefixTy); } // If we are supposed to add a microsoft-style suffix for stdcall/fastcall, // add it. if (DL->hasMicrosoftFastStdCallMangling()) { if (const Function *F = dyn_cast<Function>(GV)) { CallingConv::ID CC = F->getCallingConv(); // fastcall functions need to start with @. // FIXME: This logic seems unlikely to be right. if (CC == CallingConv::X86_FastCall) { if (OutName[0] == '_') OutName[0] = '@'; else OutName.insert(OutName.begin(), '@'); } // fastcall and stdcall functions usually need @42 at the end to specify // the argument info. FunctionType *FT = F->getFunctionType(); if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) && // "Pure" variadic functions do not receive @0 suffix. (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && F->hasStructRetAttr()))) AddFastCallStdCallSuffix(OutName, F, *DL); } } }
/// isFreeCall - Returns non-null if the value is a call to the builtin free() static const CallInst* isFreeCall(const Value* I) { const CallInst* CI = dyn_cast<CallInst>(I); if (!CI) return 0; Function* Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration()) return 0; if (Callee->getName() != "free" /*&& Callee->getName() != "my_free" && Callee->getName() != "_ZdlPv" && // operator delete(void*) Callee->getName() != "_ZdaPv"*/) // operator delete[](void*) return 0; // Check free prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. FunctionType* FTy = Callee->getFunctionType(); if (!FTy->getReturnType()->isVoidTy()) return 0; if (FTy->getNumParams() != 1) return 0; if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext())) return 0; return CI; }
/// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { const CallInst *CI = dyn_cast<CallInst>(I); if (!CI || isa<IntrinsicInst>(CI)) return 0; Function *Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration()) return 0; StringRef FnName = Callee->getName(); LibFunc::Func TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return 0; if (TLIFn != LibFunc::free && TLIFn != LibFunc::ZdlPv && // operator delete(void*) TLIFn != LibFunc::ZdaPv) // operator delete[](void*) return 0; // Check free prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. FunctionType *FTy = Callee->getFunctionType(); if (!FTy->getReturnType()->isVoidTy()) return 0; if (FTy->getNumParams() != 1) return 0; if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext())) return 0; return CI; }
void TypeDuplicater::RemoveNonLocalTypes(Module &M){ std::set<Function *> UndefinedFunctions; for(auto IF = M.begin(), EF = M.end(); IF != EF; ++IF){ Function *F = &*IF; if(F->isDeclaration()) UndefinedFunctions.insert(F); } for(auto F: UndefinedFunctions){ FunctionType *FuncType = cast<FunctionType>(F->getFunctionType()); for(int i=0; i<FuncType->getNumParams(); i++){ Type *T =FuncType->getParamType(i); while(T->isPointerTy()) T = T->getPointerElementType(); if(auto *ST = dyn_cast<StructType>(T)) RawStructs.erase(ST); } Type *T =FuncType->getReturnType(); while(T->isPointerTy()) T = T->getPointerElementType(); if(auto *ST = dyn_cast<StructType>(T)) RawStructs.erase(ST); } }
void Mapper::remapInstruction(Instruction *I) { // Remap operands. for (Use &Op : I->operands()) { Value *V = mapValue(Op); // If we aren't ignoring missing entries, assert that something happened. if (V) Op = V; else assert((Flags & RF_IgnoreMissingLocals) && "Referenced value not in value map!"); } // Remap phi nodes' incoming blocks. if (PHINode *PN = dyn_cast<PHINode>(I)) { for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *V = mapValue(PN->getIncomingBlock(i)); // If we aren't ignoring missing entries, assert that something happened. if (V) PN->setIncomingBlock(i, cast<BasicBlock>(V)); else assert((Flags & RF_IgnoreMissingLocals) && "Referenced block not in value map!"); } } // Remap attached metadata. SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; I->getAllMetadata(MDs); for (const auto &MI : MDs) { MDNode *Old = MI.second; MDNode *New = cast_or_null<MDNode>(mapMetadata(Old)); if (New != Old) I->setMetadata(MI.first, New); } if (!TypeMapper) return; // If the instruction's type is being remapped, do so now. if (auto CS = CallSite(I)) { SmallVector<Type *, 3> Tys; FunctionType *FTy = CS.getFunctionType(); Tys.reserve(FTy->getNumParams()); for (Type *Ty : FTy->params()) Tys.push_back(TypeMapper->remapType(Ty)); CS.mutateFunctionType(FunctionType::get( TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg())); return; } if (auto *AI = dyn_cast<AllocaInst>(I)) AI->setAllocatedType(TypeMapper->remapType(AI->getAllocatedType())); if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) { GEP->setSourceElementType( TypeMapper->remapType(GEP->getSourceElementType())); GEP->setResultElementType( TypeMapper->remapType(GEP->getResultElementType())); } I->mutateType(TypeMapper->remapType(I->getType())); }
/// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { bool IsNoBuiltinCall; const Function *Callee = getCalledFunction(I, /*LookThroughBitCast=*/false, IsNoBuiltinCall); if (Callee == nullptr || IsNoBuiltinCall) return nullptr; StringRef FnName = Callee->getName(); LibFunc TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return nullptr; unsigned ExpectedNumParams; if (TLIFn == LibFunc_free || TLIFn == LibFunc_ZdlPv || // operator delete(void*) TLIFn == LibFunc_ZdaPv || // operator delete[](void*) TLIFn == LibFunc_msvc_delete_ptr32 || // operator delete(void*) TLIFn == LibFunc_msvc_delete_ptr64 || // operator delete(void*) TLIFn == LibFunc_msvc_delete_array_ptr32 || // operator delete[](void*) TLIFn == LibFunc_msvc_delete_array_ptr64) // operator delete[](void*) ExpectedNumParams = 1; else if (TLIFn == LibFunc_ZdlPvj || // delete(void*, uint) TLIFn == LibFunc_ZdlPvm || // delete(void*, ulong) TLIFn == LibFunc_ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) TLIFn == LibFunc_ZdlPvSt11align_val_t || // delete(void*, align_val_t) TLIFn == LibFunc_ZdaPvj || // delete[](void*, uint) TLIFn == LibFunc_ZdaPvm || // delete[](void*, ulong) TLIFn == LibFunc_ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) TLIFn == LibFunc_ZdaPvSt11align_val_t || // delete[](void*, align_val_t) TLIFn == LibFunc_msvc_delete_ptr32_int || // delete(void*, uint) TLIFn == LibFunc_msvc_delete_ptr64_longlong || // delete(void*, ulonglong) TLIFn == LibFunc_msvc_delete_ptr32_nothrow || // delete(void*, nothrow) TLIFn == LibFunc_msvc_delete_ptr64_nothrow || // delete(void*, nothrow) TLIFn == LibFunc_msvc_delete_array_ptr32_int || // delete[](void*, uint) TLIFn == LibFunc_msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) TLIFn == LibFunc_msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) TLIFn == LibFunc_msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ExpectedNumParams = 2; else if (TLIFn == LibFunc_ZdaPvSt11align_val_tRKSt9nothrow_t || // delete(void*, align_val_t, nothrow) TLIFn == LibFunc_ZdlPvSt11align_val_tRKSt9nothrow_t) // delete[](void*, align_val_t, nothrow) ExpectedNumParams = 3; else return nullptr; // Check free prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. FunctionType *FTy = Callee->getFunctionType(); if (!FTy->getReturnType()->isVoidTy()) return nullptr; if (FTy->getNumParams() != ExpectedNumParams) return nullptr; if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext())) return nullptr; return dyn_cast<CallInst>(I); }
/// RemapInstruction - Convert the instruction operands from referencing the /// current values into those specified by VMap. /// void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap, RemapFlags Flags, ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer){ // Remap operands. for (User::op_iterator op = I->op_begin(), E = I->op_end(); op != E; ++op) { Value *V = MapValue(*op, VMap, Flags, TypeMapper, Materializer); // If we aren't ignoring missing entries, assert that something happened. if (V) *op = V; else assert((Flags & RF_IgnoreMissingEntries) && "Referenced value not in value map!"); } // Remap phi nodes' incoming blocks. if (PHINode *PN = dyn_cast<PHINode>(I)) { for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *V = MapValue(PN->getIncomingBlock(i), VMap, Flags); // If we aren't ignoring missing entries, assert that something happened. if (V) PN->setIncomingBlock(i, cast<BasicBlock>(V)); else assert((Flags & RF_IgnoreMissingEntries) && "Referenced block not in value map!"); } } // Remap attached metadata. SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; I->getAllMetadata(MDs); for (SmallVectorImpl<std::pair<unsigned, MDNode *>>::iterator MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) { MDNode *Old = MI->second; MDNode *New = MapMetadata(Old, VMap, Flags, TypeMapper, Materializer); if (New != Old) I->setMetadata(MI->first, New); } if (!TypeMapper) return; // If the instruction's type is being remapped, do so now. if (auto CS = CallSite(I)) { SmallVector<Type *, 3> Tys; FunctionType *FTy = CS.getFunctionType(); Tys.reserve(FTy->getNumParams()); for (Type *Ty : FTy->params()) Tys.push_back(TypeMapper->remapType(Ty)); CS.mutateFunctionType(FunctionType::get( TypeMapper->remapType(I->getType()), Tys, FTy->isVarArg())); } else I->mutateType(TypeMapper->remapType(I->getType())); }
// We accept bswap for a limited set of types (i16, i32, i64). // The various backends are able to generate instructions to // implement the intrinsic. Also, i16 and i64 are easy to // implement as along as there is a way to do i32. static bool isWhitelistedBswap(const Function *F) { FunctionType *FT = F->getFunctionType(); if (FT->getNumParams() != 1) return false; Type *ParamType = FT->getParamType(0); LLVMContext &C = F->getContext(); Type *AcceptableTypes[] = { Type::getInt16Ty(C), Type::getInt32Ty(C), Type::getInt64Ty(C) }; return TypeAcceptable(ParamType, AcceptableTypes); }
/// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *llvm::isFreeCall(const Value *I, const TargetLibraryInfo *TLI) { const CallInst *CI = dyn_cast<CallInst>(I); if (!CI || isa<IntrinsicInst>(CI)) return nullptr; Function *Callee = CI->getCalledFunction(); if (Callee == nullptr) return nullptr; StringRef FnName = Callee->getName(); LibFunc::Func TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return nullptr; unsigned ExpectedNumParams; if (TLIFn == LibFunc::free || TLIFn == LibFunc::ZdlPv || // operator delete(void*) TLIFn == LibFunc::ZdaPv || // operator delete[](void*) TLIFn == LibFunc::msvc_delete_ptr32 || // operator delete(void*) TLIFn == LibFunc::msvc_delete_ptr64 || // operator delete(void*) TLIFn == LibFunc::msvc_delete_array_ptr32 || // operator delete[](void*) TLIFn == LibFunc::msvc_delete_array_ptr64) // operator delete[](void*) ExpectedNumParams = 1; else if (TLIFn == LibFunc::ZdlPvj || // delete(void*, uint) TLIFn == LibFunc::ZdlPvm || // delete(void*, ulong) TLIFn == LibFunc::ZdlPvRKSt9nothrow_t || // delete(void*, nothrow) TLIFn == LibFunc::ZdaPvj || // delete[](void*, uint) TLIFn == LibFunc::ZdaPvm || // delete[](void*, ulong) TLIFn == LibFunc::ZdaPvRKSt9nothrow_t || // delete[](void*, nothrow) TLIFn == LibFunc::msvc_delete_ptr32_int || // delete(void*, uint) TLIFn == LibFunc::msvc_delete_ptr64_longlong || // delete(void*, ulonglong) TLIFn == LibFunc::msvc_delete_ptr32_nothrow || // delete(void*, nothrow) TLIFn == LibFunc::msvc_delete_ptr64_nothrow || // delete(void*, nothrow) TLIFn == LibFunc::msvc_delete_array_ptr32_int || // delete[](void*, uint) TLIFn == LibFunc::msvc_delete_array_ptr64_longlong || // delete[](void*, ulonglong) TLIFn == LibFunc::msvc_delete_array_ptr32_nothrow || // delete[](void*, nothrow) TLIFn == LibFunc::msvc_delete_array_ptr64_nothrow) // delete[](void*, nothrow) ExpectedNumParams = 2; else return nullptr; // Check free prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. FunctionType *FTy = Callee->getFunctionType(); if (!FTy->getReturnType()->isVoidTy()) return nullptr; if (FTy->getNumParams() != ExpectedNumParams) return nullptr; if (FTy->getParamType(0) != Type::getInt8PtrTy(Callee->getContext())) return nullptr; return CI; }
static void check(Value *Func, ArrayRef<Value *> Args) { FunctionType *FTy = cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); assert((Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "XXCalling a function with bad signature!"); for (unsigned i = 0; i != Args.size(); ++i) { if (!(FTy->getParamType(i) == Args[i]->getType())) { errs() << "types:\n "; FTy->getParamType(i)->dump(); errs() << "\n "; Args[i]->getType()->dump(); errs() << "\n"; } assert((i >= FTy->getNumParams() || FTy->getParamType(i) == Args[i]->getType()) && "YYCalling a function with a bad signature!"); } }
/// \brief Returns the allocation data for the given value if it is a call to a /// known allocation function, and NULL otherwise. static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false) { // Skip all intrinsics but duetto.allocate if (const IntrinsicInst* II = dyn_cast<IntrinsicInst>(V)) { if (II->getIntrinsicID() == Intrinsic::duetto_allocate) return &AllocationFnData[0]; return 0; } Function *Callee = getCalledFunction(V, LookThroughBitCast); if (!Callee) return 0; // Make sure that the function is available. StringRef FnName = Callee->getName(); LibFunc::Func TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return 0; unsigned i = 0; bool found = false; for ( ; i < array_lengthof(AllocationFnData); ++i) { if (AllocationFnData[i].Func == TLIFn) { found = true; break; } } if (!found) return 0; const AllocFnsTy *FnData = &AllocationFnData[i]; if ((FnData->AllocTy & AllocTy) != FnData->AllocTy) return 0; // Check function prototype. int FstParam = FnData->FstParam; int SndParam = FnData->SndParam; FunctionType *FTy = Callee->getFunctionType(); if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == FnData->NumParams && (FstParam < 0 || (FTy->getParamType(FstParam)->isIntegerTy(32) || FTy->getParamType(FstParam)->isIntegerTy(64))) && (SndParam < 0 || FTy->getParamType(SndParam)->isIntegerTy(32) || FTy->getParamType(SndParam)->isIntegerTy(64))) return FnData; return 0; }
/// Creates a hash-code for the function which is the same for any two /// functions that will compare equal, without looking at the instructions /// inside the function. static unsigned profileFunction(const Function *F) { FunctionType *FTy = F->getFunctionType(); FoldingSetNodeID ID; ID.AddInteger(F->size()); ID.AddInteger(F->getCallingConv()); ID.AddBoolean(F->hasGC()); ID.AddBoolean(FTy->isVarArg()); ID.AddInteger(getTypeIDForHash(FTy->getReturnType())); for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) ID.AddInteger(getTypeIDForHash(FTy->getParamType(i))); return ID.ComputeHash(); }
void Function::BuildLazyArguments() const { // Create the arguments vector, all arguments start out unnamed. FunctionType *FT = getFunctionType(); for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { assert(!FT->getParamType(i)->isVoidTy() && "Cannot have void typed arguments!"); ArgumentList.push_back(new Argument(FT->getParamType(i))); } // Clear the lazy arguments bit. unsigned SDC = getSubclassDataFromValue(); const_cast<Function*>(this)->setValueSubclassData(SDC &= ~1); }
// a simple function 'prototype' printer void printFuncProtoType(Function *F) { F->getReturnType()->dump(); errs() << " " << F->getName() << "("; FunctionType * FTY = F->getFunctionType(); unsigned params = FTY->getNumParams(); unsigned i; for (i = 0; i < params; i++) { FTY->getParamType(i)->dump(); if (i != params - 1) errs() << ","; } errs() << ")"; }
// Helper to find the set of values described by a TSpecifier std::set<const Value*> getValues(const ImmutableCallSite cs, TSpecifier TS) { std::set<const Value*> Values; switch (TS) { case Ret: assert(!cs.getInstruction()->getType()->isVoidTy()); Values.insert(cs.getInstruction()); break; case Arg0: assert(0 < cs.arg_size()); Values.insert(cs.getArgument(0)); break; case Arg1: assert(1 < cs.arg_size()); Values.insert(cs.getArgument(1)); break; case Arg2: assert(2 < cs.arg_size()); Values.insert(cs.getArgument(2)); break; case Arg3: assert(3 < cs.arg_size()); Values.insert(cs.getArgument(3)); break; case Arg4: assert(4 < cs.arg_size()); Values.insert(cs.getArgument(4)); break; case AllArgs: assert(!cs.arg_empty()); for (unsigned i = 0; i < cs.arg_size(); ++i) Values.insert(cs.getArgument(i)); break; case VarArgs: { const Value *Callee = cs.getCalledValue()->stripPointerCasts(); FunctionType *CalleeType = dyn_cast<FunctionType>( dyn_cast<PointerType>(Callee->getType())->getElementType() ); for (unsigned i = CalleeType->getNumParams(); i < cs.arg_size(); ++i) Values.insert(cs.getArgument(i)); break; } } return Values; }
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; }
/// \brief Returns the allocation data for the given value if it is a call to a /// known allocation function, and NULL otherwise. static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy, const TargetLibraryInfo *TLI, bool LookThroughBitCast = false) { // Skip intrinsics if (isa<IntrinsicInst>(V)) return nullptr; Function *Callee = getCalledFunction(V, LookThroughBitCast); if (!Callee) return nullptr; // Make sure that the function is available. StringRef FnName = Callee->getName(); LibFunc::Func TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return nullptr; const AllocFnsTy *FnData = std::find_if(std::begin(AllocationFnData), std::end(AllocationFnData), [TLIFn](const AllocFnsTy &Fn) { return Fn.Func == TLIFn; }); if (FnData == std::end(AllocationFnData)) return nullptr; if ((FnData->AllocTy & AllocTy) != FnData->AllocTy) return nullptr; // Check function prototype. int FstParam = FnData->FstParam; int SndParam = FnData->SndParam; FunctionType *FTy = Callee->getFunctionType(); if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == FnData->NumParams && (FstParam < 0 || (FTy->getParamType(FstParam)->isIntegerTy(32) || FTy->getParamType(FstParam)->isIntegerTy(64))) && (SndParam < 0 || FTy->getParamType(SndParam)->isIntegerTy(32) || FTy->getParamType(SndParam)->isIntegerTy(64))) return FnData; return nullptr; }
static bool isCallocCall(const CallInst *CI) { if (!CI) return false; Function *Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration()) return false; if (Callee->getName() != "calloc") return false; // Check malloc prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute exists. FunctionType *FTy = Callee->getFunctionType(); return FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == 2 && ((FTy->getParamType(0)->isIntegerTy(32) && FTy->getParamType(1)->isIntegerTy(32)) || (FTy->getParamType(0)->isIntegerTy(64) && FTy->getParamType(1)->isIntegerTy(64))); }
// TODO Copy-paste static bool isMallocCall(const CallInst* CI) { if (!CI) return false; Function* Callee = CI->getCalledFunction(); if (Callee == 0 || !Callee->isDeclaration()) return false; if (Callee->getName() != "malloc" /*&& Callee->getName() != "my_malloc" && Callee->getName() != "_Znwj" && // operator new(unsigned int) Callee->getName() != "_Znwm" && // operator new(unsigned long) Callee->getName() != "_Znaj" && // operator new[](unsigned int) Callee->getName() != "_Znam"*/) // operator new[](unsigned long) return false; // Check malloc prototype. // FIXME: workaround for PR5130, this will be obsolete when a nobuiltin // attribute will exist. FunctionType* FTy = Callee->getFunctionType(); return FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == 1 && (FTy->getParamType(0)->isIntegerTy(32) || FTy->getParamType(0)->isIntegerTy(64)); }
/// Replace \p Thunk with a simple tail call to \p ToFunc. Also add parameters /// to the call to \p ToFunc, which are defined by the FuncIdx's value in /// \p Params. void SwiftMergeFunctions::writeThunk(Function *ToFunc, Function *Thunk, const ParamInfos &Params, unsigned FuncIdx) { // Delete the existing content of Thunk. Thunk->dropAllReferences(); BasicBlock *BB = BasicBlock::Create(Thunk->getContext(), "", Thunk); IRBuilder<> Builder(BB); SmallVector<Value *, 16> Args; unsigned ParamIdx = 0; FunctionType *ToFuncTy = ToFunc->getFunctionType(); // Add arguments which are passed through Thunk. for (Argument & AI : Thunk->args()) { Args.push_back(createCast(Builder, &AI, ToFuncTy->getParamType(ParamIdx))); ++ParamIdx; } // Add new arguments defined by Params. for (const ParamInfo &PI : Params) { assert(ParamIdx < ToFuncTy->getNumParams()); Args.push_back(createCast(Builder, PI.Values[FuncIdx], ToFuncTy->getParamType(ParamIdx))); ++ParamIdx; } CallInst *CI = Builder.CreateCall(ToFunc, Args); CI->setTailCall(); CI->setCallingConv(ToFunc->getCallingConv()); CI->setAttributes(ToFunc->getAttributes()); if (Thunk->getReturnType()->isVoidTy()) { Builder.CreateRetVoid(); } else { Builder.CreateRet(createCast(Builder, CI, Thunk->getReturnType())); } LLVM_DEBUG(dbgs() << " writeThunk: " << Thunk->getName() << '\n'); ++NumSwiftThunksWritten; }
/// \brief Returns the allocation data for the given value if it is a call to a /// known allocation function, and NULL otherwise. static const AllocFnsTy *getAllocationData(const Value *V, AllocType AllocTy, bool LookThroughBitCast = false) { Function *Callee = getCalledFunction(V, LookThroughBitCast); if (!Callee) return 0; unsigned i = 0; bool found = false; for ( ; i < array_lengthof(AllocationFnData); ++i) { if (Callee->getName() == AllocationFnData[i].Name) { found = true; break; } } if (!found) return 0; const AllocFnsTy *FnData = &AllocationFnData[i]; if ((FnData->AllocTy & AllocTy) == 0) return 0; // Check function prototype. // FIXME: Check the nobuiltin metadata?? (PR5130) int FstParam = FnData->FstParam; int SndParam = FnData->SndParam; FunctionType *FTy = Callee->getFunctionType(); if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == FnData->NumParams && (FstParam < 0 || (FTy->getParamType(FstParam)->isIntegerTy(32) || FTy->getParamType(FstParam)->isIntegerTy(64))) && (SndParam < 0 || FTy->getParamType(SndParam)->isIntegerTy(32) || FTy->getParamType(SndParam)->isIntegerTy(64))) return FnData; return 0; }
/// Returns the allocation data for the given value if it's either a call to a /// known allocation function, or a call to a function with the allocsize /// attribute. static Optional<AllocFnsTy> getAllocationDataForFunction(const Function *Callee, AllocType AllocTy, const TargetLibraryInfo *TLI) { // Make sure that the function is available. StringRef FnName = Callee->getName(); LibFunc TLIFn; if (!TLI || !TLI->getLibFunc(FnName, TLIFn) || !TLI->has(TLIFn)) return None; const auto *Iter = find_if( AllocationFnData, [TLIFn](const std::pair<LibFunc, AllocFnsTy> &P) { return P.first == TLIFn; }); if (Iter == std::end(AllocationFnData)) return None; const AllocFnsTy *FnData = &Iter->second; if ((FnData->AllocTy & AllocTy) != FnData->AllocTy) return None; // Check function prototype. int FstParam = FnData->FstParam; int SndParam = FnData->SndParam; FunctionType *FTy = Callee->getFunctionType(); if (FTy->getReturnType() == Type::getInt8PtrTy(FTy->getContext()) && FTy->getNumParams() == FnData->NumParams && (FstParam < 0 || (FTy->getParamType(FstParam)->isIntegerTy(32) || FTy->getParamType(FstParam)->isIntegerTy(64))) && (SndParam < 0 || FTy->getParamType(SndParam)->isIntegerTy(32) || FTy->getParamType(SndParam)->isIntegerTy(64))) return *FnData; return None; }
bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const DataLayout *TD, const TargetLibraryInfo *TLI) { // We really need DataLayout for later. if (!TD) return false; this->CI = CI; Function *Callee = CI->getCalledFunction(); StringRef Name = Callee->getName(); FunctionType *FT = Callee->getFunctionType(); LLVMContext &Context = CI->getParent()->getContext(); IRBuilder<> B(CI); if (Name == "__memcpy_chk") { // Check if this has the right signature. if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || FT->getParamType(2) != TD->getIntPtrType(Context) || FT->getParamType(3) != TD->getIntPtrType(Context)) return false; if (isFoldable(3, 2, false)) { B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), 1); replaceCall(CI->getArgOperand(0)); return true; } return false; } // Should be similar to memcpy. if (Name == "__mempcpy_chk") { return false; } if (Name == "__memmove_chk") { // Check if this has the right signature. if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || FT->getParamType(2) != TD->getIntPtrType(Context) || FT->getParamType(3) != TD->getIntPtrType(Context)) return false; if (isFoldable(3, 2, false)) { B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), 1); replaceCall(CI->getArgOperand(0)); return true; } return false; } if (Name == "__memset_chk") { // Check if this has the right signature. if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isIntegerTy() || FT->getParamType(2) != TD->getIntPtrType(Context) || FT->getParamType(3) != TD->getIntPtrType(Context)) return false; if (isFoldable(3, 2, false)) { Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1); replaceCall(CI->getArgOperand(0)); return true; } return false; } if (Name == "__strcpy_chk" || Name == "__stpcpy_chk") { // Check if this has the right signature. if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != Type::getInt8PtrTy(Context) || FT->getParamType(2) != TD->getIntPtrType(Context)) return 0; // If a) we don't have any length information, or b) we know this will // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our // st[rp]cpy_chk call which may fail at runtime if the size is too long. // TODO: It might be nice to get a maximum length out of the possible // string lengths for varying. if (isFoldable(2, 1, true)) { Value *Ret = EmitStrCpy(CI->getArgOperand(0), CI->getArgOperand(1), B, TD, TLI, Name.substr(2, 6)); if (!Ret) return false; replaceCall(Ret); return true; } return false; } if (Name == "__strncpy_chk" || Name == "__stpncpy_chk") { // Check if this has the right signature. if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != Type::getInt8PtrTy(Context) || !FT->getParamType(2)->isIntegerTy() || FT->getParamType(3) != TD->getIntPtrType(Context)) return false; if (isFoldable(3, 2, false)) { Value *Ret = EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), B, TD, TLI, Name.substr(2, 7)); if (!Ret) return false; replaceCall(Ret); return true; } return false; } if (Name == "__strcat_chk") { return false; } if (Name == "__strncat_chk") { return false; } return false; }
// RemoveDeadStuffFromFunction - Remove any arguments and return values from F // that are not in LiveValues. Transform the function and all of the callees of // the function to not have these arguments and return values. // bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Don't modify fully live functions if (LiveFunctions.count(F)) return false; // Start by computing a new prototype for the function, which is the same as // the old function, but has fewer arguments and a different return type. FunctionType *FTy = F->getFunctionType(); std::vector<Type*> Params; // Keep track of if we have a live 'returned' argument bool HasLiveReturnedArg = false; // Set up to build a new list of parameter attributes. SmallVector<AttributeSet, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); // Remember which arguments are still alive. SmallVector<bool, 10> ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct // a new set of parameter attributes to correspond. Skip the first parameter // attribute, since that belongs to the return value. unsigned i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++i) { RetOrArg Arg = CreateArg(F, i); if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); ArgAlive[i] = true; // Get the original parameter attributes (skipping the first one, that is // for the return value. if (PAL.hasAttributes(i + 1)) { AttrBuilder B(PAL, i + 1); if (B.contains(Attribute::Returned)) HasLiveReturnedArg = true; AttributesVec. push_back(AttributeSet::get(F->getContext(), Params.size(), B)); } } else { ++NumArgumentsEliminated; DEBUG(dbgs() << "DAE - Removing argument " << i << " (" << I->getName() << ") from " << F->getName() << "\n"); } } // Find out the new return value. Type *RetTy = FTy->getReturnType(); Type *NRetTy = nullptr; unsigned RetCount = NumRetVals(F); // -1 means unused, other numbers are the new index SmallVector<int, 5> NewRetIdxs(RetCount, -1); std::vector<Type*> RetTypes; // If there is a function with a live 'returned' argument but a dead return // value, then there are two possible actions: // 1) Eliminate the return value and take off the 'returned' attribute on the // argument. // 2) Retain the 'returned' attribute and treat the return value (but not the // entire function) as live so that it is not eliminated. // // It's not clear in the general case which option is more profitable because, // even in the absence of explicit uses of the return value, code generation // is free to use the 'returned' attribute to do things like eliding // save/restores of registers across calls. Whether or not this happens is // target and ABI-specific as well as depending on the amount of register // pressure, so there's no good way for an IR-level pass to figure this out. // // Fortunately, the only places where 'returned' is currently generated by // the FE are places where 'returned' is basically free and almost always a // performance win, so the second option can just be used always for now. // // This should be revisited if 'returned' is ever applied more liberally. if (RetTy->isVoidTy() || HasLiveReturnedArg) { NRetTy = RetTy; } else { // Look at each of the original return values individually. for (unsigned i = 0; i != RetCount; ++i) { RetOrArg Ret = CreateRet(F, i); if (LiveValues.erase(Ret)) { RetTypes.push_back(getRetComponentType(F, i)); NewRetIdxs[i] = RetTypes.size() - 1; } else { ++NumRetValsEliminated; DEBUG(dbgs() << "DAE - Removing return value " << i << " from " << F->getName() << "\n"); } } if (RetTypes.size() > 1) { // More than one return type? Reduce it down to size. if (StructType *STy = dyn_cast<StructType>(RetTy)) { // Make the new struct packed if we used to return a packed struct // already. NRetTy = StructType::get(STy->getContext(), RetTypes, STy->isPacked()); } else { assert(isa<ArrayType>(RetTy) && "unexpected multi-value return"); NRetTy = ArrayType::get(RetTypes[0], RetTypes.size()); } } else if (RetTypes.size() == 1) // One return type? Just a simple value then, but only if we didn't use to // return a struct with that simple value before. NRetTy = RetTypes.front(); else if (RetTypes.size() == 0) // No return types? Make it void, but only if we didn't use to return {}. NRetTy = Type::getVoidTy(F->getContext()); } assert(NRetTy && "No new return type found?"); // The existing function return attributes. AttributeSet RAttrs = PAL.getRetAttributes(); // Remove any incompatible attributes, but only if we removed all return // values. Otherwise, ensure that we don't have any conflicting attributes // here. Currently, this should not be possible, but special handling might be // required when new return value attributes are added. if (NRetTy->isVoidTy()) RAttrs = RAttrs.removeAttributes(NRetTy->getContext(), AttributeSet::ReturnIndex, AttributeFuncs::typeIncompatible(NRetTy)); else assert(!AttrBuilder(RAttrs, AttributeSet::ReturnIndex). overlaps(AttributeFuncs::typeIncompatible(NRetTy)) && "Return attributes no longer compatible?"); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(NRetTy->getContext(), RAttrs)); if (PAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(F->getContext(), PAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewPAL = AttributeSet::get(F->getContext(), AttributesVec); // Create the new function type based on the recomputed parameters. FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); // No change? if (NFTy == FTy) return false; // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); NF->setAttributes(NewPAL); // Insert the new function before the old function, so we won't be processing // it again. F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); // 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 (!F->use_empty()) { CallSite CS(F->user_back()); Instruction *Call = CS.getInstruction(); AttributesVec.clear(); const AttributeSet &CallPAL = CS.getAttributes(); // The call return attributes. AttributeSet RAttrs = CallPAL.getRetAttributes(); // Adjust in case the function was changed to return void. RAttrs = RAttrs.removeAttributes(NRetTy->getContext(), AttributeSet::ReturnIndex, AttributeFuncs::typeIncompatible(NF->getReturnType())); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(NF->getContext(), RAttrs)); // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs. CallSite::arg_iterator I = CS.arg_begin(); unsigned i = 0; // Loop over those operands, corresponding to the normal arguments to the // original function, and add those that are still alive. for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) if (ArgAlive[i]) { Args.push_back(*I); // Get original parameter attributes, but skip return attributes. if (CallPAL.hasAttributes(i + 1)) { AttrBuilder B(CallPAL, i + 1); // If the return type has changed, then get rid of 'returned' on the // call site. The alternative is to make all 'returned' attributes on // call sites keep the return value alive just like 'returned' // attributes on function declaration but it's less clearly a win // and this is not an expected case anyway if (NRetTy != RetTy && B.contains(Attribute::Returned)) B.removeAttribute(Attribute::Returned); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } // Push any varargs arguments on the list. Don't forget their attributes. for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { Args.push_back(*I); if (CallPAL.hasAttributes(i + 1)) { AttrBuilder B(CallPAL, i + 1); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(Call->getContext(), CallPAL.getFnAttributes())); // Reconstruct the AttributesList based on the vector we constructed. AttributeSet NewCallPAL = AttributeSet::get(F->getContext(), AttributesVec); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call->getParent()); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(NewCallPAL); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(NewCallPAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); if (!Call->use_empty()) { if (New->getType() == Call->getType()) { // Return type not changed? Just replace users then. Call->replaceAllUsesWith(New); New->takeName(Call); } else if (New->getType()->isVoidTy()) { // Our return value has uses, but they will get removed later on. // Replace by null for now. if (!Call->getType()->isX86_MMXTy()) Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); } else { assert((RetTy->isStructTy() || RetTy->isArrayTy()) && "Return type changed, but not into a void. The old return type" " must have been a struct or an array!"); Instruction *InsertPt = Call; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { BasicBlock *NewEdge = SplitEdge(New->getParent(), II->getNormalDest()); InsertPt = &*NewEdge->getFirstInsertionPt(); } // We used to return a struct or array. Instead of doing smart stuff // with all the uses, we will just rebuild it using extract/insertvalue // chaining and let instcombine clean that up. // // Start out building up our return value from undef Value *RetVal = UndefValue::get(RetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { Value *V; if (RetTypes.size() > 1) // We are still returning a struct, so extract the value from our // return value V = ExtractValueInst::Create(New, NewRetIdxs[i], "newret", InsertPt); else // We are now returning a single element, so just insert that V = New; // Insert the value at the old position RetVal = InsertValueInst::Create(RetVal, V, i, "oldret", InsertPt); } // Now, replace all uses of the old call instruction with the return // struct we built Call->replaceAllUsesWith(RetVal); 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(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++i) if (ArgAlive[i]) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); ++I2; } else { // If this argument is dead, replace any uses of it with null constants // (these are guaranteed to become unused later on). if (!I->getType()->isX86_MMXTy()) I->replaceAllUsesWith(Constant::getNullValue(I->getType())); } // If we change the return value of the function we must rewrite any return // instructions. Check this now. if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) { Value *RetVal; if (NFTy->getReturnType()->isVoidTy()) { RetVal = nullptr; } else { assert(RetTy->isStructTy() || RetTy->isArrayTy()); // The original return value was a struct or array, insert // extractvalue/insertvalue chains to extract only the values we need // to return and insert them into our new result. // This does generate messy code, but we'll let it to instcombine to // clean that up. Value *OldRet = RI->getOperand(0); // Start out building up our return value from undef RetVal = UndefValue::get(NRetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "oldret", RI); if (RetTypes.size() > 1) { // We're still returning a struct, so reinsert the value into // our new return value at the new index RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "newret", RI); } else { // We are now only returning a simple value, so just return the // extracted value. RetVal = EV; } } } // Replace the return instruction with one returning the new return // value (possibly 0 if we became void). ReturnInst::Create(F->getContext(), RetVal, RI); BB->getInstList().erase(RI); } // Patch the pointer to LLVM function in debug info descriptor. NF->setSubprogram(F->getSubprogram()); // Now that the old function is dead, delete it. F->eraseFromParent(); return true; }
GenericValue MCJIT::runFunction(Function *F, const std::vector<GenericValue> &ArgValues) { assert(F && "Function *F was null at entry to run()"); void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); FunctionType *FTy = F->getFunctionType(); Type *RetTy = FTy->getReturnType(); assert((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && "Wrong number of arguments passed into function!"); assert(FTy->getNumParams() == ArgValues.size() && "This doesn't support passing arguments through varargs (yet)!"); // Handle some common cases first. These cases correspond to common `main' // prototypes. if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { switch (ArgValues.size()) { case 3: if (FTy->getParamType(0)->isIntegerTy(32) && FTy->getParamType(1)->isPointerTy() && FTy->getParamType(2)->isPointerTy()) { int (*PF)(int, char **, const char **) = (int(*)(int, char **, const char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]), (const char **)GVTOP(ArgValues[2]))); return rv; } break; case 2: if (FTy->getParamType(0)->isIntegerTy(32) && FTy->getParamType(1)->isPointerTy()) { int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]))); return rv; } break; case 1: if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) { GenericValue rv; int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); return rv; } break; } } // Handle cases where no arguments are passed first. if (ArgValues.empty()) { GenericValue rv; switch (RetTy->getTypeID()) { default: llvm_unreachable("Unknown return type for function call!"); case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); if (BitWidth == 1) rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); else if (BitWidth <= 8) rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); else if (BitWidth <= 16) rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); else if (BitWidth <= 32) rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); else if (BitWidth <= 64) rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); else llvm_unreachable("Integer types > 64 bits not supported"); return rv; } case Type::VoidTyID: rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); return rv; case Type::FloatTyID: rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); return rv; case Type::DoubleTyID: rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); return rv; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: llvm_unreachable("long double not supported yet"); case Type::PointerTyID: return PTOGV(((void*(*)())(intptr_t)FPtr)()); } } llvm_unreachable("Full-featured argument passing not supported yet!"); }
/// cmpType - compares two types, /// defines total ordering among the types set. /// See method declaration comments for more details. int FunctionComparator::cmpType(Type *TyL, Type *TyR) const { PointerType *PTyL = dyn_cast<PointerType>(TyL); PointerType *PTyR = dyn_cast<PointerType>(TyR); if (DL) { if (PTyL && PTyL->getAddressSpace() == 0) TyL = DL->getIntPtrType(TyL); if (PTyR && PTyR->getAddressSpace() == 0) TyR = DL->getIntPtrType(TyR); } if (TyL == TyR) return 0; if (int Res = cmpNumbers(TyL->getTypeID(), TyR->getTypeID())) return Res; switch (TyL->getTypeID()) { default: llvm_unreachable("Unknown type!"); // Fall through in Release mode. case Type::IntegerTyID: case Type::VectorTyID: // TyL == TyR would have returned true earlier. return cmpNumbers((uint64_t)TyL, (uint64_t)TyR); case Type::VoidTyID: case Type::FloatTyID: case Type::DoubleTyID: case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: case Type::LabelTyID: case Type::MetadataTyID: return 0; case Type::PointerTyID: { assert(PTyL && PTyR && "Both types must be pointers here."); return cmpNumbers(PTyL->getAddressSpace(), PTyR->getAddressSpace()); } case Type::StructTyID: { StructType *STyL = cast<StructType>(TyL); StructType *STyR = cast<StructType>(TyR); if (STyL->getNumElements() != STyR->getNumElements()) return cmpNumbers(STyL->getNumElements(), STyR->getNumElements()); if (STyL->isPacked() != STyR->isPacked()) return cmpNumbers(STyL->isPacked(), STyR->isPacked()); for (unsigned i = 0, e = STyL->getNumElements(); i != e; ++i) { if (int Res = cmpType(STyL->getElementType(i), STyR->getElementType(i))) return Res; } return 0; } case Type::FunctionTyID: { FunctionType *FTyL = cast<FunctionType>(TyL); FunctionType *FTyR = cast<FunctionType>(TyR); if (FTyL->getNumParams() != FTyR->getNumParams()) return cmpNumbers(FTyL->getNumParams(), FTyR->getNumParams()); if (FTyL->isVarArg() != FTyR->isVarArg()) return cmpNumbers(FTyL->isVarArg(), FTyR->isVarArg()); if (int Res = cmpType(FTyL->getReturnType(), FTyR->getReturnType())) return Res; for (unsigned i = 0, e = FTyL->getNumParams(); i != e; ++i) { if (int Res = cmpType(FTyL->getParamType(i), FTyR->getParamType(i))) return Res; } return 0; } case Type::ArrayTyID: { ArrayType *ATyL = cast<ArrayType>(TyL); ArrayType *ATyR = cast<ArrayType>(TyR); if (ATyL->getNumElements() != ATyR->getNumElements()) return cmpNumbers(ATyL->getNumElements(), ATyR->getNumElements()); return cmpType(ATyL->getElementType(), ATyR->getElementType()); } } }
// // Method: visitCallSite() // // Description: // This method transforms a call site. A call site may either be a call // instruction or an invoke instruction. // // Inputs: // CS - The call site representing the instruction that should be transformed. // void FuncTransform::visitCallSite(CallSite& CS) { const Function *CF = CS.getCalledFunction(); Instruction *TheCall = CS.getInstruction(); bool thread_creation_point = false; // // Get the value that is called at this call site. Strip away any pointer // casts that do not change the representation of the data (i.e., are // lossless casts). // Value * CalledValue = CS.getCalledValue()->stripPointerCasts(); // // The CallSite::getCalledFunction() method is not guaranteed to strip off // pointer casts. If no called function was found, manually strip pointer // casts off of the called value and see if we get a function. If so, this // is a direct call, and we want to update CF accordingly. // if (!CF) CF = dyn_cast<Function>(CalledValue); // // Do not change any inline assembly code. // if (isa<InlineAsm>(TheCall->getOperand(0))) { errs() << "INLINE ASM: ignoring. Hoping that's safe.\n"; return; } // // Ignore calls to NULL pointers or undefined values. // if ((isa<ConstantPointerNull>(CalledValue)) || (isa<UndefValue>(CalledValue))) { errs() << "WARNING: Ignoring call using NULL/Undef function pointer.\n"; return; } // If this function is one of the memory manipulating functions built into // libc, emulate it with pool calls as appropriate. if (CF && CF->isDeclaration()) { std::string Name = CF->getName(); if (Name == "free" || Name == "cfree") { visitFreeCall(CS); return; } else if (Name == "malloc") { visitMallocCall(CS); return; } else if (Name == "calloc") { visitCallocCall(CS); return; } else if (Name == "realloc") { visitReallocCall(CS); return; } else if (Name == "memalign" || Name == "posix_memalign") { visitMemAlignCall(CS); return; } else if (Name == "strdup") { visitStrdupCall(CS); return; } else if (Name == "valloc") { errs() << "VALLOC USED BUT NOT HANDLED!\n"; abort(); } else if (unsigned PoolArgc = PAInfo.getNumInitialPoolArguments(Name)) { visitRuntimeCheck(CS, PoolArgc); return; } else if (Name == "pthread_create") { thread_creation_point = true; // // Get DSNode representing the DSNode of the function pointer Value of // the pthread_create call // DSNode* thread_callee_node = G->getNodeForValue(CS.getArgument(2)).getNode(); if (!thread_callee_node) { assert(0 && "apparently you need this code"); FuncInfo *CFI = PAInfo.getFuncInfo(*CF); thread_callee_node = G->getNodeForValue(CFI->MapValueToOriginal(CS.getArgument(2))).getNode(); } // Fill in CF with the name of one of the functions in thread_callee_node CF = const_cast<Function*>(dyn_cast<Function>(*thread_callee_node->globals_begin())); } } // // We need to figure out which local pool descriptors correspond to the pool // descriptor arguments passed into the function call. Calculate a mapping // from callee DSNodes to caller DSNodes. We construct a partial isomophism // between the graphs to figure out which pool descriptors need to be passed // in. The roots of this mapping is found from arguments and return values. // DataStructures& Graphs = PAInfo.getGraphs(); DSGraph::NodeMapTy NodeMapping; Instruction *NewCall; Value *NewCallee; std::vector<const DSNode*> ArgNodes; DSGraph *CalleeGraph; // The callee graph // For indirect callees, find any callee since all DS graphs have been // merged. if (CF) { // Direct calls are nice and simple. DEBUG(errs() << " Handling direct call: " << *TheCall << "\n"); // // Do not try to add pool handles to the function if it: // a) Already calls a cloned function; or // b) Calls a function which was never cloned. // // For such a call, just replace any arguments that take original functions // with their cloned function poiner values. // FuncInfo *CFI = PAInfo.getFuncInfo(*CF); if (CFI == 0 || CFI->Clone == 0) { // Nothing to transform... visitInstruction(*TheCall); return; } // // Oh, dear. We must add pool descriptors to this direct call. // NewCallee = CFI->Clone; ArgNodes = CFI->ArgNodes; assert ((Graphs.hasDSGraph (*CF)) && "Function has no ECGraph!\n"); CalleeGraph = Graphs.getDSGraph(*CF); } else { DEBUG(errs() << " Handling indirect call: " << *TheCall << "\n"); DSGraph *G = Graphs.getGlobalsGraph(); DSGraph::ScalarMapTy& SM = G->getScalarMap(); // Here we fill in CF with one of the possible called functions. Because we // merged together all of the arguments to all of the functions in the // equivalence set, it doesn't really matter which one we pick. // (If the function was cloned, we have to map the cloned call instruction // in CS back to the original call instruction.) Instruction *OrigInst = cast<Instruction>(getOldValueIfAvailable(CS.getInstruction())); // // Attempt to get one of the function targets of this indirect call site by // looking at the call graph constructed by the points-to analysis. Be // sure to use the original call site from the original function; the // points-to analysis has no information on the clones we've created. // // Also, look for the target that has the greatest number of arguments that // have associated DSNodes. This ensures that we pass the maximum number // of pools possible and prevents us from eliding a pool because we're // examining a target that doesn't need it. // const DSCallGraph & callGraph = Graphs.getCallGraph(); DSCallGraph::callee_iterator I = callGraph.callee_begin(OrigInst); for (; I != callGraph.callee_end(OrigInst); ++I) { for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(*I), sccee = callGraph.scc_end(*I); sccii != sccee; ++sccii){ if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end()) continue; // // Get the information for this function. Since this is coming from // DSA, it should be an original function. // // This call site calls a function, that is not defined in this module if (!(Graphs.hasDSGraph(**sccii))) return; // For all other cases Func Info must exist. PAInfo.getFuncInfo(**sccii); // // If this target takes more DSNodes than the last one we found, then // make *this* target our canonical target. // CF = *sccii; break; } } if(!CF){ const Function *F1 = OrigInst->getParent()->getParent(); F1 = callGraph.sccLeader(&*F1); for(DSCallGraph::scc_iterator sccii = callGraph.scc_begin(F1), sccee = callGraph.scc_end(F1); sccii != sccee; ++sccii){ if(SM.find(SM.getLeaderForGlobal(*sccii)) == SM.end()) continue; // // Get the information for this function. Since this is coming from DSA, // it should be an original function. // // This call site calls a function, that is not defined in this module if (!(Graphs.hasDSGraph(**sccii))) return; // For all other cases Func Info must exist. PAInfo.getFuncInfo(**sccii); // // If this target takes more DSNodes than the last one we found, then // make *this* target our canonical target. // CF = *sccii; } } // Assuming the call graph is always correct. And if the call graph reports, // no callees, we can assume that it is right. // // If we didn't find the callee in the constructed call graph, try // checking in the DSNode itself. // This isn't ideal as it means that this call site didn't have inlining // happen. // // // If we still haven't been able to find a target function of the call site // to transform, do nothing. // // One may be tempted to think that we should always have at least one // target, but this is not true. There are perfectly acceptable (but // strange) programs for which no function targets exist. Function // pointers loaded from undef values, for example, will have no targets. // if (!CF) return; // // It's possible that this program has indirect call targets that are // not defined in this module. Do not transformation for such functions. // if (!(Graphs.hasDSGraph(*CF))) return; // // Get the common graph for the set of functions this call may invoke. // assert ((Graphs.hasDSGraph(*CF)) && "Function has no DSGraph!\n"); CalleeGraph = Graphs.getDSGraph(*CF); #ifndef NDEBUG // Verify that all potential callees at call site have the same DS graph. DSCallGraph::callee_iterator E = Graphs.getCallGraph().callee_end(OrigInst); for (; I != E; ++I) { const Function * F = *I; assert (F); if (!(F)->isDeclaration()) assert(CalleeGraph == Graphs.getDSGraph(**I) && "Callees at call site do not have a common graph!"); } #endif // Find the DS nodes for the arguments that need to be added, if any. FuncInfo *CFI = PAInfo.getFuncInfo(*CF); assert(CFI && "No function info for callee at indirect call?"); ArgNodes = CFI->ArgNodes; if (ArgNodes.empty()) return; // No arguments to add? Transformation is a noop! // Cast the function pointer to an appropriate type! std::vector<Type*> ArgTys(ArgNodes.size(), PoolAllocate::PoolDescPtrTy); for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) ArgTys.push_back((*I)->getType()); FunctionType *FTy = FunctionType::get(TheCall->getType(), ArgTys, false); PointerType *PFTy = PointerType::getUnqual(FTy); // If there are any pool arguments cast the func ptr to the right type. NewCallee = CastInst::CreatePointerCast(CS.getCalledValue(), PFTy, "tmp", TheCall); } // // FIXME: Why do we disable strict checking when calling the // DSGraph::computeNodeMapping() method? // Function::const_arg_iterator FAI = CF->arg_begin(), E = CF->arg_end(); CallSite::arg_iterator AI = CS.arg_begin() + (thread_creation_point ? 3 : 0); CallSite::arg_iterator AE = CS.arg_end(); for ( ; FAI != E && AI != AE; ++FAI, ++AI) if (!isa<Constant>(*AI)) { DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(FAI), getDSNodeHFor(*AI), NodeMapping, false); } //assert(AI == AE && "Varargs calls not handled yet!"); // Map the return value as well... if (isa<PointerType>(TheCall->getType())) DSGraph::computeNodeMapping(CalleeGraph->getReturnNodeFor(*CF), getDSNodeHFor(TheCall), NodeMapping, false); // This code seems redundant (and crashes occasionally) // There is no reason to map globals here, since they are not passed as // arguments // // Map the nodes that are pointed to by globals. // DSScalarMap &CalleeSM = CalleeGraph->getScalarMap(); // for (DSScalarMap::global_iterator GI = G.getScalarMap().global_begin(), // E = G.getScalarMap().global_end(); GI != E; ++GI) // if (CalleeSM.count(*GI)) // DSGraph::computeNodeMapping(CalleeGraph->getNodeForValue(*GI), // getDSNodeHFor(*GI), // NodeMapping, false); // // Okay, now that we have established our mapping, we can figure out which // pool descriptors to pass in... // // Note: // There used to be code here that would create a new pool before the // function call and destroy it after the function call. This could would // get triggered if bounds checking was disbled or the DSNode for the // argument was an array value. // // I believe that code was incorrect; an argument may have a NULL pool handle // (i.e., no pool handle) because the pool allocation heuristic used simply // decided not to assign that value a pool. The argument may alias data // that should not be freed after the function call is complete, so calling // pooldestroy() after the call would free data, causing dangling pointer // dereference errors. // std::vector<Value*> Args; for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) { Value *ArgVal = Constant::getNullValue(PoolAllocate::PoolDescPtrTy); if (NodeMapping.count(ArgNodes[i])) { if (DSNode *LocalNode = NodeMapping[ArgNodes[i]].getNode()) if (FI.PoolDescriptors.count(LocalNode)) ArgVal = FI.PoolDescriptors.find(LocalNode)->second; } Args.push_back(ArgVal); } // Add the rest of the arguments unless we're a thread creation point, in which case we only need the pools if(!thread_creation_point) Args.insert(Args.end(), CS.arg_begin(), CS.arg_end()); // // There are circumstances where a function is casted to another type and // then called (que horible). We need to perform a similar cast if the // type doesn't match the number of arguments. // if (Function * NewFunction = dyn_cast<Function>(NewCallee)) { FunctionType * NewCalleeType = NewFunction->getFunctionType(); if (NewCalleeType->getNumParams() != Args.size()) { std::vector<Type *> Types; Type * FuncTy = FunctionType::get (NewCalleeType->getReturnType(), Types, true); FuncTy = PointerType::getUnqual (FuncTy); NewCallee = new BitCastInst (NewCallee, FuncTy, "", TheCall); } } std::string Name = TheCall->getName(); TheCall->setName(""); if(thread_creation_point) { Module *M = CS.getInstruction()->getParent()->getParent()->getParent(); Value* pthread_replacement = M->getFunction("poolalloc_pthread_create"); std::vector<Value*> thread_args; //Push back original thread arguments through the callee thread_args.push_back(CS.getArgument(0)); thread_args.push_back(CS.getArgument(1)); thread_args.push_back(CS.getArgument(2)); //Push back the integer argument saying how many uses there are thread_args.push_back(Constant::getIntegerValue(llvm::Type::getInt32Ty(M->getContext()),APInt(32,Args.size()))); thread_args.insert(thread_args.end(),Args.begin(),Args.end()); thread_args.push_back(CS.getArgument(3)); //Make the thread creation call NewCall = CallInst::Create(pthread_replacement, thread_args, Name,TheCall); } else if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) { NewCall = InvokeInst::Create (NewCallee, II->getNormalDest(), II->getUnwindDest(), Args, Name, TheCall); } else { NewCall = CallInst::Create (NewCallee, Args, Name, TheCall); } // Add all of the uses of the pool descriptor for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i) AddPoolUse(*NewCall, Args[i], PoolUses); TheCall->replaceAllUsesWith(NewCall); DEBUG(errs() << " Result Call: " << *NewCall << "\n"); if (!TheCall->getType()->isVoidTy()) { // If we are modifying the original function, update the DSGraph... DSGraph::ScalarMapTy &SM = G->getScalarMap(); DSGraph::ScalarMapTy::iterator CII = SM.find(TheCall); if (CII != SM.end()) { SM[NewCall] = CII->second; SM.erase(CII); // Destroy the CallInst } else if (!FI.NewToOldValueMap.empty()) { // Otherwise, if this is a clone, update the NewToOldValueMap with the new // CI return value. UpdateNewToOldValueMap(TheCall, NewCall); } } else if (!FI.NewToOldValueMap.empty()) { UpdateNewToOldValueMap(TheCall, NewCall); } // // Copy over the calling convention and attributes of the original call // instruction to the new call instruction. // CallSite(NewCall).setCallingConv(CallSite(TheCall).getCallingConv()); TheCall->eraseFromParent(); visitInstruction(*NewCall); }
void Lint::visitCallSite(CallSite CS) { Instruction &I = *CS.getInstruction(); Value *Callee = CS.getCalledValue(); visitMemoryReference(I, Callee, MemoryLocation::UnknownSize, 0, nullptr, MemRef::Callee); if (Function *F = dyn_cast<Function>(findValue(Callee, /*OffsetOk=*/false))) { Assert(CS.getCallingConv() == F->getCallingConv(), "Undefined behavior: Caller and callee calling convention differ", &I); FunctionType *FT = F->getFunctionType(); unsigned NumActualArgs = CS.arg_size(); Assert(FT->isVarArg() ? FT->getNumParams() <= NumActualArgs : FT->getNumParams() == NumActualArgs, "Undefined behavior: Call argument count mismatches callee " "argument count", &I); Assert(FT->getReturnType() == I.getType(), "Undefined behavior: Call return type mismatches " "callee return type", &I); // Check argument types (in case the callee was casted) and attributes. // TODO: Verify that caller and callee attributes are compatible. Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end(); CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); for (; AI != AE; ++AI) { Value *Actual = *AI; if (PI != PE) { Argument *Formal = &*PI++; Assert(Formal->getType() == Actual->getType(), "Undefined behavior: Call argument type mismatches " "callee parameter type", &I); // Check that noalias arguments don't alias other arguments. This is // not fully precise because we don't know the sizes of the dereferenced // memory regions. if (Formal->hasNoAliasAttr() && Actual->getType()->isPointerTy()) for (CallSite::arg_iterator BI = CS.arg_begin(); BI != AE; ++BI) if (AI != BI && (*BI)->getType()->isPointerTy()) { AliasResult Result = AA->alias(*AI, *BI); Assert(Result != MustAlias && Result != PartialAlias, "Unusual: noalias argument aliases another argument", &I); } // Check that an sret argument points to valid memory. if (Formal->hasStructRetAttr() && Actual->getType()->isPointerTy()) { Type *Ty = cast<PointerType>(Formal->getType())->getElementType(); visitMemoryReference(I, Actual, DL->getTypeStoreSize(Ty), DL->getABITypeAlignment(Ty), Ty, MemRef::Read | MemRef::Write); } } } } if (CS.isCall() && cast<CallInst>(CS.getInstruction())->isTailCall()) for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); AI != AE; ++AI) { Value *Obj = findValue(*AI, /*OffsetOk=*/true); Assert(!isa<AllocaInst>(Obj), "Undefined behavior: Call with \"tail\" keyword references " "alloca", &I); } if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I)) switch (II->getIntrinsicID()) { default: break; // TODO: Check more intrinsics case Intrinsic::memcpy: { MemCpyInst *MCI = cast<MemCpyInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MCI->getDest(), MemoryLocation::UnknownSize, MCI->getAlignment(), nullptr, MemRef::Write); visitMemoryReference(I, MCI->getSource(), MemoryLocation::UnknownSize, MCI->getAlignment(), nullptr, MemRef::Read); // Check that the memcpy arguments don't overlap. The AliasAnalysis API // isn't expressive enough for what we really want to do. Known partial // overlap is not distinguished from the case where nothing is known. uint64_t Size = 0; if (const ConstantInt *Len = dyn_cast<ConstantInt>(findValue(MCI->getLength(), /*OffsetOk=*/false))) if (Len->getValue().isIntN(32)) Size = Len->getValue().getZExtValue(); Assert(AA->alias(MCI->getSource(), Size, MCI->getDest(), Size) != MustAlias, "Undefined behavior: memcpy source and destination overlap", &I); break; } case Intrinsic::memmove: { MemMoveInst *MMI = cast<MemMoveInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MMI->getDest(), MemoryLocation::UnknownSize, MMI->getAlignment(), nullptr, MemRef::Write); visitMemoryReference(I, MMI->getSource(), MemoryLocation::UnknownSize, MMI->getAlignment(), nullptr, MemRef::Read); break; } case Intrinsic::memset: { MemSetInst *MSI = cast<MemSetInst>(&I); // TODO: If the size is known, use it. visitMemoryReference(I, MSI->getDest(), MemoryLocation::UnknownSize, MSI->getAlignment(), nullptr, MemRef::Write); break; } case Intrinsic::vastart: Assert(I.getParent()->getParent()->isVarArg(), "Undefined behavior: va_start called in a non-varargs function", &I); visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; case Intrinsic::vacopy: visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Write); visitMemoryReference(I, CS.getArgument(1), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read); break; case Intrinsic::vaend: visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; case Intrinsic::stackrestore: // Stackrestore doesn't read or write memory, but it sets the // stack pointer, which the compiler may read from or write to // at any time, so check it for both readability and writeability. visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; } }