BuildLibCalls.cpp revision 249423
1204792Srdivacky//===- BuildLibCalls.cpp - Utility builder for libcalls -------------------===// 2204792Srdivacky// 3204792Srdivacky// The LLVM Compiler Infrastructure 4204792Srdivacky// 5204792Srdivacky// This file is distributed under the University of Illinois Open Source 6204792Srdivacky// License. See LICENSE.TXT for details. 7204792Srdivacky// 8204792Srdivacky//===----------------------------------------------------------------------===// 9204792Srdivacky// 10204792Srdivacky// This file implements some functions that will create standard C libcalls. 11204792Srdivacky// 12204792Srdivacky//===----------------------------------------------------------------------===// 13204792Srdivacky 14204792Srdivacky#include "llvm/Transforms/Utils/BuildLibCalls.h" 15239462Sdim#include "llvm/ADT/SmallString.h" 16249423Sdim#include "llvm/IR/Constants.h" 17249423Sdim#include "llvm/IR/DataLayout.h" 18249423Sdim#include "llvm/IR/Function.h" 19249423Sdim#include "llvm/IR/IRBuilder.h" 20249423Sdim#include "llvm/IR/Intrinsics.h" 21249423Sdim#include "llvm/IR/LLVMContext.h" 22249423Sdim#include "llvm/IR/Module.h" 23249423Sdim#include "llvm/IR/Type.h" 24234353Sdim#include "llvm/Target/TargetLibraryInfo.h" 25204792Srdivacky 26204792Srdivackyusing namespace llvm; 27204792Srdivacky 28204792Srdivacky/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. 29204792SrdivackyValue *llvm::CastToCStr(Value *V, IRBuilder<> &B) { 30204792Srdivacky return B.CreateBitCast(V, B.getInt8PtrTy(), "cstr"); 31204792Srdivacky} 32204792Srdivacky 33204792Srdivacky/// EmitStrLen - Emit a call to the strlen function to the builder, for the 34204792Srdivacky/// specified pointer. This always returns an integer value of size intptr_t. 35243830SdimValue *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout *TD, 36239462Sdim const TargetLibraryInfo *TLI) { 37239462Sdim if (!TLI->has(LibFunc::strlen)) 38239462Sdim return 0; 39239462Sdim 40204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 41249423Sdim AttributeSet AS[2]; 42249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 43249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 44249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 45249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 46204792Srdivacky 47204792Srdivacky LLVMContext &Context = B.GetInsertBlock()->getContext(); 48243830Sdim Constant *StrLen = M->getOrInsertFunction("strlen", 49249423Sdim AttributeSet::get(M->getContext(), 50249423Sdim AS), 51204792Srdivacky TD->getIntPtrType(Context), 52204792Srdivacky B.getInt8PtrTy(), 53204792Srdivacky NULL); 54204792Srdivacky CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen"); 55204792Srdivacky if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts())) 56204792Srdivacky CI->setCallingConv(F->getCallingConv()); 57204792Srdivacky 58204792Srdivacky return CI; 59204792Srdivacky} 60204792Srdivacky 61239462Sdim/// EmitStrNLen - Emit a call to the strnlen function to the builder, for the 62239462Sdim/// specified pointer. Ptr is required to be some pointer type, MaxLen must 63239462Sdim/// be of size_t type, and the return value has 'intptr_t' type. 64239462SdimValue *llvm::EmitStrNLen(Value *Ptr, Value *MaxLen, IRBuilder<> &B, 65243830Sdim const DataLayout *TD, const TargetLibraryInfo *TLI) { 66239462Sdim if (!TLI->has(LibFunc::strnlen)) 67239462Sdim return 0; 68239462Sdim 69239462Sdim Module *M = B.GetInsertBlock()->getParent()->getParent(); 70249423Sdim AttributeSet AS[2]; 71249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 72249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 73249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 74249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 75239462Sdim 76239462Sdim LLVMContext &Context = B.GetInsertBlock()->getContext(); 77243830Sdim Constant *StrNLen = M->getOrInsertFunction("strnlen", 78249423Sdim AttributeSet::get(M->getContext(), 79249423Sdim AS), 80239462Sdim TD->getIntPtrType(Context), 81239462Sdim B.getInt8PtrTy(), 82239462Sdim TD->getIntPtrType(Context), 83239462Sdim NULL); 84239462Sdim CallInst *CI = B.CreateCall2(StrNLen, CastToCStr(Ptr, B), MaxLen, "strnlen"); 85239462Sdim if (const Function *F = dyn_cast<Function>(StrNLen->stripPointerCasts())) 86239462Sdim CI->setCallingConv(F->getCallingConv()); 87239462Sdim 88239462Sdim return CI; 89239462Sdim} 90239462Sdim 91204792Srdivacky/// EmitStrChr - Emit a call to the strchr function to the builder, for the 92204792Srdivacky/// specified pointer and character. Ptr is required to be some pointer type, 93204792Srdivacky/// and the return value has 'i8*' type. 94204792SrdivackyValue *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, 95243830Sdim const DataLayout *TD, const TargetLibraryInfo *TLI) { 96239462Sdim if (!TLI->has(LibFunc::strchr)) 97239462Sdim return 0; 98239462Sdim 99204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 100249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 101249423Sdim AttributeSet AS = 102249423Sdim AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 103249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 104204792Srdivacky 105226633Sdim Type *I8Ptr = B.getInt8PtrTy(); 106226633Sdim Type *I32Ty = B.getInt32Ty(); 107243830Sdim Constant *StrChr = M->getOrInsertFunction("strchr", 108249423Sdim AttributeSet::get(M->getContext(), 109249423Sdim AS), 110204792Srdivacky I8Ptr, I8Ptr, I32Ty, NULL); 111204792Srdivacky CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), 112204792Srdivacky ConstantInt::get(I32Ty, C), "strchr"); 113204792Srdivacky if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts())) 114204792Srdivacky CI->setCallingConv(F->getCallingConv()); 115204792Srdivacky return CI; 116204792Srdivacky} 117204792Srdivacky 118210299Sed/// EmitStrNCmp - Emit a call to the strncmp function to the builder. 119210299SedValue *llvm::EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, 120243830Sdim IRBuilder<> &B, const DataLayout *TD, 121239462Sdim const TargetLibraryInfo *TLI) { 122239462Sdim if (!TLI->has(LibFunc::strncmp)) 123239462Sdim return 0; 124239462Sdim 125210299Sed Module *M = B.GetInsertBlock()->getParent()->getParent(); 126249423Sdim AttributeSet AS[3]; 127249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 128249423Sdim AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 129249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 130249423Sdim AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 131249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 132210299Sed 133210299Sed LLVMContext &Context = B.GetInsertBlock()->getContext(); 134243830Sdim Value *StrNCmp = M->getOrInsertFunction("strncmp", 135249423Sdim AttributeSet::get(M->getContext(), 136249423Sdim AS), 137210299Sed B.getInt32Ty(), 138210299Sed B.getInt8PtrTy(), 139210299Sed B.getInt8PtrTy(), 140210299Sed TD->getIntPtrType(Context), NULL); 141210299Sed CallInst *CI = B.CreateCall3(StrNCmp, CastToCStr(Ptr1, B), 142210299Sed CastToCStr(Ptr2, B), Len, "strncmp"); 143210299Sed 144210299Sed if (const Function *F = dyn_cast<Function>(StrNCmp->stripPointerCasts())) 145210299Sed CI->setCallingConv(F->getCallingConv()); 146210299Sed 147210299Sed return CI; 148210299Sed} 149210299Sed 150204792Srdivacky/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the 151204792Srdivacky/// specified pointer arguments. 152204792SrdivackyValue *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, 153243830Sdim const DataLayout *TD, const TargetLibraryInfo *TLI, 154239462Sdim StringRef Name) { 155239462Sdim if (!TLI->has(LibFunc::strcpy)) 156239462Sdim return 0; 157239462Sdim 158204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 159249423Sdim AttributeSet AS[2]; 160249423Sdim AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 161249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 162249423Sdim Attribute::NoUnwind); 163226633Sdim Type *I8Ptr = B.getInt8PtrTy(); 164243830Sdim Value *StrCpy = M->getOrInsertFunction(Name, 165249423Sdim AttributeSet::get(M->getContext(), AS), 166204792Srdivacky I8Ptr, I8Ptr, I8Ptr, NULL); 167204792Srdivacky CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B), 168205218Srdivacky Name); 169204792Srdivacky if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts())) 170204792Srdivacky CI->setCallingConv(F->getCallingConv()); 171204792Srdivacky return CI; 172204792Srdivacky} 173204792Srdivacky 174205218Srdivacky/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the 175205218Srdivacky/// specified pointer arguments. 176205218SrdivackyValue *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len, 177243830Sdim IRBuilder<> &B, const DataLayout *TD, 178239462Sdim const TargetLibraryInfo *TLI, StringRef Name) { 179239462Sdim if (!TLI->has(LibFunc::strncpy)) 180239462Sdim return 0; 181239462Sdim 182205218Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 183249423Sdim AttributeSet AS[2]; 184249423Sdim AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 185249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 186249423Sdim Attribute::NoUnwind); 187226633Sdim Type *I8Ptr = B.getInt8PtrTy(); 188243830Sdim Value *StrNCpy = M->getOrInsertFunction(Name, 189249423Sdim AttributeSet::get(M->getContext(), 190249423Sdim AS), 191207618Srdivacky I8Ptr, I8Ptr, I8Ptr, 192207618Srdivacky Len->getType(), NULL); 193205218Srdivacky CallInst *CI = B.CreateCall3(StrNCpy, CastToCStr(Dst, B), CastToCStr(Src, B), 194205218Srdivacky Len, "strncpy"); 195205218Srdivacky if (const Function *F = dyn_cast<Function>(StrNCpy->stripPointerCasts())) 196205218Srdivacky CI->setCallingConv(F->getCallingConv()); 197205218Srdivacky return CI; 198205218Srdivacky} 199205218Srdivacky 200206083Srdivacky/// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder. 201206083Srdivacky/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src 202206083Srdivacky/// are pointers. 203206083SrdivackyValue *llvm::EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, 204243830Sdim IRBuilder<> &B, const DataLayout *TD, 205239462Sdim const TargetLibraryInfo *TLI) { 206239462Sdim if (!TLI->has(LibFunc::memcpy_chk)) 207239462Sdim return 0; 208239462Sdim 209206083Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 210249423Sdim AttributeSet AS; 211249423Sdim AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 212249423Sdim Attribute::NoUnwind); 213206083Srdivacky LLVMContext &Context = B.GetInsertBlock()->getContext(); 214206083Srdivacky Value *MemCpy = M->getOrInsertFunction("__memcpy_chk", 215249423Sdim AttributeSet::get(M->getContext(), AS), 216206083Srdivacky B.getInt8PtrTy(), 217206083Srdivacky B.getInt8PtrTy(), 218206083Srdivacky B.getInt8PtrTy(), 219206083Srdivacky TD->getIntPtrType(Context), 220206083Srdivacky TD->getIntPtrType(Context), NULL); 221206083Srdivacky Dst = CastToCStr(Dst, B); 222206083Srdivacky Src = CastToCStr(Src, B); 223206083Srdivacky CallInst *CI = B.CreateCall4(MemCpy, Dst, Src, Len, ObjSize); 224206083Srdivacky if (const Function *F = dyn_cast<Function>(MemCpy->stripPointerCasts())) 225206083Srdivacky CI->setCallingConv(F->getCallingConv()); 226206083Srdivacky return CI; 227206083Srdivacky} 228206083Srdivacky 229204792Srdivacky/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is 230204792Srdivacky/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. 231204792SrdivackyValue *llvm::EmitMemChr(Value *Ptr, Value *Val, 232243830Sdim Value *Len, IRBuilder<> &B, const DataLayout *TD, 233239462Sdim const TargetLibraryInfo *TLI) { 234239462Sdim if (!TLI->has(LibFunc::memchr)) 235239462Sdim return 0; 236239462Sdim 237204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 238249423Sdim AttributeSet AS; 239249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 240249423Sdim AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 241249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 242204792Srdivacky LLVMContext &Context = B.GetInsertBlock()->getContext(); 243243830Sdim Value *MemChr = M->getOrInsertFunction("memchr", 244249423Sdim AttributeSet::get(M->getContext(), AS), 245204792Srdivacky B.getInt8PtrTy(), 246204792Srdivacky B.getInt8PtrTy(), 247204792Srdivacky B.getInt32Ty(), 248204792Srdivacky TD->getIntPtrType(Context), 249204792Srdivacky NULL); 250204792Srdivacky CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr"); 251204792Srdivacky 252204792Srdivacky if (const Function *F = dyn_cast<Function>(MemChr->stripPointerCasts())) 253204792Srdivacky CI->setCallingConv(F->getCallingConv()); 254204792Srdivacky 255204792Srdivacky return CI; 256204792Srdivacky} 257204792Srdivacky 258204792Srdivacky/// EmitMemCmp - Emit a call to the memcmp function. 259204792SrdivackyValue *llvm::EmitMemCmp(Value *Ptr1, Value *Ptr2, 260243830Sdim Value *Len, IRBuilder<> &B, const DataLayout *TD, 261239462Sdim const TargetLibraryInfo *TLI) { 262239462Sdim if (!TLI->has(LibFunc::memcmp)) 263239462Sdim return 0; 264239462Sdim 265204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 266249423Sdim AttributeSet AS[3]; 267249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 268249423Sdim AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 269249423Sdim Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind }; 270249423Sdim AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 271249423Sdim ArrayRef<Attribute::AttrKind>(AVs, 2)); 272204792Srdivacky 273204792Srdivacky LLVMContext &Context = B.GetInsertBlock()->getContext(); 274243830Sdim Value *MemCmp = M->getOrInsertFunction("memcmp", 275249423Sdim AttributeSet::get(M->getContext(), AS), 276204792Srdivacky B.getInt32Ty(), 277204792Srdivacky B.getInt8PtrTy(), 278204792Srdivacky B.getInt8PtrTy(), 279204792Srdivacky TD->getIntPtrType(Context), NULL); 280204792Srdivacky CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B), 281204792Srdivacky Len, "memcmp"); 282204792Srdivacky 283204792Srdivacky if (const Function *F = dyn_cast<Function>(MemCmp->stripPointerCasts())) 284204792Srdivacky CI->setCallingConv(F->getCallingConv()); 285204792Srdivacky 286204792Srdivacky return CI; 287204792Srdivacky} 288204792Srdivacky 289204792Srdivacky/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. 290204792Srdivacky/// 'floor'). This function is known to take a single of type matching 'Op' and 291204792Srdivacky/// returns one value with the same type. If 'Op' is a long double, 'l' is 292204792Srdivacky/// added as the suffix of name, if 'Op' is a float, we add a 'f' suffix. 293234353SdimValue *llvm::EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B, 294249423Sdim const AttributeSet &Attrs) { 295234353Sdim SmallString<20> NameBuffer; 296204792Srdivacky if (!Op->getType()->isDoubleTy()) { 297204792Srdivacky // If we need to add a suffix, copy into NameBuffer. 298234353Sdim NameBuffer += Name; 299204792Srdivacky if (Op->getType()->isFloatTy()) 300234353Sdim NameBuffer += 'f'; // floorf 301204792Srdivacky else 302234353Sdim NameBuffer += 'l'; // floorl 303204792Srdivacky Name = NameBuffer; 304204792Srdivacky } 305204792Srdivacky 306204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 307204792Srdivacky Value *Callee = M->getOrInsertFunction(Name, Op->getType(), 308204792Srdivacky Op->getType(), NULL); 309204792Srdivacky CallInst *CI = B.CreateCall(Callee, Op, Name); 310204792Srdivacky CI->setAttributes(Attrs); 311204792Srdivacky if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts())) 312204792Srdivacky CI->setCallingConv(F->getCallingConv()); 313204792Srdivacky 314204792Srdivacky return CI; 315204792Srdivacky} 316204792Srdivacky 317204792Srdivacky/// EmitPutChar - Emit a call to the putchar function. This assumes that Char 318204792Srdivacky/// is an integer. 319243830SdimValue *llvm::EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD, 320239462Sdim const TargetLibraryInfo *TLI) { 321239462Sdim if (!TLI->has(LibFunc::putchar)) 322239462Sdim return 0; 323239462Sdim 324204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 325204792Srdivacky Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(), 326204792Srdivacky B.getInt32Ty(), NULL); 327204792Srdivacky CallInst *CI = B.CreateCall(PutChar, 328204792Srdivacky B.CreateIntCast(Char, 329204792Srdivacky B.getInt32Ty(), 330204792Srdivacky /*isSigned*/true, 331204792Srdivacky "chari"), 332204792Srdivacky "putchar"); 333204792Srdivacky 334204792Srdivacky if (const Function *F = dyn_cast<Function>(PutChar->stripPointerCasts())) 335204792Srdivacky CI->setCallingConv(F->getCallingConv()); 336204792Srdivacky return CI; 337204792Srdivacky} 338204792Srdivacky 339204792Srdivacky/// EmitPutS - Emit a call to the puts function. This assumes that Str is 340204792Srdivacky/// some pointer. 341243830SdimValue *llvm::EmitPutS(Value *Str, IRBuilder<> &B, const DataLayout *TD, 342239462Sdim const TargetLibraryInfo *TLI) { 343239462Sdim if (!TLI->has(LibFunc::puts)) 344239462Sdim return 0; 345239462Sdim 346204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 347249423Sdim AttributeSet AS[2]; 348249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 349249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 350249423Sdim Attribute::NoUnwind); 351204792Srdivacky 352243830Sdim Value *PutS = M->getOrInsertFunction("puts", 353249423Sdim AttributeSet::get(M->getContext(), AS), 354204792Srdivacky B.getInt32Ty(), 355204792Srdivacky B.getInt8PtrTy(), 356204792Srdivacky NULL); 357204792Srdivacky CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts"); 358204792Srdivacky if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts())) 359204792Srdivacky CI->setCallingConv(F->getCallingConv()); 360239462Sdim return CI; 361204792Srdivacky} 362204792Srdivacky 363204792Srdivacky/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is 364204792Srdivacky/// an integer and File is a pointer to FILE. 365239462SdimValue *llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, 366243830Sdim const DataLayout *TD, const TargetLibraryInfo *TLI) { 367239462Sdim if (!TLI->has(LibFunc::fputc)) 368239462Sdim return 0; 369239462Sdim 370204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 371249423Sdim AttributeSet AS[2]; 372249423Sdim AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 373249423Sdim AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 374249423Sdim Attribute::NoUnwind); 375204792Srdivacky Constant *F; 376204792Srdivacky if (File->getType()->isPointerTy()) 377243830Sdim F = M->getOrInsertFunction("fputc", 378249423Sdim AttributeSet::get(M->getContext(), AS), 379204792Srdivacky B.getInt32Ty(), 380204792Srdivacky B.getInt32Ty(), File->getType(), 381204792Srdivacky NULL); 382204792Srdivacky else 383204792Srdivacky F = M->getOrInsertFunction("fputc", 384204792Srdivacky B.getInt32Ty(), 385204792Srdivacky B.getInt32Ty(), 386204792Srdivacky File->getType(), NULL); 387204792Srdivacky Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true, 388204792Srdivacky "chari"); 389204792Srdivacky CallInst *CI = B.CreateCall2(F, Char, File, "fputc"); 390204792Srdivacky 391204792Srdivacky if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) 392204792Srdivacky CI->setCallingConv(Fn->getCallingConv()); 393239462Sdim return CI; 394204792Srdivacky} 395204792Srdivacky 396204792Srdivacky/// EmitFPutS - Emit a call to the puts function. Str is required to be a 397204792Srdivacky/// pointer and File is a pointer to FILE. 398239462SdimValue *llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, 399243830Sdim const DataLayout *TD, const TargetLibraryInfo *TLI) { 400239462Sdim if (!TLI->has(LibFunc::fputs)) 401239462Sdim return 0; 402239462Sdim 403204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 404249423Sdim AttributeSet AS[3]; 405249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 406249423Sdim AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture); 407249423Sdim AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 408249423Sdim Attribute::NoUnwind); 409234353Sdim StringRef FPutsName = TLI->getName(LibFunc::fputs); 410204792Srdivacky Constant *F; 411204792Srdivacky if (File->getType()->isPointerTy()) 412243830Sdim F = M->getOrInsertFunction(FPutsName, 413249423Sdim AttributeSet::get(M->getContext(), AS), 414204792Srdivacky B.getInt32Ty(), 415204792Srdivacky B.getInt8PtrTy(), 416204792Srdivacky File->getType(), NULL); 417204792Srdivacky else 418234353Sdim F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(), 419204792Srdivacky B.getInt8PtrTy(), 420204792Srdivacky File->getType(), NULL); 421204792Srdivacky CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs"); 422204792Srdivacky 423204792Srdivacky if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) 424204792Srdivacky CI->setCallingConv(Fn->getCallingConv()); 425239462Sdim return CI; 426204792Srdivacky} 427204792Srdivacky 428204792Srdivacky/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is 429204792Srdivacky/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. 430239462SdimValue *llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File, 431243830Sdim IRBuilder<> &B, const DataLayout *TD, 432239462Sdim const TargetLibraryInfo *TLI) { 433239462Sdim if (!TLI->has(LibFunc::fwrite)) 434239462Sdim return 0; 435239462Sdim 436204792Srdivacky Module *M = B.GetInsertBlock()->getParent()->getParent(); 437249423Sdim AttributeSet AS[3]; 438249423Sdim AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture); 439249423Sdim AS[1] = AttributeSet::get(M->getContext(), 4, Attribute::NoCapture); 440249423Sdim AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, 441249423Sdim Attribute::NoUnwind); 442204792Srdivacky LLVMContext &Context = B.GetInsertBlock()->getContext(); 443234353Sdim StringRef FWriteName = TLI->getName(LibFunc::fwrite); 444204792Srdivacky Constant *F; 445204792Srdivacky if (File->getType()->isPointerTy()) 446243830Sdim F = M->getOrInsertFunction(FWriteName, 447249423Sdim AttributeSet::get(M->getContext(), AS), 448204792Srdivacky TD->getIntPtrType(Context), 449204792Srdivacky B.getInt8PtrTy(), 450204792Srdivacky TD->getIntPtrType(Context), 451204792Srdivacky TD->getIntPtrType(Context), 452204792Srdivacky File->getType(), NULL); 453204792Srdivacky else 454234353Sdim F = M->getOrInsertFunction(FWriteName, TD->getIntPtrType(Context), 455204792Srdivacky B.getInt8PtrTy(), 456204792Srdivacky TD->getIntPtrType(Context), 457204792Srdivacky TD->getIntPtrType(Context), 458204792Srdivacky File->getType(), NULL); 459204792Srdivacky CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size, 460204792Srdivacky ConstantInt::get(TD->getIntPtrType(Context), 1), File); 461204792Srdivacky 462204792Srdivacky if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) 463204792Srdivacky CI->setCallingConv(Fn->getCallingConv()); 464239462Sdim return CI; 465204792Srdivacky} 466205218Srdivacky 467205218SrdivackySimplifyFortifiedLibCalls::~SimplifyFortifiedLibCalls() { } 468205218Srdivacky 469243830Sdimbool SimplifyFortifiedLibCalls::fold(CallInst *CI, const DataLayout *TD, 470239462Sdim const TargetLibraryInfo *TLI) { 471243830Sdim // We really need DataLayout for later. 472207618Srdivacky if (!TD) return false; 473207618Srdivacky 474205218Srdivacky this->CI = CI; 475207618Srdivacky Function *Callee = CI->getCalledFunction(); 476207618Srdivacky StringRef Name = Callee->getName(); 477226633Sdim FunctionType *FT = Callee->getFunctionType(); 478207618Srdivacky LLVMContext &Context = CI->getParent()->getContext(); 479223017Sdim IRBuilder<> B(CI); 480205218Srdivacky 481205218Srdivacky if (Name == "__memcpy_chk") { 482207618Srdivacky // Check if this has the right signature. 483207618Srdivacky if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || 484207618Srdivacky !FT->getParamType(0)->isPointerTy() || 485207618Srdivacky !FT->getParamType(1)->isPointerTy() || 486207618Srdivacky FT->getParamType(2) != TD->getIntPtrType(Context) || 487207618Srdivacky FT->getParamType(3) != TD->getIntPtrType(Context)) 488207618Srdivacky return false; 489210299Sed 490212904Sdim if (isFoldable(3, 2, false)) { 491218893Sdim B.CreateMemCpy(CI->getArgOperand(0), CI->getArgOperand(1), 492218893Sdim CI->getArgOperand(2), 1); 493210299Sed replaceCall(CI->getArgOperand(0)); 494205218Srdivacky return true; 495205218Srdivacky } 496205218Srdivacky return false; 497205218Srdivacky } 498205218Srdivacky 499205218Srdivacky // Should be similar to memcpy. 500205218Srdivacky if (Name == "__mempcpy_chk") { 501205218Srdivacky return false; 502205218Srdivacky } 503205218Srdivacky 504205218Srdivacky if (Name == "__memmove_chk") { 505207618Srdivacky // Check if this has the right signature. 506207618Srdivacky if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || 507207618Srdivacky !FT->getParamType(0)->isPointerTy() || 508207618Srdivacky !FT->getParamType(1)->isPointerTy() || 509207618Srdivacky FT->getParamType(2) != TD->getIntPtrType(Context) || 510207618Srdivacky FT->getParamType(3) != TD->getIntPtrType(Context)) 511207618Srdivacky return false; 512210299Sed 513212904Sdim if (isFoldable(3, 2, false)) { 514218893Sdim B.CreateMemMove(CI->getArgOperand(0), CI->getArgOperand(1), 515218893Sdim CI->getArgOperand(2), 1); 516210299Sed replaceCall(CI->getArgOperand(0)); 517205218Srdivacky return true; 518205218Srdivacky } 519205218Srdivacky return false; 520205218Srdivacky } 521205218Srdivacky 522205218Srdivacky if (Name == "__memset_chk") { 523207618Srdivacky // Check if this has the right signature. 524207618Srdivacky if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || 525207618Srdivacky !FT->getParamType(0)->isPointerTy() || 526207618Srdivacky !FT->getParamType(1)->isIntegerTy() || 527207618Srdivacky FT->getParamType(2) != TD->getIntPtrType(Context) || 528207618Srdivacky FT->getParamType(3) != TD->getIntPtrType(Context)) 529207618Srdivacky return false; 530210299Sed 531212904Sdim if (isFoldable(3, 2, false)) { 532210299Sed Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), 533205218Srdivacky false); 534218893Sdim B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1); 535210299Sed replaceCall(CI->getArgOperand(0)); 536205218Srdivacky return true; 537205218Srdivacky } 538205218Srdivacky return false; 539205218Srdivacky } 540205218Srdivacky 541205218Srdivacky if (Name == "__strcpy_chk" || Name == "__stpcpy_chk") { 542207618Srdivacky // Check if this has the right signature. 543207618Srdivacky if (FT->getNumParams() != 3 || 544207618Srdivacky FT->getReturnType() != FT->getParamType(0) || 545207618Srdivacky FT->getParamType(0) != FT->getParamType(1) || 546207618Srdivacky FT->getParamType(0) != Type::getInt8PtrTy(Context) || 547207618Srdivacky FT->getParamType(2) != TD->getIntPtrType(Context)) 548207618Srdivacky return 0; 549207618Srdivacky 550207618Srdivacky 551205218Srdivacky // If a) we don't have any length information, or b) we know this will 552205218Srdivacky // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our 553205218Srdivacky // st[rp]cpy_chk call which may fail at runtime if the size is too long. 554205218Srdivacky // TODO: It might be nice to get a maximum length out of the possible 555205218Srdivacky // string lengths for varying. 556212904Sdim if (isFoldable(2, 1, true)) { 557210299Sed Value *Ret = EmitStrCpy(CI->getArgOperand(0), CI->getArgOperand(1), B, TD, 558239462Sdim TLI, Name.substr(2, 6)); 559239462Sdim if (!Ret) 560239462Sdim return false; 561205218Srdivacky replaceCall(Ret); 562205218Srdivacky return true; 563205218Srdivacky } 564205218Srdivacky return false; 565205218Srdivacky } 566205218Srdivacky 567207618Srdivacky if (Name == "__strncpy_chk" || Name == "__stpncpy_chk") { 568207618Srdivacky // Check if this has the right signature. 569207618Srdivacky if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || 570207618Srdivacky FT->getParamType(0) != FT->getParamType(1) || 571207618Srdivacky FT->getParamType(0) != Type::getInt8PtrTy(Context) || 572207618Srdivacky !FT->getParamType(2)->isIntegerTy() || 573207618Srdivacky FT->getParamType(3) != TD->getIntPtrType(Context)) 574207618Srdivacky return false; 575210299Sed 576212904Sdim if (isFoldable(3, 2, false)) { 577210299Sed Value *Ret = EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1), 578239462Sdim CI->getArgOperand(2), B, TD, TLI, 579239462Sdim Name.substr(2, 7)); 580239462Sdim if (!Ret) 581239462Sdim return false; 582205218Srdivacky replaceCall(Ret); 583205218Srdivacky return true; 584205218Srdivacky } 585205218Srdivacky return false; 586205218Srdivacky } 587205218Srdivacky 588205218Srdivacky if (Name == "__strcat_chk") { 589205218Srdivacky return false; 590205218Srdivacky } 591205218Srdivacky 592205218Srdivacky if (Name == "__strncat_chk") { 593205218Srdivacky return false; 594205218Srdivacky } 595205218Srdivacky 596205218Srdivacky return false; 597205218Srdivacky} 598