//===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// // // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the default intrinsic lowering implementation. // //===----------------------------------------------------------------------===// #include "llvm/IntrinsicLowering.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/iOther.h" using namespace llvm; void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { Function *Callee = CI->getCalledFunction(); assert(Callee && "Cannot lower an indirect call!"); Module *M = Callee->getParent(); switch (Callee->getIntrinsicID()) { case Intrinsic::not_intrinsic: std::cerr << "Cannot lower a call to a non-intrinsic function '" << Callee->getName() << "'!\n"; abort(); default: std::cerr << "Error: Code generator does not support intrinsic function '" << Callee->getName() << "'!\n"; abort(); // The default implementation of setjmp/longjmp transforms setjmp into a // noop that always returns zero and longjmp into a call to abort. This // allows code that never longjmps to work correctly. case Intrinsic::setjmp: case Intrinsic::sigsetjmp: if (CI->getType() != Type::VoidTy) CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); break; case Intrinsic::longjmp: case Intrinsic::siglongjmp: // Insert the call to abort new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI); break; case Intrinsic::returnaddress: case Intrinsic::frameaddress: std::cerr << "WARNING: this target does not support the llvm." << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? "return" : "frame") << "address intrinsic.\n"; CI->replaceAllUsesWith(ConstantPointerNull::get( cast(CI->getType()))); break; case Intrinsic::dbg_stoppoint: case Intrinsic::dbg_region_start: case Intrinsic::dbg_region_end: case Intrinsic::dbg_declare: case Intrinsic::dbg_func_start: if (CI->getType() != Type::VoidTy) CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); break; // Simply strip out debugging intrinsics case Intrinsic::memcpy: { // The memcpy intrinsic take an extra alignment argument that the memcpy // libc function does not. const FunctionType *CFT = Callee->getFunctionType(); FunctionType *FT = FunctionType::get(*CFT->param_begin(), std::vector(CFT->param_begin(), CFT->param_end()-1), false); Function *MemCpy = M->getOrInsertFunction("memcpy", FT); new CallInst(MemCpy, std::vector(CI->op_begin()+1, CI->op_end()-1), CI->getName(), CI); break; } case Intrinsic::memmove: { // The memmove intrinsic take an extra alignment argument that the memmove // libc function does not. const FunctionType *CFT = Callee->getFunctionType(); FunctionType *FT = FunctionType::get(*CFT->param_begin(), std::vector(CFT->param_begin(), CFT->param_end()-1), false); Function *MemMove = M->getOrInsertFunction("memmove", FT); new CallInst(MemMove, std::vector(CI->op_begin()+1, CI->op_end()-1), CI->getName(), CI); break; } case Intrinsic::memset: { // The memset intrinsic take an extra alignment argument that the memset // libc function does not. const FunctionType *CFT = Callee->getFunctionType(); FunctionType *FT = FunctionType::get(*CFT->param_begin(), std::vector(CFT->param_begin(), CFT->param_end()-1), false); Function *MemSet = M->getOrInsertFunction("memset", FT); new CallInst(MemSet, std::vector(CI->op_begin()+1, CI->op_end()-1), CI->getName(), CI); break; } } assert(CI->use_empty() && "Lowering should have eliminated any uses of the intrinsic call!"); CI->getParent()->getInstList().erase(CI); }