712ec0482c477d8548de178e8c34b23e032db65c
[oota-llvm.git] / lib / CodeGen / IntrinsicLowering.cpp
1 //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the default intrinsic lowering implementation.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/CodeGen/IntrinsicLowering.h"
15 #include "llvm/Constants.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Module.h"
18 #include "llvm/Instructions.h"
19 #include <iostream>
20
21 using namespace llvm;
22
23 template <class ArgIt>
24 static Function *EnsureFunctionExists(Module &M, const char *Name,
25                                       ArgIt ArgBegin, ArgIt ArgEnd,
26                                       const Type *RetTy) {
27   if (Function *F = M.getNamedFunction(Name)) return F;
28   // It doesn't already exist in the program, insert a new definition now.
29   std::vector<const Type *> ParamTys;
30   for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
31     ParamTys.push_back(I->getType());
32   return M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
33 }
34
35 /// ReplaceCallWith - This function is used when we want to lower an intrinsic
36 /// call to a call of an external function.  This handles hard cases such as
37 /// when there was already a prototype for the external function, and if that
38 /// prototype doesn't match the arguments we expect to pass in.
39 template <class ArgIt>
40 static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
41                                  ArgIt ArgBegin, ArgIt ArgEnd,
42                                  const Type *RetTy, Function *&FCache) {
43   if (!FCache) {
44     // If we haven't already looked up this function, check to see if the
45     // program already contains a function with this name.
46     Module *M = CI->getParent()->getParent()->getParent();
47     FCache = M->getNamedFunction(NewFn);
48     if (!FCache) {
49       // It doesn't already exist in the program, insert a new definition now.
50       std::vector<const Type *> ParamTys;
51       for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
52         ParamTys.push_back((*I)->getType());
53       FCache = M->getOrInsertFunction(NewFn,
54                                      FunctionType::get(RetTy, ParamTys, false));
55     }
56    }
57
58   const FunctionType *FT = FCache->getFunctionType();
59   std::vector<Value*> Operands;
60   unsigned ArgNo = 0;
61   for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
62        ++I, ++ArgNo) {
63     Value *Arg = *I;
64     if (Arg->getType() != FT->getParamType(ArgNo))
65       Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
66     Operands.push_back(Arg);
67   }
68   // Pass nulls into any additional arguments...
69   for (; ArgNo != FT->getNumParams(); ++ArgNo)
70     Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
71
72   std::string Name = CI->getName(); CI->setName("");
73   if (FT->getReturnType() == Type::VoidTy) Name.clear();
74   CallInst *NewCI = new CallInst(FCache, Operands, Name, CI);
75   if (!CI->use_empty()) {
76     Value *V = NewCI;
77     if (CI->getType() != NewCI->getType())
78       V = new CastInst(NewCI, CI->getType(), Name, CI);
79     CI->replaceAllUsesWith(V);
80   }
81   return NewCI;
82 }
83
84 void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
85   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
86     if (I->isExternal() && !I->use_empty())
87       switch (I->getIntrinsicID()) {
88       default: break;
89       case Intrinsic::setjmp:
90         EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), Type::IntTy);
91         break;
92       case Intrinsic::longjmp:
93         EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(),Type::VoidTy);
94         break;
95       case Intrinsic::siglongjmp:
96         EnsureFunctionExists(M, "abort", I->arg_end(), I->arg_end(), Type::VoidTy);
97         break;
98       case Intrinsic::memcpy:
99         EnsureFunctionExists(M, "memcpy", I->arg_begin(), --I->arg_end(),
100                              I->arg_begin()->getType());
101         break;
102       case Intrinsic::memmove:
103         EnsureFunctionExists(M, "memmove", I->arg_begin(), --I->arg_end(),
104                              I->arg_begin()->getType());
105         break;
106       case Intrinsic::memset:
107         EnsureFunctionExists(M, "memset", I->arg_begin(), --I->arg_end(),
108                              I->arg_begin()->getType());
109         break;
110       case Intrinsic::isunordered:
111         EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy);
112         break;
113       case Intrinsic::sqrt:
114         if(I->abegin()->getType() == Type::FloatTy)
115           EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy);
116         else
117           EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy);
118         break;
119       }
120 }
121
122 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
123   Function *Callee = CI->getCalledFunction();
124   assert(Callee && "Cannot lower an indirect call!");
125
126   switch (Callee->getIntrinsicID()) {
127   case Intrinsic::not_intrinsic:
128     std::cerr << "Cannot lower a call to a non-intrinsic function '"
129               << Callee->getName() << "'!\n";
130     abort();
131   default:
132     std::cerr << "Error: Code generator does not support intrinsic function '"
133               << Callee->getName() << "'!\n";
134     abort();
135
136     // The setjmp/longjmp intrinsics should only exist in the code if it was
137     // never optimized (ie, right out of the CFE), or if it has been hacked on
138     // by the lowerinvoke pass.  In both cases, the right thing to do is to
139     // convert the call to an explicit setjmp or longjmp call.
140   case Intrinsic::setjmp: {
141     static Function *SetjmpFCache = 0;
142     Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
143                                Type::IntTy, SetjmpFCache);
144     if (CI->getType() != Type::VoidTy)
145       CI->replaceAllUsesWith(V);
146     break;
147   }
148   case Intrinsic::sigsetjmp:
149      if (CI->getType() != Type::VoidTy)
150        CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
151      break;
152
153   case Intrinsic::longjmp: {
154     static Function *LongjmpFCache = 0;
155     ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
156                     Type::VoidTy, LongjmpFCache);
157     break;
158   }
159
160   case Intrinsic::siglongjmp: {
161     // Insert the call to abort
162     static Function *AbortFCache = 0;
163     ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
164                     AbortFCache);
165     break;
166   }
167
168   case Intrinsic::returnaddress:
169   case Intrinsic::frameaddress:
170     std::cerr << "WARNING: this target does not support the llvm."
171               << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
172                   "return" : "frame") << "address intrinsic.\n";
173     CI->replaceAllUsesWith(ConstantPointerNull::get(
174                                             cast<PointerType>(CI->getType())));
175     break;
176
177   case Intrinsic::prefetch:
178     break;    // Simply strip out prefetches on unsupported architectures
179
180   case Intrinsic::pcmarker:
181     break;    // Simply strip out pcmarker on unsupported architectures
182
183   case Intrinsic::dbg_stoppoint:
184   case Intrinsic::dbg_region_start:
185   case Intrinsic::dbg_region_end:
186   case Intrinsic::dbg_declare:
187   case Intrinsic::dbg_func_start:
188     if (CI->getType() != Type::VoidTy)
189       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
190     break;    // Simply strip out debugging intrinsics
191
192   case Intrinsic::memcpy: {
193     // The memcpy intrinsic take an extra alignment argument that the memcpy
194     // libc function does not.
195     static Function *MemcpyFCache = 0;
196     ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
197                     (*(CI->op_begin()+1))->getType(), MemcpyFCache);
198     break;
199   }
200   case Intrinsic::memmove: {
201     // The memmove intrinsic take an extra alignment argument that the memmove
202     // libc function does not.
203     static Function *MemmoveFCache = 0;
204     ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
205                     (*(CI->op_begin()+1))->getType(), MemmoveFCache);
206     break;
207   }
208   case Intrinsic::memset: {
209     // The memset intrinsic take an extra alignment argument that the memset
210     // libc function does not.
211     static Function *MemsetFCache = 0;
212     ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
213                     (*(CI->op_begin()+1))->getType(), MemsetFCache);
214     break;
215   }
216   case Intrinsic::isunordered: {
217     Value *L = CI->getOperand(1);
218     Value *R = CI->getOperand(2);
219
220     Value *LIsNan = new SetCondInst(Instruction::SetNE, L, L, "LIsNan", CI);
221     Value *RIsNan = new SetCondInst(Instruction::SetNE, R, R, "RIsNan", CI);
222     CI->replaceAllUsesWith(
223       BinaryOperator::create(Instruction::Or, LIsNan, RIsNan,
224                              "isunordered", CI));
225     break;
226   }
227   case Intrinsic::sqrt: {
228     static Function *sqrtFCache = 0;
229     static Function *sqrtfFCache = 0;
230     if(CI->getType() == Type::FloatTy)
231       ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(),
232                       Type::FloatTy, sqrtfFCache);
233     else
234       ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(),
235                       Type::DoubleTy, sqrtFCache);
236     break;
237   }
238   }
239
240   assert(CI->use_empty() &&
241          "Lowering should have eliminated any uses of the intrinsic call!");
242   CI->getParent()->getInstList().erase(CI);
243 }