| OLD | NEW |
| 1 //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// | 1 //===-- IntrinsicLowering.cpp - Intrinsic Lowering default implementation -===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the IntrinsicLowering class. | 10 // This file implements the IntrinsicLowering class. |
| 11 // | 11 // |
| 12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// |
| 13 | 13 |
| 14 #include "llvm/Constants.h" | 14 #include "llvm/Constants.h" |
| 15 #include "llvm/DerivedTypes.h" | 15 #include "llvm/DerivedTypes.h" |
| 16 #include "llvm/Module.h" | 16 #include "llvm/Module.h" |
| 17 #include "llvm/Type.h" | 17 #include "llvm/Type.h" |
| 18 #include "llvm/CodeGen/IntrinsicLowering.h" | 18 #include "llvm/CodeGen/IntrinsicLowering.h" |
| 19 #include "llvm/Support/CallSite.h" | 19 #include "llvm/Support/CallSite.h" |
| 20 #include "llvm/Support/CommandLine.h" // @LOCALMOD | |
| 21 #include "llvm/Support/ErrorHandling.h" | 20 #include "llvm/Support/ErrorHandling.h" |
| 22 #include "llvm/Support/IRBuilder.h" | 21 #include "llvm/Support/IRBuilder.h" |
| 23 #include "llvm/Support/raw_ostream.h" | 22 #include "llvm/Support/raw_ostream.h" |
| 24 #include "llvm/Target/TargetData.h" | 23 #include "llvm/Target/TargetData.h" |
| 25 #include "llvm/ADT/SmallVector.h" | 24 #include "llvm/ADT/SmallVector.h" |
| 26 using namespace llvm; | 25 using namespace llvm; |
| 27 | 26 |
| 28 // @LOCALMOD-BEGIN | |
| 29 static cl::opt<bool> | |
| 30 AddNaClReadTPDep("add-nacl-read-tp-dependency", | |
| 31 cl::desc("Add __nacl_read_tp dependency to bitcode modules"), | |
| 32 cl::init(false)); | |
| 33 | |
| 34 // We use this when we want to link libgcc as bitcode | |
| 35 static cl::opt<bool> | |
| 36 AddLibgccDeps("add-libgcc-dependencies", | |
| 37 cl::desc("Add libgcc dependencies to bitcode modules"), | |
| 38 cl::init(false)); | |
| 39 // @LOCALMOD-END | |
| 40 | |
| 41 template <class ArgIt> | 27 template <class ArgIt> |
| 42 static void EnsureFunctionExists(Module &M, const char *Name, | 28 static void EnsureFunctionExists(Module &M, const char *Name, |
| 43 ArgIt ArgBegin, ArgIt ArgEnd, | 29 ArgIt ArgBegin, ArgIt ArgEnd, |
| 44 Type *RetTy) { | 30 Type *RetTy) { |
| 45 // Insert a correctly-typed definition now. | 31 // Insert a correctly-typed definition now. |
| 46 std::vector<Type *> ParamTys; | 32 std::vector<Type *> ParamTys; |
| 47 for (ArgIt I = ArgBegin; I != ArgEnd; ++I) | 33 for (ArgIt I = ArgBegin; I != ArgEnd; ++I) |
| 48 ParamTys.push_back(I->getType()); | 34 ParamTys.push_back(I->getType()); |
| 49 M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false)); | 35 M.getOrInsertFunction(Name, FunctionType::get(RetTy, ParamTys, false)); |
| 50 } | 36 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 | 86 |
| 101 // VisualStudio defines setjmp as _setjmp | 87 // VisualStudio defines setjmp as _setjmp |
| 102 #if defined(_MSC_VER) && defined(setjmp) && \ | 88 #if defined(_MSC_VER) && defined(setjmp) && \ |
| 103 !defined(setjmp_undefined_for_msvc) | 89 !defined(setjmp_undefined_for_msvc) |
| 104 # pragma push_macro("setjmp") | 90 # pragma push_macro("setjmp") |
| 105 # undef setjmp | 91 # undef setjmp |
| 106 # define setjmp_undefined_for_msvc | 92 # define setjmp_undefined_for_msvc |
| 107 #endif | 93 #endif |
| 108 | 94 |
| 109 // @LOCALMOD-BEGIN | 95 // @LOCALMOD-BEGIN |
| 110 // NOTE: we are experimenting with the idea of providing libgcc | |
| 111 // in a bitcode (derived) form. If this works out libgcc will not | |
| 112 // differ between platforms anymore, and the list of symbols below will | |
| 113 // be what is guaranteed to be included with libgcc. | |
| 114 // If for some reason a backend needs additional functions | |
| 115 // it would have generated them itself. | |
| 116 // NOTE: llvm bitcode does not preserve signedness of types so the type | |
| 117 // annotation below is simplified: | |
| 118 // s: i32 | |
| 119 // d: i64 | |
| 120 // f: f32 | |
| 121 // F: f64 | |
| 122 // The first letter denotes the return type the remaining one the | |
| 123 // parameter types. | |
| 124 static const struct { const char* name; const char* types; } | |
| 125 LibgccIntrinsicNames[] = { | |
| 126 /* RTLIB::SDIV_I32 */ {"__divsi3", "sss"}, | |
| 127 /* RTLIB::SDIV_I64 */ {"__divdi3", "ddd"}, | |
| 128 | |
| 129 /* RTLIB::UDIV_I32 */ {"__udivsi3", "sss"}, | |
| 130 /* RTLIB::UDIV_I64 */ {"__udivdi3", "ddd"}, | |
| 131 | |
| 132 /* RTLIB::SREM_I32 */ {"__modsi3", "sss"}, | |
| 133 /* RTLIB::SREM_I64 */ {"__moddi3", "ddd"}, | |
| 134 | |
| 135 /* RTLIB::UREM_I32 */ {"__umodsi3", "sss"}, | |
| 136 /* RTLIB::UREM_I64 */ {"__umoddi3", "ddd"}, | |
| 137 | |
| 138 /* RTLIB::FPTOSINT_F32_I32 */ {"__fixsfsi", "sf"}, | |
| 139 /* RTLIB::FPTOSINT_F32_I64 */ {"__fixsfdi", "df"}, | |
| 140 | |
| 141 /* RTLIB::FPTOSINT_F64_I32 */ {"__fixdfsi", "sF"}, | |
| 142 /* RTLIB::FPTOSINT_F64_I64 */ {"__fixdfdi", "dF"}, | |
| 143 | |
| 144 /* RTLIB::FPTOUINT_F32_I32 */ {"__fixunssfsi", "sf"}, | |
| 145 /* RTLIB::FPTOUINT_F32_I64 */ {"__fixunssfdi", "dF"}, | |
| 146 | |
| 147 /* RTLIB::FPTOUINT_F64_I32 */ {"__fixunsdfsi", "sF"}, | |
| 148 /* RTLIB::FPTOUINT_F64_I64 */ {"__fixunsdfdi", "dF"}, | |
| 149 | |
| 150 /* RTLIB::SINTTOFP_I32_F32 */ {"__floatsisf", "fs"}, | |
| 151 /* RTLIB::SINTTOFP_I32_F64 */ {"__floatsidf", "Fs"}, | |
| 152 | |
| 153 /* RTLIB::SINTTOFP_I64_F32 */ {"__floatdisf", "fd"}, | |
| 154 /* RTLIB::SINTTOFP_I64_F64 */ {"__floatdidf", "Fd"}, | |
| 155 | |
| 156 /* RTLIB::UINTTOFP_I32_F32 */ {"__floatunsisf", "fs"}, | |
| 157 /* RTLIB::UINTTOFP_I32_F64 */ {"__floatunsidf", "Fs"}, | |
| 158 | |
| 159 /* RTLIB::UINTTOFP_I64_F32 */ {"__floatundisf", "fd"}, | |
| 160 /* RTLIB::UINTTOFP_I64_F64 */ {"__floatundidf", "Fd"}, | |
| 161 | |
| 162 /* RTLIB::POWI_F32 */ {"__powisf2", "ffs"}, | |
| 163 /* RTLIB::POWI_F64 */ {"__powidf2", "FFs"}, | |
| 164 {NULL, NULL} | |
| 165 }; | |
| 166 | |
| 167 // Calls to these functions may materialize as part of a conversion | 96 // Calls to these functions may materialize as part of a conversion |
| 168 // from an intrinsics, e.g. llvm.memset -> memset | 97 // from an intrinsics, e.g. llvm.memset -> memset |
| 169 // So if these functions are available in bitcode form we need to: | 98 // So if these functions are available in bitcode form we need to: |
| 170 // * make sure they do not get discarded -- if there is a chance that | 99 // * make sure they do not get discarded -- if there is a chance that |
| 171 // a caller might materialize | 100 // a caller might materialize |
| 172 // * make sure they do not get specialized for a given callsite | 101 // * make sure they do not get specialized for a given callsite |
| 173 // Both problems are avoided by pretending there are unknown callers. | 102 // Both problems are avoided by pretending there are unknown callers. |
| 174 // The function: IntrinsicLowering::AddPrototypes() below does just that. | 103 // The function: IntrinsicLowering::AddPrototypes() below does just that. |
| 175 // TODO(robertm): elaborate some more | 104 // TODO(robertm): elaborate some more |
| 176 static const char *MiscIntrinsicNames[] = { | 105 static const char *IntrinsicNames[] = { |
| 177 "abort", | 106 "abort", |
| 178 "memcpy", "memset", "memmove", | 107 "memcpy", "memset", "memmove", |
| 179 "sqrtf", "sqrt", "sqrtl", | 108 "sqrtf", "sqrt", "sqrtl", |
| 180 "sinf", "sin", "sinl", | 109 "sinf", "sin", "sinl", |
| 181 "cosf", "cos", "cosl", | 110 "cosf", "cos", "cosl", |
| 182 "powf", "pow", "powl", | 111 "powf", "pow", "powl", |
| 183 "logf", "log", "logl", | 112 "logf", "log", "logl", |
| 184 "log2f", "log2", "log2l", | 113 "log2f", "log2", "log2l", |
| 185 "log10f", "log10", "log10l", | 114 "log10f", "log10", "log10l", |
| 186 "expf", "exp", "expl", | 115 "expf", "exp", "expl", |
| 187 "exp2f", "exp2", "exp2l", | 116 "exp2f", "exp2", "exp2l", |
| 188 "__nacl_read_tp", | |
| 189 NULL | 117 NULL |
| 190 }; | 118 }; |
| 191 | 119 |
| 192 StringSet<> IntrinsicLowering::FuncNames; | 120 StringSet<> IntrinsicLowering::FuncNames; |
| 193 | 121 |
| 194 const StringSet<> &IntrinsicLowering::GetFuncNames() { | 122 const StringSet<> &IntrinsicLowering::GetFuncNames() { |
| 195 if (FuncNames.empty()) { | 123 if (FuncNames.empty()) { |
| 196 for (unsigned i=0; MiscIntrinsicNames[i]; ++i) | 124 for (unsigned i=0; IntrinsicNames[i]; ++i) |
| 197 FuncNames.insert(MiscIntrinsicNames[i]); | 125 FuncNames.insert(IntrinsicNames[i]); |
| 198 | |
| 199 for (unsigned i=0; LibgccIntrinsicNames[i].name; ++i) | |
| 200 FuncNames.insert(LibgccIntrinsicNames[i].name); | |
| 201 } | 126 } |
| 202 return FuncNames; | 127 return FuncNames; |
| 203 } | 128 } |
| 204 | 129 |
| 205 bool IntrinsicLowering::IsCalledByIntrinsic(const StringRef &FuncName) { | 130 bool IntrinsicLowering::IsCalledByIntrinsic(const StringRef &FuncName) { |
| 206 return IntrinsicLowering::GetFuncNames().count(FuncName) > 0; | 131 return IntrinsicLowering::GetFuncNames().count(FuncName) > 0; |
| 207 } | 132 } |
| 208 // @LOCALMOD-END | 133 // @LOCALMOD-END |
| 209 | 134 |
| 210 void IntrinsicLowering::AddPrototypes(Module &M) { | 135 void IntrinsicLowering::AddPrototypes(Module &M) { |
| 211 LLVMContext &Context = M.getContext(); | 136 LLVMContext &Context = M.getContext(); |
| 212 | |
| 213 // @LOCALMOD-BEGIN | |
| 214 // Calls to __nacl_read_tp may be generated by codegen on X86-64 | |
| 215 // in non-PIC TLS mode. Since __nacl_read_tp exists in a bitcode | |
| 216 // archive, it is necessary to add a dependency to it during | |
| 217 // bitcode linking, so that it gets included in the link. | |
| 218 if (AddNaClReadTPDep) { | |
| 219 Type *RetTy = Type::getInt8PtrTy(Context); | |
| 220 M.getOrInsertFunction("__nacl_read_tp", RetTy, (Type*)0); | |
| 221 } | |
| 222 | |
| 223 // If we link libgcc we need to add a dependency to all its functions | |
| 224 // during bitcode linking, so that they get included in the link. | |
| 225 | |
| 226 if (AddLibgccDeps) { | |
| 227 Type *CharToTypeMap[128]; | |
| 228 for (unsigned i=0; i < 128; ++i) { | |
| 229 CharToTypeMap[i] = 0; | |
| 230 } | |
| 231 CharToTypeMap['f'] = Type::getFloatTy(Context); | |
| 232 CharToTypeMap['F'] = Type::getDoubleTy(Context); | |
| 233 CharToTypeMap['s'] = Type::getInt32Ty(Context); | |
| 234 CharToTypeMap['d'] = Type::getInt64Ty(Context); | |
| 235 | |
| 236 for (unsigned i=0; LibgccIntrinsicNames[i].name; ++i) { | |
| 237 Type *RetTy = 0; | |
| 238 std::vector<Type *> ParamTys; | |
| 239 const char* name = LibgccIntrinsicNames[i].name; | |
| 240 const char* params = LibgccIntrinsicNames[i].types; | |
| 241 for (unsigned j=0; params[j]; ++j) { | |
| 242 Type *Current = CharToTypeMap[params[j]]; | |
| 243 assert (Current != 0); | |
| 244 if (j == 0) { | |
| 245 RetTy = Current; | |
| 246 } else { | |
| 247 ParamTys.push_back(Current); | |
| 248 } | |
| 249 } | |
| 250 M.getOrInsertFunction(name, FunctionType::get(RetTy, | |
| 251 makeArrayRef(ParamTys), | |
| 252 false)); | |
| 253 } | |
| 254 } | |
| 255 // @LOCALMOD-END | |
| 256 | |
| 257 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) | 137 for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) |
| 258 if (I->isDeclaration() && !I->use_empty()) | 138 if (I->isDeclaration() && !I->use_empty()) |
| 259 switch (I->getIntrinsicID()) { | 139 switch (I->getIntrinsicID()) { |
| 260 default: break; | 140 default: break; |
| 261 case Intrinsic::setjmp: | 141 case Intrinsic::setjmp: |
| 262 EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), | 142 EnsureFunctionExists(M, "setjmp", I->arg_begin(), I->arg_end(), |
| 263 Type::getInt32Ty(M.getContext())); | 143 Type::getInt32Ty(M.getContext())); |
| 264 break; | 144 break; |
| 265 case Intrinsic::longjmp: | 145 case Intrinsic::longjmp: |
| 266 EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(), | 146 EnsureFunctionExists(M, "longjmp", I->arg_begin(), I->arg_end(), |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 Module *M = CI->getParent()->getParent()->getParent(); | 601 Module *M = CI->getParent()->getParent()->getParent(); |
| 722 Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty); | 602 Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Ty); |
| 723 | 603 |
| 724 Value *Op = CI->getArgOperand(0); | 604 Value *Op = CI->getArgOperand(0); |
| 725 Op = CallInst::Create(Int, Op, CI->getName(), CI); | 605 Op = CallInst::Create(Int, Op, CI->getName(), CI); |
| 726 | 606 |
| 727 CI->replaceAllUsesWith(Op); | 607 CI->replaceAllUsesWith(Op); |
| 728 CI->eraseFromParent(); | 608 CI->eraseFromParent(); |
| 729 return true; | 609 return true; |
| 730 } | 610 } |
| OLD | NEW |