Remove trailing whitespace
[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       }
114
115 }
116
117 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
118   Function *Callee = CI->getCalledFunction();
119   assert(Callee && "Cannot lower an indirect call!");
120
121   switch (Callee->getIntrinsicID()) {
122   case Intrinsic::not_intrinsic:
123     std::cerr << "Cannot lower a call to a non-intrinsic function '"
124               << Callee->getName() << "'!\n";
125     abort();
126   default:
127     std::cerr << "Error: Code generator does not support intrinsic function '"
128               << Callee->getName() << "'!\n";
129     abort();
130
131     // The setjmp/longjmp intrinsics should only exist in the code if it was
132     // never optimized (ie, right out of the CFE), or if it has been hacked on
133     // by the lowerinvoke pass.  In both cases, the right thing to do is to
134     // convert the call to an explicit setjmp or longjmp call.
135   case Intrinsic::setjmp: {
136     static Function *SetjmpFCache = 0;
137     Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
138                                Type::IntTy, SetjmpFCache);
139     if (CI->getType() != Type::VoidTy)
140       CI->replaceAllUsesWith(V);
141     break;
142   }
143   case Intrinsic::sigsetjmp:
144      if (CI->getType() != Type::VoidTy)
145        CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
146      break;
147
148   case Intrinsic::longjmp: {
149     static Function *LongjmpFCache = 0;
150     ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
151                     Type::VoidTy, LongjmpFCache);
152     break;
153   }
154
155   case Intrinsic::siglongjmp: {
156     // Insert the call to abort
157     static Function *AbortFCache = 0;
158     ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
159                     AbortFCache);
160     break;
161   }
162
163   case Intrinsic::returnaddress:
164   case Intrinsic::frameaddress:
165     std::cerr << "WARNING: this target does not support the llvm."
166               << (Callee->getIntrinsicID() == Intrinsic::returnaddress ?
167                   "return" : "frame") << "address intrinsic.\n";
168     CI->replaceAllUsesWith(ConstantPointerNull::get(
169                                             cast<PointerType>(CI->getType())));
170     break;
171
172   case Intrinsic::prefetch:
173     break;    // Simply strip out prefetches on unsupported architectures
174
175   case Intrinsic::pcmarker:
176     break;    // Simply strip out pcmarker on unsupported architectures
177
178   case Intrinsic::dbg_stoppoint:
179   case Intrinsic::dbg_region_start:
180   case Intrinsic::dbg_region_end:
181   case Intrinsic::dbg_declare:
182   case Intrinsic::dbg_func_start:
183     if (CI->getType() != Type::VoidTy)
184       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
185     break;    // Simply strip out debugging intrinsics
186
187   case Intrinsic::memcpy: {
188     // The memcpy intrinsic take an extra alignment argument that the memcpy
189     // libc function does not.
190     static Function *MemcpyFCache = 0;
191     ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
192                     (*(CI->op_begin()+1))->getType(), MemcpyFCache);
193     break;
194   }
195   case Intrinsic::memmove: {
196     // The memmove intrinsic take an extra alignment argument that the memmove
197     // libc function does not.
198     static Function *MemmoveFCache = 0;
199     ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
200                     (*(CI->op_begin()+1))->getType(), MemmoveFCache);
201     break;
202   }
203   case Intrinsic::memset: {
204     // The memset intrinsic take an extra alignment argument that the memset
205     // libc function does not.
206     static Function *MemsetFCache = 0;
207     ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
208                     (*(CI->op_begin()+1))->getType(), MemsetFCache);
209     break;
210   }
211   case Intrinsic::isunordered: {
212     Value *L = CI->getOperand(1);
213     Value *R = CI->getOperand(2);
214
215     Value *LIsNan = new SetCondInst(Instruction::SetNE, L, L, "LIsNan", CI);
216     Value *RIsNan = new SetCondInst(Instruction::SetNE, R, R, "RIsNan", CI);
217     CI->replaceAllUsesWith(
218       BinaryOperator::create(Instruction::Or, LIsNan, RIsNan,
219                              "isunordered", CI));
220     break;
221   }
222   }
223
224   assert(CI->use_empty() &&
225          "Lowering should have eliminated any uses of the intrinsic call!");
226   CI->getParent()->getInstList().erase(CI);
227 }