1 //===- BuildLibCalls.cpp - Utility builder for libcalls -------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements some functions that will create standard C libcalls.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/Transforms/Utils/BuildLibCalls.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/Analysis/TargetLibraryInfo.h"
17 #include "llvm/IR/Constants.h"
18 #include "llvm/IR/DataLayout.h"
19 #include "llvm/IR/Function.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/IR/LLVMContext.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/IR/Type.h"
25 
26 using namespace llvm;
27 
28 Value *llvm::castToCStr(Value *V, IRBuilder<> &B) {
29   unsigned AS = V->getType()->getPointerAddressSpace();
30   return B.CreateBitCast(V, B.getInt8PtrTy(AS), "cstr");
31 }
32 
33 Value *llvm::emitStrLen(Value *Ptr, IRBuilder<> &B, const DataLayout &DL,
34                         const TargetLibraryInfo *TLI) {
35   if (!TLI->has(LibFunc::strlen))
36     return nullptr;
37 
38   Module *M = B.GetInsertBlock()->getModule();
39   AttributeSet AS[2];
40   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
41   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
42   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);
43 
44   LLVMContext &Context = B.GetInsertBlock()->getContext();
45   Constant *StrLen = M->getOrInsertFunction(
46       "strlen", AttributeSet::get(M->getContext(), AS),
47       DL.getIntPtrType(Context), B.getInt8PtrTy(), nullptr);
48   CallInst *CI = B.CreateCall(StrLen, castToCStr(Ptr, B), "strlen");
49   if (const Function *F = dyn_cast<Function>(StrLen->stripPointerCasts()))
50     CI->setCallingConv(F->getCallingConv());
51 
52   return CI;
53 }
54 
55 Value *llvm::emitStrChr(Value *Ptr, char C, IRBuilder<> &B,
56                         const TargetLibraryInfo *TLI) {
57   if (!TLI->has(LibFunc::strchr))
58     return nullptr;
59 
60   Module *M = B.GetInsertBlock()->getModule();
61   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
62   AttributeSet AS =
63     AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);
64 
65   Type *I8Ptr = B.getInt8PtrTy();
66   Type *I32Ty = B.getInt32Ty();
67   Constant *StrChr = M->getOrInsertFunction("strchr",
68                                             AttributeSet::get(M->getContext(),
69                                                              AS),
70                                             I8Ptr, I8Ptr, I32Ty, nullptr);
71   CallInst *CI = B.CreateCall(
72       StrChr, {castToCStr(Ptr, B), ConstantInt::get(I32Ty, C)}, "strchr");
73   if (const Function *F = dyn_cast<Function>(StrChr->stripPointerCasts()))
74     CI->setCallingConv(F->getCallingConv());
75   return CI;
76 }
77 
78 Value *llvm::emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
79                          const DataLayout &DL, const TargetLibraryInfo *TLI) {
80   if (!TLI->has(LibFunc::strncmp))
81     return nullptr;
82 
83   Module *M = B.GetInsertBlock()->getModule();
84   AttributeSet AS[3];
85   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
86   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
87   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
88   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);
89 
90   LLVMContext &Context = B.GetInsertBlock()->getContext();
91   Value *StrNCmp = M->getOrInsertFunction(
92       "strncmp", AttributeSet::get(M->getContext(), AS), B.getInt32Ty(),
93       B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context), nullptr);
94   CallInst *CI = B.CreateCall(
95       StrNCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, "strncmp");
96 
97   if (const Function *F = dyn_cast<Function>(StrNCmp->stripPointerCasts()))
98     CI->setCallingConv(F->getCallingConv());
99 
100   return CI;
101 }
102 
103 Value *llvm::emitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
104                         const TargetLibraryInfo *TLI, StringRef Name) {
105   if (!TLI->has(LibFunc::strcpy))
106     return nullptr;
107 
108   Module *M = B.GetInsertBlock()->getModule();
109   AttributeSet AS[2];
110   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
111   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
112                             Attribute::NoUnwind);
113   Type *I8Ptr = B.getInt8PtrTy();
114   Value *StrCpy = M->getOrInsertFunction(Name,
115                                          AttributeSet::get(M->getContext(), AS),
116                                          I8Ptr, I8Ptr, I8Ptr, nullptr);
117   CallInst *CI =
118       B.CreateCall(StrCpy, {castToCStr(Dst, B), castToCStr(Src, B)}, Name);
119   if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts()))
120     CI->setCallingConv(F->getCallingConv());
121   return CI;
122 }
123 
124 Value *llvm::emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
125                          const TargetLibraryInfo *TLI, StringRef Name) {
126   if (!TLI->has(LibFunc::strncpy))
127     return nullptr;
128 
129   Module *M = B.GetInsertBlock()->getModule();
130   AttributeSet AS[2];
131   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
132   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
133                             Attribute::NoUnwind);
134   Type *I8Ptr = B.getInt8PtrTy();
135   Value *StrNCpy = M->getOrInsertFunction(Name,
136                                           AttributeSet::get(M->getContext(),
137                                                             AS),
138                                           I8Ptr, I8Ptr, I8Ptr,
139                                           Len->getType(), nullptr);
140   CallInst *CI = B.CreateCall(
141       StrNCpy, {castToCStr(Dst, B), castToCStr(Src, B), Len}, "strncpy");
142   if (const Function *F = dyn_cast<Function>(StrNCpy->stripPointerCasts()))
143     CI->setCallingConv(F->getCallingConv());
144   return CI;
145 }
146 
147 Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
148                            IRBuilder<> &B, const DataLayout &DL,
149                            const TargetLibraryInfo *TLI) {
150   if (!TLI->has(LibFunc::memcpy_chk))
151     return nullptr;
152 
153   Module *M = B.GetInsertBlock()->getModule();
154   AttributeSet AS;
155   AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
156                          Attribute::NoUnwind);
157   LLVMContext &Context = B.GetInsertBlock()->getContext();
158   Value *MemCpy = M->getOrInsertFunction(
159       "__memcpy_chk", AttributeSet::get(M->getContext(), AS), B.getInt8PtrTy(),
160       B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context),
161       DL.getIntPtrType(Context), nullptr);
162   Dst = castToCStr(Dst, B);
163   Src = castToCStr(Src, B);
164   CallInst *CI = B.CreateCall(MemCpy, {Dst, Src, Len, ObjSize});
165   if (const Function *F = dyn_cast<Function>(MemCpy->stripPointerCasts()))
166     CI->setCallingConv(F->getCallingConv());
167   return CI;
168 }
169 
170 Value *llvm::emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
171                         const DataLayout &DL, const TargetLibraryInfo *TLI) {
172   if (!TLI->has(LibFunc::memchr))
173     return nullptr;
174 
175   Module *M = B.GetInsertBlock()->getModule();
176   AttributeSet AS;
177   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
178   AS = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);
179   LLVMContext &Context = B.GetInsertBlock()->getContext();
180   Value *MemChr = M->getOrInsertFunction(
181       "memchr", AttributeSet::get(M->getContext(), AS), B.getInt8PtrTy(),
182       B.getInt8PtrTy(), B.getInt32Ty(), DL.getIntPtrType(Context), nullptr);
183   CallInst *CI = B.CreateCall(MemChr, {castToCStr(Ptr, B), Val, Len}, "memchr");
184 
185   if (const Function *F = dyn_cast<Function>(MemChr->stripPointerCasts()))
186     CI->setCallingConv(F->getCallingConv());
187 
188   return CI;
189 }
190 
191 Value *llvm::emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
192                         const DataLayout &DL, const TargetLibraryInfo *TLI) {
193   if (!TLI->has(LibFunc::memcmp))
194     return nullptr;
195 
196   Module *M = B.GetInsertBlock()->getModule();
197   AttributeSet AS[3];
198   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
199   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
200   Attribute::AttrKind AVs[2] = { Attribute::ReadOnly, Attribute::NoUnwind };
201   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex, AVs);
202 
203   LLVMContext &Context = B.GetInsertBlock()->getContext();
204   Value *MemCmp = M->getOrInsertFunction(
205       "memcmp", AttributeSet::get(M->getContext(), AS), B.getInt32Ty(),
206       B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context), nullptr);
207   CallInst *CI = B.CreateCall(
208       MemCmp, {castToCStr(Ptr1, B), castToCStr(Ptr2, B), Len}, "memcmp");
209 
210   if (const Function *F = dyn_cast<Function>(MemCmp->stripPointerCasts()))
211     CI->setCallingConv(F->getCallingConv());
212 
213   return CI;
214 }
215 
216 /// Append a suffix to the function name according to the type of 'Op'.
217 static void appendTypeSuffix(Value *Op, StringRef &Name,
218                              SmallString<20> &NameBuffer) {
219   if (!Op->getType()->isDoubleTy()) {
220       NameBuffer += Name;
221 
222     if (Op->getType()->isFloatTy())
223       NameBuffer += 'f';
224     else
225       NameBuffer += 'l';
226 
227     Name = NameBuffer;
228   }
229 }
230 
231 Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
232                                   const AttributeSet &Attrs) {
233   SmallString<20> NameBuffer;
234   appendTypeSuffix(Op, Name, NameBuffer);
235 
236   Module *M = B.GetInsertBlock()->getModule();
237   Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
238                                          Op->getType(), nullptr);
239   CallInst *CI = B.CreateCall(Callee, Op, Name);
240   CI->setAttributes(Attrs);
241   if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
242     CI->setCallingConv(F->getCallingConv());
243 
244   return CI;
245 }
246 
247 Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
248                                   IRBuilder<> &B, const AttributeSet &Attrs) {
249   SmallString<20> NameBuffer;
250   appendTypeSuffix(Op1, Name, NameBuffer);
251 
252   Module *M = B.GetInsertBlock()->getModule();
253   Value *Callee = M->getOrInsertFunction(Name, Op1->getType(), Op1->getType(),
254                                          Op2->getType(), nullptr);
255   CallInst *CI = B.CreateCall(Callee, {Op1, Op2}, Name);
256   CI->setAttributes(Attrs);
257   if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
258     CI->setCallingConv(F->getCallingConv());
259 
260   return CI;
261 }
262 
263 Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B,
264                          const TargetLibraryInfo *TLI) {
265   if (!TLI->has(LibFunc::putchar))
266     return nullptr;
267 
268   Module *M = B.GetInsertBlock()->getModule();
269   Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(),
270                                           B.getInt32Ty(), nullptr);
271   CallInst *CI = B.CreateCall(PutChar,
272                               B.CreateIntCast(Char,
273                               B.getInt32Ty(),
274                               /*isSigned*/true,
275                               "chari"),
276                               "putchar");
277 
278   if (const Function *F = dyn_cast<Function>(PutChar->stripPointerCasts()))
279     CI->setCallingConv(F->getCallingConv());
280   return CI;
281 }
282 
283 Value *llvm::emitPutS(Value *Str, IRBuilder<> &B,
284                       const TargetLibraryInfo *TLI) {
285   if (!TLI->has(LibFunc::puts))
286     return nullptr;
287 
288   Module *M = B.GetInsertBlock()->getModule();
289   AttributeSet AS[2];
290   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
291   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
292                             Attribute::NoUnwind);
293 
294   Value *PutS = M->getOrInsertFunction("puts",
295                                        AttributeSet::get(M->getContext(), AS),
296                                        B.getInt32Ty(),
297                                        B.getInt8PtrTy(),
298                                        nullptr);
299   CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), "puts");
300   if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
301     CI->setCallingConv(F->getCallingConv());
302   return CI;
303 }
304 
305 Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
306                        const TargetLibraryInfo *TLI) {
307   if (!TLI->has(LibFunc::fputc))
308     return nullptr;
309 
310   Module *M = B.GetInsertBlock()->getModule();
311   AttributeSet AS[2];
312   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
313   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
314                             Attribute::NoUnwind);
315   Constant *F;
316   if (File->getType()->isPointerTy())
317     F = M->getOrInsertFunction("fputc",
318                                AttributeSet::get(M->getContext(), AS),
319                                B.getInt32Ty(),
320                                B.getInt32Ty(), File->getType(),
321                                nullptr);
322   else
323     F = M->getOrInsertFunction("fputc",
324                                B.getInt32Ty(),
325                                B.getInt32Ty(),
326                                File->getType(), nullptr);
327   Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
328                          "chari");
329   CallInst *CI = B.CreateCall(F, {Char, File}, "fputc");
330 
331   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
332     CI->setCallingConv(Fn->getCallingConv());
333   return CI;
334 }
335 
336 Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
337                        const TargetLibraryInfo *TLI) {
338   if (!TLI->has(LibFunc::fputs))
339     return nullptr;
340 
341   Module *M = B.GetInsertBlock()->getModule();
342   AttributeSet AS[3];
343   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
344   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
345   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
346                             Attribute::NoUnwind);
347   StringRef FPutsName = TLI->getName(LibFunc::fputs);
348   Constant *F;
349   if (File->getType()->isPointerTy())
350     F = M->getOrInsertFunction(FPutsName,
351                                AttributeSet::get(M->getContext(), AS),
352                                B.getInt32Ty(),
353                                B.getInt8PtrTy(),
354                                File->getType(), nullptr);
355   else
356     F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(),
357                                B.getInt8PtrTy(),
358                                File->getType(), nullptr);
359   CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, "fputs");
360 
361   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
362     CI->setCallingConv(Fn->getCallingConv());
363   return CI;
364 }
365 
366 Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
367                         const DataLayout &DL, const TargetLibraryInfo *TLI) {
368   if (!TLI->has(LibFunc::fwrite))
369     return nullptr;
370 
371   Module *M = B.GetInsertBlock()->getModule();
372   AttributeSet AS[3];
373   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
374   AS[1] = AttributeSet::get(M->getContext(), 4, Attribute::NoCapture);
375   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
376                             Attribute::NoUnwind);
377   LLVMContext &Context = B.GetInsertBlock()->getContext();
378   StringRef FWriteName = TLI->getName(LibFunc::fwrite);
379   Constant *F;
380   if (File->getType()->isPointerTy())
381     F = M->getOrInsertFunction(
382         FWriteName, AttributeSet::get(M->getContext(), AS),
383         DL.getIntPtrType(Context), B.getInt8PtrTy(), DL.getIntPtrType(Context),
384         DL.getIntPtrType(Context), File->getType(), nullptr);
385   else
386     F = M->getOrInsertFunction(FWriteName, DL.getIntPtrType(Context),
387                                B.getInt8PtrTy(), DL.getIntPtrType(Context),
388                                DL.getIntPtrType(Context), File->getType(),
389                                nullptr);
390   CallInst *CI =
391       B.CreateCall(F, {castToCStr(Ptr, B), Size,
392                        ConstantInt::get(DL.getIntPtrType(Context), 1), File});
393 
394   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
395     CI->setCallingConv(Fn->getCallingConv());
396   return CI;
397 }
398