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   return;
230 }
231 
232 Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
233                                   const AttributeSet &Attrs) {
234   SmallString<20> NameBuffer;
235   appendTypeSuffix(Op, Name, NameBuffer);
236 
237   Module *M = B.GetInsertBlock()->getModule();
238   Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
239                                          Op->getType(), nullptr);
240   CallInst *CI = B.CreateCall(Callee, Op, Name);
241   CI->setAttributes(Attrs);
242   if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
243     CI->setCallingConv(F->getCallingConv());
244 
245   return CI;
246 }
247 
248 Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
249                                   IRBuilder<> &B, const AttributeSet &Attrs) {
250   SmallString<20> NameBuffer;
251   appendTypeSuffix(Op1, Name, NameBuffer);
252 
253   Module *M = B.GetInsertBlock()->getModule();
254   Value *Callee = M->getOrInsertFunction(Name, Op1->getType(), Op1->getType(),
255                                          Op2->getType(), nullptr);
256   CallInst *CI = B.CreateCall(Callee, {Op1, Op2}, Name);
257   CI->setAttributes(Attrs);
258   if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
259     CI->setCallingConv(F->getCallingConv());
260 
261   return CI;
262 }
263 
264 Value *llvm::emitPutChar(Value *Char, IRBuilder<> &B,
265                          const TargetLibraryInfo *TLI) {
266   if (!TLI->has(LibFunc::putchar))
267     return nullptr;
268 
269   Module *M = B.GetInsertBlock()->getModule();
270   Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(),
271                                           B.getInt32Ty(), nullptr);
272   CallInst *CI = B.CreateCall(PutChar,
273                               B.CreateIntCast(Char,
274                               B.getInt32Ty(),
275                               /*isSigned*/true,
276                               "chari"),
277                               "putchar");
278 
279   if (const Function *F = dyn_cast<Function>(PutChar->stripPointerCasts()))
280     CI->setCallingConv(F->getCallingConv());
281   return CI;
282 }
283 
284 Value *llvm::emitPutS(Value *Str, IRBuilder<> &B,
285                       const TargetLibraryInfo *TLI) {
286   if (!TLI->has(LibFunc::puts))
287     return nullptr;
288 
289   Module *M = B.GetInsertBlock()->getModule();
290   AttributeSet AS[2];
291   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
292   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
293                             Attribute::NoUnwind);
294 
295   Value *PutS = M->getOrInsertFunction("puts",
296                                        AttributeSet::get(M->getContext(), AS),
297                                        B.getInt32Ty(),
298                                        B.getInt8PtrTy(),
299                                        nullptr);
300   CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), "puts");
301   if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
302     CI->setCallingConv(F->getCallingConv());
303   return CI;
304 }
305 
306 Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilder<> &B,
307                        const TargetLibraryInfo *TLI) {
308   if (!TLI->has(LibFunc::fputc))
309     return nullptr;
310 
311   Module *M = B.GetInsertBlock()->getModule();
312   AttributeSet AS[2];
313   AS[0] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
314   AS[1] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
315                             Attribute::NoUnwind);
316   Constant *F;
317   if (File->getType()->isPointerTy())
318     F = M->getOrInsertFunction("fputc",
319                                AttributeSet::get(M->getContext(), AS),
320                                B.getInt32Ty(),
321                                B.getInt32Ty(), File->getType(),
322                                nullptr);
323   else
324     F = M->getOrInsertFunction("fputc",
325                                B.getInt32Ty(),
326                                B.getInt32Ty(),
327                                File->getType(), nullptr);
328   Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
329                          "chari");
330   CallInst *CI = B.CreateCall(F, {Char, File}, "fputc");
331 
332   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
333     CI->setCallingConv(Fn->getCallingConv());
334   return CI;
335 }
336 
337 Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilder<> &B,
338                        const TargetLibraryInfo *TLI) {
339   if (!TLI->has(LibFunc::fputs))
340     return nullptr;
341 
342   Module *M = B.GetInsertBlock()->getModule();
343   AttributeSet AS[3];
344   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
345   AS[1] = AttributeSet::get(M->getContext(), 2, Attribute::NoCapture);
346   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
347                             Attribute::NoUnwind);
348   StringRef FPutsName = TLI->getName(LibFunc::fputs);
349   Constant *F;
350   if (File->getType()->isPointerTy())
351     F = M->getOrInsertFunction(FPutsName,
352                                AttributeSet::get(M->getContext(), AS),
353                                B.getInt32Ty(),
354                                B.getInt8PtrTy(),
355                                File->getType(), nullptr);
356   else
357     F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(),
358                                B.getInt8PtrTy(),
359                                File->getType(), nullptr);
360   CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, "fputs");
361 
362   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
363     CI->setCallingConv(Fn->getCallingConv());
364   return CI;
365 }
366 
367 Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
368                         const DataLayout &DL, const TargetLibraryInfo *TLI) {
369   if (!TLI->has(LibFunc::fwrite))
370     return nullptr;
371 
372   Module *M = B.GetInsertBlock()->getModule();
373   AttributeSet AS[3];
374   AS[0] = AttributeSet::get(M->getContext(), 1, Attribute::NoCapture);
375   AS[1] = AttributeSet::get(M->getContext(), 4, Attribute::NoCapture);
376   AS[2] = AttributeSet::get(M->getContext(), AttributeSet::FunctionIndex,
377                             Attribute::NoUnwind);
378   LLVMContext &Context = B.GetInsertBlock()->getContext();
379   StringRef FWriteName = TLI->getName(LibFunc::fwrite);
380   Constant *F;
381   if (File->getType()->isPointerTy())
382     F = M->getOrInsertFunction(
383         FWriteName, AttributeSet::get(M->getContext(), AS),
384         DL.getIntPtrType(Context), B.getInt8PtrTy(), DL.getIntPtrType(Context),
385         DL.getIntPtrType(Context), File->getType(), nullptr);
386   else
387     F = M->getOrInsertFunction(FWriteName, DL.getIntPtrType(Context),
388                                B.getInt8PtrTy(), DL.getIntPtrType(Context),
389                                DL.getIntPtrType(Context), File->getType(),
390                                nullptr);
391   CallInst *CI =
392       B.CreateCall(F, {castToCStr(Ptr, B), Size,
393                        ConstantInt::get(DL.getIntPtrType(Context), 1), File});
394 
395   if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
396     CI->setCallingConv(Fn->getCallingConv());
397   return CI;
398 }
399