Chris Lattner | 3b66ecb | 2003-12-28 08:19:41 +0000 | [diff] [blame] | 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 | |
Chris Lattner | 42450d8 | 2003-12-28 08:30:20 +0000 | [diff] [blame] | 14 | #include "llvm/IntrinsicLowering.h" |
Chris Lattner | cf89908 | 2004-02-14 02:47:17 +0000 | [diff] [blame] | 15 | #include "llvm/Constants.h" |
Chris Lattner | 5fe51cc | 2004-02-12 17:01:09 +0000 | [diff] [blame] | 16 | #include "llvm/DerivedTypes.h" |
Chris Lattner | 3b66ecb | 2003-12-28 08:19:41 +0000 | [diff] [blame] | 17 | #include "llvm/Module.h" |
Chris Lattner | 3b66ecb | 2003-12-28 08:19:41 +0000 | [diff] [blame] | 18 | #include "llvm/iOther.h" |
| 19 | using namespace llvm; |
| 20 | |
| 21 | void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { |
| 22 | Function *Callee = CI->getCalledFunction(); |
| 23 | assert(Callee && "Cannot lower an indirect call!"); |
| 24 | |
| 25 | Module *M = Callee->getParent(); |
| 26 | |
| 27 | switch (Callee->getIntrinsicID()) { |
| 28 | case Intrinsic::not_intrinsic: |
| 29 | std::cerr << "Cannot lower a call to a non-intrinsic function '" |
| 30 | << Callee->getName() << "'!\n"; |
| 31 | abort(); |
| 32 | default: |
| 33 | std::cerr << "Error: Code generator does not support intrinsic function '" |
| 34 | << Callee->getName() << "'!\n"; |
| 35 | abort(); |
| 36 | |
| 37 | // The default implementation of setjmp/longjmp transforms setjmp into a |
| 38 | // noop that always returns zero and longjmp into a call to abort. This |
| 39 | // allows code that never longjmps to work correctly. |
| 40 | case Intrinsic::setjmp: |
| 41 | case Intrinsic::sigsetjmp: |
| 42 | if (CI->getType() != Type::VoidTy) |
| 43 | CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); |
| 44 | break; |
| 45 | |
| 46 | case Intrinsic::longjmp: |
| 47 | case Intrinsic::siglongjmp: |
| 48 | // Insert the call to abort |
| 49 | new CallInst(M->getOrInsertFunction("abort", Type::VoidTy, 0), "", CI); |
| 50 | break; |
Chris Lattner | 77b1330 | 2004-01-05 05:36:30 +0000 | [diff] [blame] | 51 | |
Chris Lattner | cf89908 | 2004-02-14 02:47:17 +0000 | [diff] [blame] | 52 | case Intrinsic::returnaddress: |
| 53 | case Intrinsic::frameaddress: |
Chris Lattner | cc42d2c | 2004-02-14 04:52:06 +0000 | [diff] [blame] | 54 | std::cerr << "WARNING: this target does not support the llvm." |
| 55 | << (Callee->getIntrinsicID() == Intrinsic::returnaddress ? |
| 56 | "return" : "frame") << "address intrinsic.\n"; |
Chris Lattner | cf89908 | 2004-02-14 02:47:17 +0000 | [diff] [blame] | 57 | CI->replaceAllUsesWith(ConstantPointerNull::get( |
| 58 | cast<PointerType>(CI->getType()))); |
| 59 | break; |
| 60 | |
Chris Lattner | 77b1330 | 2004-01-05 05:36:30 +0000 | [diff] [blame] | 61 | case Intrinsic::dbg_stoppoint: |
| 62 | case Intrinsic::dbg_region_start: |
| 63 | case Intrinsic::dbg_region_end: |
Chris Lattner | f907bac | 2004-01-14 20:41:29 +0000 | [diff] [blame] | 64 | case Intrinsic::dbg_declare: |
Chris Lattner | 77b1330 | 2004-01-05 05:36:30 +0000 | [diff] [blame] | 65 | case Intrinsic::dbg_func_start: |
| 66 | if (CI->getType() != Type::VoidTy) |
| 67 | CI->replaceAllUsesWith(Constant::getNullValue(CI->getType())); |
| 68 | break; // Simply strip out debugging intrinsics |
Chris Lattner | 5fe51cc | 2004-02-12 17:01:09 +0000 | [diff] [blame] | 69 | |
| 70 | case Intrinsic::memcpy: { |
| 71 | // The memcpy intrinsic take an extra alignment argument that the memcpy |
| 72 | // libc function does not. |
| 73 | const FunctionType *CFT = Callee->getFunctionType(); |
| 74 | FunctionType *FT = |
| 75 | FunctionType::get(*CFT->param_begin(), |
| 76 | std::vector<const Type*>(CFT->param_begin(), CFT->param_end()-1), |
| 77 | false); |
| 78 | Function *MemCpy = M->getOrInsertFunction("memcpy", FT); |
| 79 | new CallInst(MemCpy, std::vector<Value*>(CI->op_begin()+1, CI->op_end()-1), |
| 80 | CI->getName(), CI); |
| 81 | break; |
| 82 | } |
Chris Lattner | 2751e76 | 2004-02-12 18:11:20 +0000 | [diff] [blame] | 83 | case Intrinsic::memmove: { |
Chris Lattner | cf89908 | 2004-02-14 02:47:17 +0000 | [diff] [blame] | 84 | // The memmove intrinsic take an extra alignment argument that the memmove |
Chris Lattner | 2751e76 | 2004-02-12 18:11:20 +0000 | [diff] [blame] | 85 | // libc function does not. |
| 86 | const FunctionType *CFT = Callee->getFunctionType(); |
| 87 | FunctionType *FT = |
| 88 | FunctionType::get(*CFT->param_begin(), |
| 89 | std::vector<const Type*>(CFT->param_begin(), CFT->param_end()-1), |
| 90 | false); |
| 91 | Function *MemMove = M->getOrInsertFunction("memmove", FT); |
| 92 | new CallInst(MemMove, std::vector<Value*>(CI->op_begin()+1, CI->op_end()-1), |
| 93 | CI->getName(), CI); |
| 94 | break; |
| 95 | } |
Chris Lattner | cf89908 | 2004-02-14 02:47:17 +0000 | [diff] [blame] | 96 | case Intrinsic::memset: { |
| 97 | // The memset intrinsic take an extra alignment argument that the memset |
| 98 | // libc function does not. |
| 99 | const FunctionType *CFT = Callee->getFunctionType(); |
| 100 | FunctionType *FT = |
| 101 | FunctionType::get(*CFT->param_begin(), |
| 102 | std::vector<const Type*>(CFT->param_begin(), CFT->param_end()-1), |
| 103 | false); |
| 104 | Function *MemSet = M->getOrInsertFunction("memset", FT); |
| 105 | new CallInst(MemSet, std::vector<Value*>(CI->op_begin()+1, CI->op_end()-1), |
| 106 | CI->getName(), CI); |
| 107 | break; |
| 108 | } |
Chris Lattner | 3b66ecb | 2003-12-28 08:19:41 +0000 | [diff] [blame] | 109 | } |
| 110 | |
| 111 | assert(CI->use_empty() && |
| 112 | "Lowering should have eliminated any uses of the intrinsic call!"); |
| 113 | CI->getParent()->getInstList().erase(CI); |
| 114 | } |