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