LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

IntrinsicLowering.cpp

Go to the documentation of this file.
00001 //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 // 
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the default intrinsic lowering implementation.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/CodeGen/IntrinsicLowering.h"
00015 #include "llvm/Constants.h"
00016 #include "llvm/DerivedTypes.h"
00017 #include "llvm/Module.h"
00018 #include "llvm/Instructions.h"
00019 #include <iostream>
00020 
00021 using namespace llvm;
00022 
00023 template <class ArgIt>
00024 static Function *EnsureFunctionExists(Module &M, const char *Name,
00025                                       ArgIt ArgBegin, ArgIt ArgEnd,
00026                                       const Type *RetTy) {
00027   if (Function *F = M.getNamedFunction(Name)) return F;
00028   // It doesn't already exist in the program, insert a new definition now.
00029   std::vector<const Type *> ParamTys;
00030   for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
00031     ParamTys.push_back(I->getType());
00032   return M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false));
00033 }
00034 
00035 /// ReplaceCallWith - This function is used when we want to lower an intrinsic
00036 /// call to a call of an external function.  This handles hard cases such as
00037 /// when there was already a prototype for the external function, and if that
00038 /// prototype doesn't match the arguments we expect to pass in.
00039 template <class ArgIt>
00040 static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
00041                                  ArgIt ArgBegin, ArgIt ArgEnd,
00042                                  const Type *RetTy, Function *&FCache) {
00043   if (!FCache) {
00044     // If we haven't already looked up this function, check to see if the
00045     // program already contains a function with this name.
00046     Module *M = CI->getParent()->getParent()->getParent();
00047     FCache = M->getNamedFunction(NewFn);
00048     if (!FCache) {
00049       // It doesn't already exist in the program, insert a new definition now.
00050       std::vector<const Type *> ParamTys;
00051       for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
00052         ParamTys.push_back((*I)->getType());
00053       FCache = M->getOrInsertFunction(NewFn,
00054                                      FunctionType::get(RetTy, ParamTys, false));
00055     }
00056    }
00057 
00058   const FunctionType *FT = FCache->getFunctionType();
00059   std::vector<Value*> Operands;
00060   unsigned ArgNo = 0;
00061   for (ArgIt I = ArgBegin; I != ArgEnd && ArgNo != FT->getNumParams();
00062        ++I, ++ArgNo) {
00063     Value *Arg = *I;
00064     if (Arg->getType() != FT->getParamType(ArgNo))
00065       Arg = new CastInst(Arg, FT->getParamType(ArgNo), Arg->getName(), CI);
00066     Operands.push_back(Arg);
00067   }
00068   // Pass nulls into any additional arguments...
00069   for (; ArgNo != FT->getNumParams(); ++ArgNo)
00070     Operands.push_back(Constant::getNullValue(FT->getParamType(ArgNo)));
00071 
00072   std::string Name = CI->getName(); CI->setName("");
00073   if (FT->getReturnType() == Type::VoidTy) Name.clear();
00074   CallInst *NewCI = new CallInst(FCache, Operands, Name, CI);
00075   if (!CI->use_empty()) {
00076     Value *V = NewCI;
00077     if (CI->getType() != NewCI->getType())
00078       V = new CastInst(NewCI, CI->getType(), Name, CI);
00079     CI->replaceAllUsesWith(V);
00080   }
00081   return NewCI;
00082 }
00083 
00084 void DefaultIntrinsicLowering::AddPrototypes(Module &M) {
00085   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
00086     if (I->isExternal() && !I->use_empty())
00087       switch (I->getIntrinsicID()) {
00088       default: break;
00089       case Intrinsic::setjmp:
00090         EnsureFunctionExists(M, "setjmp", I->abegin(), I->aend(), Type::IntTy);
00091         break;
00092       case Intrinsic::longjmp:
00093         EnsureFunctionExists(M, "longjmp", I->abegin(), I->aend(),Type::VoidTy);
00094         break;
00095       case Intrinsic::siglongjmp:
00096         EnsureFunctionExists(M, "abort", I->aend(), I->aend(), Type::VoidTy);
00097         break;
00098       case Intrinsic::memcpy:
00099         EnsureFunctionExists(M, "memcpy", I->abegin(), --I->aend(),
00100                              I->abegin()->getType());
00101         break;
00102       case Intrinsic::memmove:
00103         EnsureFunctionExists(M, "memmove", I->abegin(), --I->aend(),
00104                              I->abegin()->getType());
00105         break;
00106       case Intrinsic::memset:
00107         EnsureFunctionExists(M, "memset", I->abegin(), --I->aend(),
00108                              I->abegin()->getType());
00109         break;
00110       case Intrinsic::isunordered:
00111         EnsureFunctionExists(M, "isunordered", I->abegin(), I->aend(), Type::BoolTy);
00112         break;
00113       }
00114 
00115 }
00116 
00117 void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
00118   Function *Callee = CI->getCalledFunction();
00119   assert(Callee && "Cannot lower an indirect call!");
00120   
00121   switch (Callee->getIntrinsicID()) {
00122   case Intrinsic::not_intrinsic:
00123     std::cerr << "Cannot lower a call to a non-intrinsic function '"
00124               << Callee->getName() << "'!\n";
00125     abort();
00126   default:
00127     std::cerr << "Error: Code generator does not support intrinsic function '"
00128               << Callee->getName() << "'!\n";
00129     abort();
00130 
00131     // The setjmp/longjmp intrinsics should only exist in the code if it was
00132     // never optimized (ie, right out of the CFE), or if it has been hacked on
00133     // by the lowerinvoke pass.  In both cases, the right thing to do is to
00134     // convert the call to an explicit setjmp or longjmp call.
00135   case Intrinsic::setjmp: {
00136     static Function *SetjmpFCache = 0;
00137     Value *V = ReplaceCallWith("setjmp", CI, CI->op_begin()+1, CI->op_end(),
00138                                Type::IntTy, SetjmpFCache);
00139     if (CI->getType() != Type::VoidTy)
00140       CI->replaceAllUsesWith(V);
00141     break;
00142   }
00143   case Intrinsic::sigsetjmp: 
00144      if (CI->getType() != Type::VoidTy)
00145        CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
00146      break;
00147 
00148   case Intrinsic::longjmp: {
00149     static Function *LongjmpFCache = 0;
00150     ReplaceCallWith("longjmp", CI, CI->op_begin()+1, CI->op_end(),
00151                     Type::VoidTy, LongjmpFCache);
00152     break;
00153   }
00154 
00155   case Intrinsic::siglongjmp: {
00156     // Insert the call to abort
00157     static Function *AbortFCache = 0;
00158     ReplaceCallWith("abort", CI, CI->op_end(), CI->op_end(), Type::VoidTy,
00159                     AbortFCache);
00160     break;
00161   }
00162 
00163   case Intrinsic::returnaddress:
00164   case Intrinsic::frameaddress:
00165     std::cerr << "WARNING: this target does not support the llvm."
00166               << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? 
00167                   "return" : "frame") << "address intrinsic.\n";
00168     CI->replaceAllUsesWith(ConstantPointerNull::get(
00169                                             cast<PointerType>(CI->getType())));
00170     break;
00171 
00172   case Intrinsic::dbg_stoppoint:
00173   case Intrinsic::dbg_region_start:
00174   case Intrinsic::dbg_region_end:
00175   case Intrinsic::dbg_declare:
00176   case Intrinsic::dbg_func_start:
00177     if (CI->getType() != Type::VoidTy)
00178       CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
00179     break;    // Simply strip out debugging intrinsics
00180 
00181   case Intrinsic::memcpy: {
00182     // The memcpy intrinsic take an extra alignment argument that the memcpy
00183     // libc function does not.
00184     static Function *MemcpyFCache = 0;
00185     ReplaceCallWith("memcpy", CI, CI->op_begin()+1, CI->op_end()-1,
00186                     (*(CI->op_begin()+1))->getType(), MemcpyFCache);
00187     break;
00188   }
00189   case Intrinsic::memmove: {
00190     // The memmove intrinsic take an extra alignment argument that the memmove
00191     // libc function does not.
00192     static Function *MemmoveFCache = 0;
00193     ReplaceCallWith("memmove", CI, CI->op_begin()+1, CI->op_end()-1,
00194                     (*(CI->op_begin()+1))->getType(), MemmoveFCache);
00195     break;
00196   }
00197   case Intrinsic::memset: {
00198     // The memset intrinsic take an extra alignment argument that the memset
00199     // libc function does not.
00200     static Function *MemsetFCache = 0;
00201     ReplaceCallWith("memset", CI, CI->op_begin()+1, CI->op_end()-1,
00202                     (*(CI->op_begin()+1))->getType(), MemsetFCache);
00203     break;
00204   }
00205   case Intrinsic::isunordered: {
00206     static Function *isunorderedFCache = 0;
00207     ReplaceCallWith("isunordered", CI, CI->op_begin()+1, CI->op_end(),
00208                     Type::BoolTy, isunorderedFCache);
00209     break;
00210   }
00211   }
00212   
00213   assert(CI->use_empty() &&
00214          "Lowering should have eliminated any uses of the intrinsic call!");
00215   CI->getParent()->getInstList().erase(CI);
00216 }