LLVM API Documentation
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 }