| Anders Carlsson | 022012e | 2007-08-20 18:05:56 +0000 | [diff] [blame] | 1 | //===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
| Chris Lattner | 0bc735f | 2007-12-29 19:59:25 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
| Anders Carlsson | 022012e | 2007-08-20 18:05:56 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This contains code to emit Builtin calls as LLVM code. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
 | 14 | #include "CodeGenFunction.h" | 
 | 15 | #include "CodeGenModule.h" | 
| Anders Carlsson | ca6fcfa | 2007-12-09 21:20:04 +0000 | [diff] [blame] | 16 | #include "clang/Basic/TargetInfo.h" | 
| Chris Lattner | 1f32999 | 2008-10-06 06:09:18 +0000 | [diff] [blame] | 17 | #include "clang/AST/APValue.h" | 
| Chris Lattner | bef20ac | 2007-08-31 04:31:45 +0000 | [diff] [blame] | 18 | #include "clang/AST/ASTContext.h" | 
| Daniel Dunbar | c4a1dea | 2008-08-11 05:35:13 +0000 | [diff] [blame] | 19 | #include "clang/AST/Decl.h" | 
| Chris Lattner | 6b15cdc | 2009-06-14 01:05:48 +0000 | [diff] [blame] | 20 | #include "clang/Basic/TargetBuiltins.h" | 
| Anders Carlsson | 793680e | 2007-10-12 23:56:29 +0000 | [diff] [blame] | 21 | #include "llvm/Intrinsics.h" | 
| Anders Carlsson | 022012e | 2007-08-20 18:05:56 +0000 | [diff] [blame] | 22 | using namespace clang; | 
 | 23 | using namespace CodeGen; | 
| Anders Carlsson | ca6fcfa | 2007-12-09 21:20:04 +0000 | [diff] [blame] | 24 | using namespace llvm; | 
 | 25 |  | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 26 | /// Utility to insert an atomic instruction based on Instrinsic::ID | 
 | 27 | /// and the expression node. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 28 | static RValue EmitBinaryAtomic(CodeGenFunction& CGF, | 
| Mon P Wang | 1ffe281 | 2008-05-09 22:40:52 +0000 | [diff] [blame] | 29 |                                Intrinsic::ID Id, const CallExpr *E) { | 
| Mon P Wang | c500451 | 2008-07-31 03:28:23 +0000 | [diff] [blame] | 30 |   const llvm::Type *ResType[2]; | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 31 |   ResType[0] = CGF.ConvertType(E->getType()); | 
 | 32 |   ResType[1] = CGF.ConvertType(E->getArg(0)->getType()); | 
 | 33 |   Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 34 |   return RValue::get(CGF.Builder.CreateCall2(AtomF, | 
 | 35 |                                              CGF.EmitScalarExpr(E->getArg(0)), | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 36 |                                              CGF.EmitScalarExpr(E->getArg(1)))); | 
 | 37 | } | 
 | 38 |  | 
 | 39 | /// Utility to insert an atomic instruction based Instrinsic::ID and | 
 | 40 | // the expression node, where the return value is the result of the | 
 | 41 | // operation. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 42 | static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF, | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 43 |                                    Intrinsic::ID Id, const CallExpr *E, | 
 | 44 |                                    Instruction::BinaryOps Op) { | 
 | 45 |   const llvm::Type *ResType[2]; | 
 | 46 |   ResType[0] = CGF.ConvertType(E->getType()); | 
 | 47 |   ResType[1] = CGF.ConvertType(E->getArg(0)->getType()); | 
 | 48 |   Value *AtomF = CGF.CGM.getIntrinsic(Id, ResType, 2); | 
 | 49 |   Value *Ptr = CGF.EmitScalarExpr(E->getArg(0)); | 
 | 50 |   Value *Operand = CGF.EmitScalarExpr(E->getArg(1)); | 
 | 51 |   Value *Result = CGF.Builder.CreateCall2(AtomF, Ptr, Operand); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 52 |  | 
| Chris Lattner | eebd9d2 | 2009-05-13 04:37:52 +0000 | [diff] [blame] | 53 |   if (Id == Intrinsic::atomic_load_nand) | 
 | 54 |     Result = CGF.Builder.CreateNot(Result); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 55 |  | 
 | 56 |  | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 57 |   return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand)); | 
| Mon P Wang | 1ffe281 | 2008-05-09 22:40:52 +0000 | [diff] [blame] | 58 | } | 
 | 59 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 60 | RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 61 |                                         unsigned BuiltinID, const CallExpr *E) { | 
| Chris Lattner | 564ea2a | 2008-10-06 06:56:41 +0000 | [diff] [blame] | 62 |   // See if we can constant fold this builtin.  If so, don't emit it at all. | 
| Anders Carlsson | f35d35a | 2008-12-01 02:31:41 +0000 | [diff] [blame] | 63 |   Expr::EvalResult Result; | 
| Chris Lattner | 6ee7aa1 | 2008-11-16 21:24:15 +0000 | [diff] [blame] | 64 |   if (E->Evaluate(Result, CGM.getContext())) { | 
| Anders Carlsson | f35d35a | 2008-12-01 02:31:41 +0000 | [diff] [blame] | 65 |     if (Result.Val.isInt()) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 66 |       return RValue::get(llvm::ConstantInt::get(VMContext, | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 67 |                                                 Result.Val.getInt())); | 
| Eli Friedman | 3941b18 | 2009-01-25 01:54:01 +0000 | [diff] [blame] | 68 |     else if (Result.Val.isFloat()) | 
| Owen Anderson | bc0a222 | 2009-07-27 21:00:51 +0000 | [diff] [blame] | 69 |       return RValue::get(ConstantFP::get(VMContext, Result.Val.getFloat())); | 
| Chris Lattner | 1f32999 | 2008-10-06 06:09:18 +0000 | [diff] [blame] | 70 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 71 |  | 
| Chris Lattner | 564ea2a | 2008-10-06 06:56:41 +0000 | [diff] [blame] | 72 |   switch (BuiltinID) { | 
 | 73 |   default: break;  // Handle intrinsics and libm functions below. | 
| Chris Lattner | 506ff88 | 2008-10-06 07:26:43 +0000 | [diff] [blame] | 74 |   case Builtin::BI__builtin___CFStringMakeConstantString: | 
| Anders Carlsson | e9352cc | 2009-04-08 04:48:15 +0000 | [diff] [blame] | 75 |     return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0)); | 
| Chris Lattner | 6a705f0 | 2008-07-09 17:28:44 +0000 | [diff] [blame] | 76 |   case Builtin::BI__builtin_stdarg_start: | 
| Anders Carlsson | 793680e | 2007-10-12 23:56:29 +0000 | [diff] [blame] | 77 |   case Builtin::BI__builtin_va_start: | 
 | 78 |   case Builtin::BI__builtin_va_end: { | 
| Daniel Dunbar | 0785570 | 2009-02-11 22:25:55 +0000 | [diff] [blame] | 79 |     Value *ArgValue = EmitVAListRef(E->getArg(0)); | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 80 |     const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); | 
| Anders Carlsson | 793680e | 2007-10-12 23:56:29 +0000 | [diff] [blame] | 81 |     if (ArgValue->getType() != DestType) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 82 |       ArgValue = Builder.CreateBitCast(ArgValue, DestType, | 
| Daniel Dunbar | b27ffbe | 2009-07-26 09:28:40 +0000 | [diff] [blame] | 83 |                                        ArgValue->getName().data()); | 
| Anders Carlsson | 793680e | 2007-10-12 23:56:29 +0000 | [diff] [blame] | 84 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 85 |     Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ? | 
| Chris Lattner | 6a705f0 | 2008-07-09 17:28:44 +0000 | [diff] [blame] | 86 |       Intrinsic::vaend : Intrinsic::vastart; | 
| Chris Lattner | 7acda7c | 2007-12-18 00:25:38 +0000 | [diff] [blame] | 87 |     return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue)); | 
| Anders Carlsson | 793680e | 2007-10-12 23:56:29 +0000 | [diff] [blame] | 88 |   } | 
| Anders Carlsson | a28ef8b | 2008-02-09 20:26:43 +0000 | [diff] [blame] | 89 |   case Builtin::BI__builtin_va_copy: { | 
| Eli Friedman | 4fd0aa5 | 2009-01-20 17:46:04 +0000 | [diff] [blame] | 90 |     Value *DstPtr = EmitVAListRef(E->getArg(0)); | 
 | 91 |     Value *SrcPtr = EmitVAListRef(E->getArg(1)); | 
| Anders Carlsson | a28ef8b | 2008-02-09 20:26:43 +0000 | [diff] [blame] | 92 |  | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 93 |     const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext); | 
| Anders Carlsson | a28ef8b | 2008-02-09 20:26:43 +0000 | [diff] [blame] | 94 |  | 
 | 95 |     DstPtr = Builder.CreateBitCast(DstPtr, Type); | 
 | 96 |     SrcPtr = Builder.CreateBitCast(SrcPtr, Type); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 97 |     return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy), | 
| Chris Lattner | 3eae03e | 2008-05-06 00:56:42 +0000 | [diff] [blame] | 98 |                                            DstPtr, SrcPtr)); | 
| Anders Carlsson | a28ef8b | 2008-02-09 20:26:43 +0000 | [diff] [blame] | 99 |   } | 
| Anders Carlsson | c2251dc | 2007-11-20 19:05:17 +0000 | [diff] [blame] | 100 |   case Builtin::BI__builtin_abs: { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 101 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
 | 102 |  | 
| Chris Lattner | 9a847f5 | 2008-07-23 06:53:34 +0000 | [diff] [blame] | 103 |     Value *NegOp = Builder.CreateNeg(ArgValue, "neg"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 104 |     Value *CmpResult = | 
 | 105 |     Builder.CreateICmpSGE(ArgValue, | 
| Owen Anderson | c9c88b4 | 2009-07-31 20:28:54 +0000 | [diff] [blame] | 106 |                           llvm::Constant::getNullValue(ArgValue->getType()), | 
| Chris Lattner | 9a847f5 | 2008-07-23 06:53:34 +0000 | [diff] [blame] | 107 |                                                             "abscond"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 108 |     Value *Result = | 
| Anders Carlsson | c2251dc | 2007-11-20 19:05:17 +0000 | [diff] [blame] | 109 |       Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 110 |  | 
| Anders Carlsson | c2251dc | 2007-11-20 19:05:17 +0000 | [diff] [blame] | 111 |     return RValue::get(Result); | 
 | 112 |   } | 
| Anders Carlsson | 3a31d60 | 2008-02-06 07:19:27 +0000 | [diff] [blame] | 113 |   case Builtin::BI__builtin_ctz: | 
 | 114 |   case Builtin::BI__builtin_ctzl: | 
 | 115 |   case Builtin::BI__builtin_ctzll: { | 
 | 116 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 117 |  | 
| Anders Carlsson | 3a31d60 | 2008-02-06 07:19:27 +0000 | [diff] [blame] | 118 |     const llvm::Type *ArgType = ArgValue->getType(); | 
 | 119 |     Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); | 
 | 120 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 121 |     const llvm::Type *ResultType = ConvertType(E->getType()); | 
| Anders Carlsson | 3a31d60 | 2008-02-06 07:19:27 +0000 | [diff] [blame] | 122 |     Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); | 
 | 123 |     if (Result->getType() != ResultType) | 
| Duncan Sands | eac73e5 | 2009-11-16 13:11:21 +0000 | [diff] [blame] | 124 |       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, | 
 | 125 |                                      "cast"); | 
| Anders Carlsson | 3a31d60 | 2008-02-06 07:19:27 +0000 | [diff] [blame] | 126 |     return RValue::get(Result); | 
 | 127 |   } | 
| Eli Friedman | f4e8533 | 2008-05-27 15:32:46 +0000 | [diff] [blame] | 128 |   case Builtin::BI__builtin_clz: | 
 | 129 |   case Builtin::BI__builtin_clzl: | 
 | 130 |   case Builtin::BI__builtin_clzll: { | 
 | 131 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 132 |  | 
| Eli Friedman | f4e8533 | 2008-05-27 15:32:46 +0000 | [diff] [blame] | 133 |     const llvm::Type *ArgType = ArgValue->getType(); | 
 | 134 |     Value *F = CGM.getIntrinsic(Intrinsic::ctlz, &ArgType, 1); | 
 | 135 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 136 |     const llvm::Type *ResultType = ConvertType(E->getType()); | 
| Eli Friedman | f4e8533 | 2008-05-27 15:32:46 +0000 | [diff] [blame] | 137 |     Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); | 
 | 138 |     if (Result->getType() != ResultType) | 
| Duncan Sands | eac73e5 | 2009-11-16 13:11:21 +0000 | [diff] [blame] | 139 |       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, | 
 | 140 |                                      "cast"); | 
| Eli Friedman | f4e8533 | 2008-05-27 15:32:46 +0000 | [diff] [blame] | 141 |     return RValue::get(Result); | 
 | 142 |   } | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 143 |   case Builtin::BI__builtin_ffs: | 
 | 144 |   case Builtin::BI__builtin_ffsl: | 
 | 145 |   case Builtin::BI__builtin_ffsll: { | 
 | 146 |     // ffs(x) -> x ? cttz(x) + 1 : 0 | 
 | 147 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 148 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 149 |     const llvm::Type *ArgType = ArgValue->getType(); | 
 | 150 |     Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 151 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 152 |     const llvm::Type *ResultType = ConvertType(E->getType()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 153 |     Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"), | 
| Owen Anderson | 4a28d5d | 2009-07-24 23:12:58 +0000 | [diff] [blame] | 154 |                                    llvm::ConstantInt::get(ArgType, 1), "tmp"); | 
| Owen Anderson | c9c88b4 | 2009-07-31 20:28:54 +0000 | [diff] [blame] | 155 |     Value *Zero = llvm::Constant::getNullValue(ArgType); | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 156 |     Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero"); | 
 | 157 |     Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs"); | 
 | 158 |     if (Result->getType() != ResultType) | 
| Duncan Sands | eac73e5 | 2009-11-16 13:11:21 +0000 | [diff] [blame] | 159 |       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, | 
 | 160 |                                      "cast"); | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 161 |     return RValue::get(Result); | 
 | 162 |   } | 
 | 163 |   case Builtin::BI__builtin_parity: | 
 | 164 |   case Builtin::BI__builtin_parityl: | 
 | 165 |   case Builtin::BI__builtin_parityll: { | 
 | 166 |     // parity(x) -> ctpop(x) & 1 | 
 | 167 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 168 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 169 |     const llvm::Type *ArgType = ArgValue->getType(); | 
 | 170 |     Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 171 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 172 |     const llvm::Type *ResultType = ConvertType(E->getType()); | 
 | 173 |     Value *Tmp = Builder.CreateCall(F, ArgValue, "tmp"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 174 |     Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1), | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 175 |                                       "tmp"); | 
 | 176 |     if (Result->getType() != ResultType) | 
| Duncan Sands | eac73e5 | 2009-11-16 13:11:21 +0000 | [diff] [blame] | 177 |       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, | 
 | 178 |                                      "cast"); | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 179 |     return RValue::get(Result); | 
 | 180 |   } | 
 | 181 |   case Builtin::BI__builtin_popcount: | 
 | 182 |   case Builtin::BI__builtin_popcountl: | 
 | 183 |   case Builtin::BI__builtin_popcountll: { | 
 | 184 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 185 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 186 |     const llvm::Type *ArgType = ArgValue->getType(); | 
 | 187 |     Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 188 |  | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 189 |     const llvm::Type *ResultType = ConvertType(E->getType()); | 
 | 190 |     Value *Result = Builder.CreateCall(F, ArgValue, "tmp"); | 
 | 191 |     if (Result->getType() != ResultType) | 
| Duncan Sands | eac73e5 | 2009-11-16 13:11:21 +0000 | [diff] [blame] | 192 |       Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, | 
 | 193 |                                      "cast"); | 
| Daniel Dunbar | 04b2900 | 2008-07-21 17:19:41 +0000 | [diff] [blame] | 194 |     return RValue::get(Result); | 
 | 195 |   } | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 196 |   case Builtin::BI__builtin_expect: | 
| Daniel Dunbar | a933c3c | 2008-07-21 18:44:41 +0000 | [diff] [blame] | 197 |     // FIXME: pass expect through to LLVM | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 198 |     return RValue::get(EmitScalarExpr(E->getArg(0))); | 
| Anders Carlsson | df4852a | 2007-12-02 21:58:10 +0000 | [diff] [blame] | 199 |   case Builtin::BI__builtin_bswap32: | 
 | 200 |   case Builtin::BI__builtin_bswap64: { | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 201 |     Value *ArgValue = EmitScalarExpr(E->getArg(0)); | 
| Anders Carlsson | df4852a | 2007-12-02 21:58:10 +0000 | [diff] [blame] | 202 |     const llvm::Type *ArgType = ArgValue->getType(); | 
| Chris Lattner | 7acda7c | 2007-12-18 00:25:38 +0000 | [diff] [blame] | 203 |     Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1); | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 204 |     return RValue::get(Builder.CreateCall(F, ArgValue, "tmp")); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 205 |   } | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 206 |   case Builtin::BI__builtin_object_size: { | 
| Mike Stump | b16d32f | 2009-10-26 23:39:48 +0000 | [diff] [blame] | 207 |     // We pass this builtin onto the optimizer so that it can | 
 | 208 |     // figure out the object size in more complex cases. | 
| Mike Stump | c4c9045 | 2009-10-27 22:09:17 +0000 | [diff] [blame] | 209 |     const llvm::Type *ResType[] = { | 
 | 210 |       ConvertType(E->getType()) | 
 | 211 |     }; | 
| Eric Christopher | fee667f | 2009-12-23 03:49:37 +0000 | [diff] [blame] | 212 |      | 
 | 213 |     // LLVM only supports 0 and 2, make sure that we pass along that | 
 | 214 |     // as a boolean. | 
 | 215 |     Value *Ty = EmitScalarExpr(E->getArg(1)); | 
 | 216 |     ConstantInt *CI = dyn_cast<ConstantInt>(Ty); | 
 | 217 |     assert(CI); | 
 | 218 |     uint64_t val = CI->getZExtValue(); | 
 | 219 |     CI = ConstantInt::get(llvm::Type::getInt1Ty(VMContext), (val & 0x2) >> 1);     | 
 | 220 |      | 
| Mike Stump | c4c9045 | 2009-10-27 22:09:17 +0000 | [diff] [blame] | 221 |     Value *F = CGM.getIntrinsic(Intrinsic::objectsize, ResType, 1); | 
 | 222 |     return RValue::get(Builder.CreateCall2(F, | 
 | 223 |                                            EmitScalarExpr(E->getArg(0)), | 
| Eric Christopher | fee667f | 2009-12-23 03:49:37 +0000 | [diff] [blame] | 224 |                                            CI)); | 
| Daniel Dunbar | d5f8a4f | 2008-09-03 21:13:56 +0000 | [diff] [blame] | 225 |   } | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 226 |   case Builtin::BI__builtin_prefetch: { | 
 | 227 |     Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0)); | 
 | 228 |     // FIXME: Technically these constants should of type 'int', yes? | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 229 |     RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) : | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 230 |       llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 231 |     Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) : | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 232 |       llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 3); | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 233 |     Value *F = CGM.getIntrinsic(Intrinsic::prefetch, 0, 0); | 
 | 234 |     return RValue::get(Builder.CreateCall3(F, Address, RW, Locality)); | 
| Anders Carlsson | df4852a | 2007-12-02 21:58:10 +0000 | [diff] [blame] | 235 |   } | 
| Daniel Dunbar | 4493f79 | 2008-07-21 22:59:13 +0000 | [diff] [blame] | 236 |   case Builtin::BI__builtin_trap: { | 
 | 237 |     Value *F = CGM.getIntrinsic(Intrinsic::trap, 0, 0); | 
 | 238 |     return RValue::get(Builder.CreateCall(F)); | 
 | 239 |   } | 
| Chris Lattner | 21190d5 | 2009-09-21 03:09:59 +0000 | [diff] [blame] | 240 |   case Builtin::BI__builtin_unreachable: { | 
| Mike Stump | fba565d | 2009-12-16 03:07:12 +0000 | [diff] [blame] | 241 |     if (CatchUndefined && HaveInsertPoint()) | 
 | 242 |       EmitBranch(getTrapBB()); | 
| Chris Lattner | 21190d5 | 2009-09-21 03:09:59 +0000 | [diff] [blame] | 243 |     Value *V = Builder.CreateUnreachable(); | 
 | 244 |     Builder.ClearInsertionPoint(); | 
 | 245 |     return RValue::get(V); | 
 | 246 |   } | 
 | 247 |        | 
| Daniel Dunbar | a933c3c | 2008-07-21 18:44:41 +0000 | [diff] [blame] | 248 |   case Builtin::BI__builtin_powi: | 
 | 249 |   case Builtin::BI__builtin_powif: | 
 | 250 |   case Builtin::BI__builtin_powil: { | 
 | 251 |     Value *Base = EmitScalarExpr(E->getArg(0)); | 
 | 252 |     Value *Exponent = EmitScalarExpr(E->getArg(1)); | 
| Daniel Dunbar | a933c3c | 2008-07-21 18:44:41 +0000 | [diff] [blame] | 253 |     const llvm::Type *ArgType = Base->getType(); | 
 | 254 |     Value *F = CGM.getIntrinsic(Intrinsic::powi, &ArgType, 1); | 
| Daniel Dunbar | a933c3c | 2008-07-21 18:44:41 +0000 | [diff] [blame] | 255 |     return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); | 
 | 256 |   } | 
 | 257 |  | 
| Chris Lattner | fe23e21 | 2007-12-20 00:44:32 +0000 | [diff] [blame] | 258 |   case Builtin::BI__builtin_isgreater: | 
 | 259 |   case Builtin::BI__builtin_isgreaterequal: | 
 | 260 |   case Builtin::BI__builtin_isless: | 
 | 261 |   case Builtin::BI__builtin_islessequal: | 
 | 262 |   case Builtin::BI__builtin_islessgreater: | 
 | 263 |   case Builtin::BI__builtin_isunordered: { | 
 | 264 |     // Ordered comparisons: we know the arguments to these are matching scalar | 
 | 265 |     // floating point values. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 266 |     Value *LHS = EmitScalarExpr(E->getArg(0)); | 
| Chris Lattner | fe23e21 | 2007-12-20 00:44:32 +0000 | [diff] [blame] | 267 |     Value *RHS = EmitScalarExpr(E->getArg(1)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 268 |  | 
| Chris Lattner | fe23e21 | 2007-12-20 00:44:32 +0000 | [diff] [blame] | 269 |     switch (BuiltinID) { | 
 | 270 |     default: assert(0 && "Unknown ordered comparison"); | 
 | 271 |     case Builtin::BI__builtin_isgreater: | 
 | 272 |       LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp"); | 
 | 273 |       break; | 
 | 274 |     case Builtin::BI__builtin_isgreaterequal: | 
 | 275 |       LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp"); | 
 | 276 |       break; | 
 | 277 |     case Builtin::BI__builtin_isless: | 
 | 278 |       LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp"); | 
 | 279 |       break; | 
 | 280 |     case Builtin::BI__builtin_islessequal: | 
 | 281 |       LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp"); | 
 | 282 |       break; | 
 | 283 |     case Builtin::BI__builtin_islessgreater: | 
 | 284 |       LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp"); | 
 | 285 |       break; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 286 |     case Builtin::BI__builtin_isunordered: | 
| Chris Lattner | fe23e21 | 2007-12-20 00:44:32 +0000 | [diff] [blame] | 287 |       LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp"); | 
 | 288 |       break; | 
 | 289 |     } | 
 | 290 |     // ZExt bool to int type. | 
 | 291 |     return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()), | 
 | 292 |                                           "tmp")); | 
 | 293 |   } | 
| Eli Friedman | d613989 | 2009-09-01 04:19:44 +0000 | [diff] [blame] | 294 |   case Builtin::BI__builtin_isnan: { | 
 | 295 |     Value *V = EmitScalarExpr(E->getArg(0)); | 
 | 296 |     V = Builder.CreateFCmpUNO(V, V, "cmp"); | 
 | 297 |     return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp")); | 
 | 298 |   } | 
| Eli Friedman | b52fe9c | 2009-06-02 07:10:30 +0000 | [diff] [blame] | 299 |   case Builtin::BIalloca: | 
| Chris Lattner | 9e800e3 | 2008-06-16 17:15:14 +0000 | [diff] [blame] | 300 |   case Builtin::BI__builtin_alloca: { | 
 | 301 |     // FIXME: LLVM IR Should allow alloca with an i64 size! | 
 | 302 |     Value *Size = EmitScalarExpr(E->getArg(0)); | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 303 |     Size = Builder.CreateIntCast(Size, llvm::Type::getInt32Ty(VMContext), false, "tmp"); | 
 | 304 |     return RValue::get(Builder.CreateAlloca(llvm::Type::getInt8Ty(VMContext), Size, "tmp")); | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 305 |   } | 
 | 306 |   case Builtin::BI__builtin_bzero: { | 
 | 307 |     Value *Address = EmitScalarExpr(E->getArg(0)); | 
 | 308 |     Builder.CreateCall4(CGM.getMemSetFn(), Address, | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 309 |                         llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0), | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 310 |                         EmitScalarExpr(E->getArg(1)), | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 311 |                         llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 312 |     return RValue::get(Address); | 
| Chris Lattner | 9e800e3 | 2008-06-16 17:15:14 +0000 | [diff] [blame] | 313 |   } | 
| Eli Friedman | e6ec205 | 2009-12-17 00:14:28 +0000 | [diff] [blame] | 314 |   case Builtin::BImemcpy: | 
| Eli Friedman | d4b32e4 | 2008-05-19 23:27:48 +0000 | [diff] [blame] | 315 |   case Builtin::BI__builtin_memcpy: { | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 316 |     Value *Address = EmitScalarExpr(E->getArg(0)); | 
 | 317 |     Builder.CreateCall4(CGM.getMemCpyFn(), Address, | 
 | 318 |                         EmitScalarExpr(E->getArg(1)), | 
 | 319 |                         EmitScalarExpr(E->getArg(2)), | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 320 |                         llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 321 |     return RValue::get(Address); | 
 | 322 |   } | 
| Eli Friedman | e6ec205 | 2009-12-17 00:14:28 +0000 | [diff] [blame] | 323 |   case Builtin::BImemmove: | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 324 |   case Builtin::BI__builtin_memmove: { | 
 | 325 |     Value *Address = EmitScalarExpr(E->getArg(0)); | 
 | 326 |     Builder.CreateCall4(CGM.getMemMoveFn(), Address, | 
 | 327 |                         EmitScalarExpr(E->getArg(1)), | 
 | 328 |                         EmitScalarExpr(E->getArg(2)), | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 329 |                         llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 330 |     return RValue::get(Address); | 
 | 331 |   } | 
| Eli Friedman | e6ec205 | 2009-12-17 00:14:28 +0000 | [diff] [blame] | 332 |   case Builtin::BImemset: | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 333 |   case Builtin::BI__builtin_memset: { | 
 | 334 |     Value *Address = EmitScalarExpr(E->getArg(0)); | 
 | 335 |     Builder.CreateCall4(CGM.getMemSetFn(), Address, | 
| Daniel Dunbar | 62c29c6 | 2009-02-16 21:52:05 +0000 | [diff] [blame] | 336 |                         Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 337 |                                             llvm::Type::getInt8Ty(VMContext)), | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 338 |                         EmitScalarExpr(E->getArg(2)), | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 339 |                         llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1)); | 
| Daniel Dunbar | 1caae95 | 2008-07-22 00:26:45 +0000 | [diff] [blame] | 340 |     return RValue::get(Address); | 
| Eli Friedman | d4b32e4 | 2008-05-19 23:27:48 +0000 | [diff] [blame] | 341 |   } | 
| Eli Friedman | 256f77e | 2008-05-20 08:59:34 +0000 | [diff] [blame] | 342 |   case Builtin::BI__builtin_return_address: { | 
 | 343 |     Value *F = CGM.getIntrinsic(Intrinsic::returnaddress, 0, 0); | 
 | 344 |     return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0)))); | 
 | 345 |   } | 
 | 346 |   case Builtin::BI__builtin_frame_address: { | 
 | 347 |     Value *F = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0); | 
 | 348 |     return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0)))); | 
 | 349 |   } | 
| Eli Friedman | 3b660ef | 2009-05-03 19:23:23 +0000 | [diff] [blame] | 350 |   case Builtin::BI__builtin_extract_return_addr: { | 
 | 351 |     // FIXME: There should be a target hook for this | 
 | 352 |     return RValue::get(EmitScalarExpr(E->getArg(0))); | 
 | 353 |   } | 
| Eli Friedman | a6d75c0 | 2009-06-02 09:37:50 +0000 | [diff] [blame] | 354 |   case Builtin::BI__builtin_unwind_init: { | 
 | 355 |     Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init, 0, 0); | 
 | 356 |     return RValue::get(Builder.CreateCall(F)); | 
 | 357 |   } | 
 | 358 | #if 0 | 
 | 359 |   // FIXME: Finish/enable when LLVM backend support stabilizes | 
 | 360 |   case Builtin::BI__builtin_setjmp: { | 
 | 361 |     Value *Buf = EmitScalarExpr(E->getArg(0)); | 
 | 362 |     // Store the frame pointer to the buffer | 
 | 363 |     Value *FrameAddrF = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0); | 
 | 364 |     Value *FrameAddr = | 
 | 365 |         Builder.CreateCall(FrameAddrF, | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 366 |                            Constant::getNullValue(llvm::Type::getInt32Ty(VMContext))); | 
| Eli Friedman | a6d75c0 | 2009-06-02 09:37:50 +0000 | [diff] [blame] | 367 |     Builder.CreateStore(FrameAddr, Buf); | 
 | 368 |     // Call the setjmp intrinsic | 
 | 369 |     Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp, 0, 0); | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 370 |     const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); | 
| Eli Friedman | a6d75c0 | 2009-06-02 09:37:50 +0000 | [diff] [blame] | 371 |     Buf = Builder.CreateBitCast(Buf, DestType); | 
 | 372 |     return RValue::get(Builder.CreateCall(F, Buf)); | 
 | 373 |   } | 
 | 374 |   case Builtin::BI__builtin_longjmp: { | 
 | 375 |     Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp, 0, 0); | 
 | 376 |     Value *Buf = EmitScalarExpr(E->getArg(0)); | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 377 |     const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); | 
| Eli Friedman | a6d75c0 | 2009-06-02 09:37:50 +0000 | [diff] [blame] | 378 |     Buf = Builder.CreateBitCast(Buf, DestType); | 
 | 379 |     return RValue::get(Builder.CreateCall(F, Buf)); | 
 | 380 |   } | 
 | 381 | #endif | 
| Mon P Wang | 1ffe281 | 2008-05-09 22:40:52 +0000 | [diff] [blame] | 382 |   case Builtin::BI__sync_fetch_and_add: | 
| Mon P Wang | 1ffe281 | 2008-05-09 22:40:52 +0000 | [diff] [blame] | 383 |   case Builtin::BI__sync_fetch_and_sub: | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 384 |   case Builtin::BI__sync_fetch_and_or: | 
 | 385 |   case Builtin::BI__sync_fetch_and_and: | 
 | 386 |   case Builtin::BI__sync_fetch_and_xor: | 
 | 387 |   case Builtin::BI__sync_add_and_fetch: | 
 | 388 |   case Builtin::BI__sync_sub_and_fetch: | 
 | 389 |   case Builtin::BI__sync_and_and_fetch: | 
 | 390 |   case Builtin::BI__sync_or_and_fetch: | 
 | 391 |   case Builtin::BI__sync_xor_and_fetch: | 
 | 392 |   case Builtin::BI__sync_val_compare_and_swap: | 
 | 393 |   case Builtin::BI__sync_bool_compare_and_swap: | 
 | 394 |   case Builtin::BI__sync_lock_test_and_set: | 
 | 395 |   case Builtin::BI__sync_lock_release: | 
 | 396 |     assert(0 && "Shouldn't make it through sema"); | 
 | 397 |   case Builtin::BI__sync_fetch_and_add_1: | 
 | 398 |   case Builtin::BI__sync_fetch_and_add_2: | 
 | 399 |   case Builtin::BI__sync_fetch_and_add_4: | 
 | 400 |   case Builtin::BI__sync_fetch_and_add_8: | 
 | 401 |   case Builtin::BI__sync_fetch_and_add_16: | 
 | 402 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_add, E); | 
 | 403 |   case Builtin::BI__sync_fetch_and_sub_1: | 
 | 404 |   case Builtin::BI__sync_fetch_and_sub_2: | 
 | 405 |   case Builtin::BI__sync_fetch_and_sub_4: | 
 | 406 |   case Builtin::BI__sync_fetch_and_sub_8: | 
 | 407 |   case Builtin::BI__sync_fetch_and_sub_16: | 
| Mon P Wang | 09b6bf5 | 2008-06-25 08:21:36 +0000 | [diff] [blame] | 408 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_sub, E); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 409 |   case Builtin::BI__sync_fetch_and_or_1: | 
 | 410 |   case Builtin::BI__sync_fetch_and_or_2: | 
 | 411 |   case Builtin::BI__sync_fetch_and_or_4: | 
 | 412 |   case Builtin::BI__sync_fetch_and_or_8: | 
 | 413 |   case Builtin::BI__sync_fetch_and_or_16: | 
 | 414 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_or, E); | 
 | 415 |   case Builtin::BI__sync_fetch_and_and_1: | 
 | 416 |   case Builtin::BI__sync_fetch_and_and_2: | 
 | 417 |   case Builtin::BI__sync_fetch_and_and_4: | 
 | 418 |   case Builtin::BI__sync_fetch_and_and_8: | 
 | 419 |   case Builtin::BI__sync_fetch_and_and_16: | 
 | 420 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_and, E); | 
 | 421 |   case Builtin::BI__sync_fetch_and_xor_1: | 
 | 422 |   case Builtin::BI__sync_fetch_and_xor_2: | 
 | 423 |   case Builtin::BI__sync_fetch_and_xor_4: | 
 | 424 |   case Builtin::BI__sync_fetch_and_xor_8: | 
 | 425 |   case Builtin::BI__sync_fetch_and_xor_16: | 
 | 426 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_xor, E); | 
| Chris Lattner | eebd9d2 | 2009-05-13 04:37:52 +0000 | [diff] [blame] | 427 |   case Builtin::BI__sync_fetch_and_nand_1: | 
 | 428 |   case Builtin::BI__sync_fetch_and_nand_2: | 
 | 429 |   case Builtin::BI__sync_fetch_and_nand_4: | 
 | 430 |   case Builtin::BI__sync_fetch_and_nand_8: | 
 | 431 |   case Builtin::BI__sync_fetch_and_nand_16: | 
 | 432 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_nand, E); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 433 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 434 |   // Clang extensions: not overloaded yet. | 
| Mon P Wang | 1ffe281 | 2008-05-09 22:40:52 +0000 | [diff] [blame] | 435 |   case Builtin::BI__sync_fetch_and_min: | 
 | 436 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E); | 
 | 437 |   case Builtin::BI__sync_fetch_and_max: | 
 | 438 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_max, E); | 
 | 439 |   case Builtin::BI__sync_fetch_and_umin: | 
 | 440 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umin, E); | 
 | 441 |   case Builtin::BI__sync_fetch_and_umax: | 
 | 442 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umax, E); | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 443 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 444 |   case Builtin::BI__sync_add_and_fetch_1: | 
 | 445 |   case Builtin::BI__sync_add_and_fetch_2: | 
 | 446 |   case Builtin::BI__sync_add_and_fetch_4: | 
 | 447 |   case Builtin::BI__sync_add_and_fetch_8: | 
 | 448 |   case Builtin::BI__sync_add_and_fetch_16: | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 449 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E, | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 450 |                                 llvm::Instruction::Add); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 451 |   case Builtin::BI__sync_sub_and_fetch_1: | 
 | 452 |   case Builtin::BI__sync_sub_and_fetch_2: | 
 | 453 |   case Builtin::BI__sync_sub_and_fetch_4: | 
 | 454 |   case Builtin::BI__sync_sub_and_fetch_8: | 
 | 455 |   case Builtin::BI__sync_sub_and_fetch_16: | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 456 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_sub, E, | 
 | 457 |                                 llvm::Instruction::Sub); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 458 |   case Builtin::BI__sync_and_and_fetch_1: | 
 | 459 |   case Builtin::BI__sync_and_and_fetch_2: | 
 | 460 |   case Builtin::BI__sync_and_and_fetch_4: | 
 | 461 |   case Builtin::BI__sync_and_and_fetch_8: | 
 | 462 |   case Builtin::BI__sync_and_and_fetch_16: | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 463 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_and, E, | 
 | 464 |                                 llvm::Instruction::And); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 465 |   case Builtin::BI__sync_or_and_fetch_1: | 
 | 466 |   case Builtin::BI__sync_or_and_fetch_2: | 
 | 467 |   case Builtin::BI__sync_or_and_fetch_4: | 
 | 468 |   case Builtin::BI__sync_or_and_fetch_8: | 
 | 469 |   case Builtin::BI__sync_or_and_fetch_16: | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 470 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_or, E, | 
 | 471 |                                 llvm::Instruction::Or); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 472 |   case Builtin::BI__sync_xor_and_fetch_1: | 
 | 473 |   case Builtin::BI__sync_xor_and_fetch_2: | 
 | 474 |   case Builtin::BI__sync_xor_and_fetch_4: | 
 | 475 |   case Builtin::BI__sync_xor_and_fetch_8: | 
 | 476 |   case Builtin::BI__sync_xor_and_fetch_16: | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 477 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_xor, E, | 
 | 478 |                                 llvm::Instruction::Xor); | 
| Chris Lattner | eebd9d2 | 2009-05-13 04:37:52 +0000 | [diff] [blame] | 479 |   case Builtin::BI__sync_nand_and_fetch_1: | 
 | 480 |   case Builtin::BI__sync_nand_and_fetch_2: | 
 | 481 |   case Builtin::BI__sync_nand_and_fetch_4: | 
 | 482 |   case Builtin::BI__sync_nand_and_fetch_8: | 
 | 483 |   case Builtin::BI__sync_nand_and_fetch_16: | 
 | 484 |     return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_nand, E, | 
 | 485 |                                 llvm::Instruction::And); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 486 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 487 |   case Builtin::BI__sync_val_compare_and_swap_1: | 
 | 488 |   case Builtin::BI__sync_val_compare_and_swap_2: | 
 | 489 |   case Builtin::BI__sync_val_compare_and_swap_4: | 
 | 490 |   case Builtin::BI__sync_val_compare_and_swap_8: | 
 | 491 |   case Builtin::BI__sync_val_compare_and_swap_16: | 
 | 492 |   { | 
| Mon P Wang | c500451 | 2008-07-31 03:28:23 +0000 | [diff] [blame] | 493 |     const llvm::Type *ResType[2]; | 
 | 494 |     ResType[0]= ConvertType(E->getType()); | 
 | 495 |     ResType[1] = ConvertType(E->getArg(0)->getType()); | 
 | 496 |     Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 497 |     return RValue::get(Builder.CreateCall3(AtomF, | 
| Anders Carlsson | 9584446 | 2008-08-30 16:17:45 +0000 | [diff] [blame] | 498 |                                            EmitScalarExpr(E->getArg(0)), | 
 | 499 |                                            EmitScalarExpr(E->getArg(1)), | 
 | 500 |                                            EmitScalarExpr(E->getArg(2)))); | 
| Anders Carlsson | 89799cf | 2007-10-29 02:59:40 +0000 | [diff] [blame] | 501 |   } | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 502 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 503 |   case Builtin::BI__sync_bool_compare_and_swap_1: | 
 | 504 |   case Builtin::BI__sync_bool_compare_and_swap_2: | 
 | 505 |   case Builtin::BI__sync_bool_compare_and_swap_4: | 
 | 506 |   case Builtin::BI__sync_bool_compare_and_swap_8: | 
 | 507 |   case Builtin::BI__sync_bool_compare_and_swap_16: | 
 | 508 |   { | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 509 |     const llvm::Type *ResType[2]; | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 510 |     ResType[0]= ConvertType(E->getArg(1)->getType()); | 
| Owen Anderson | 96e0fc7 | 2009-07-29 22:16:19 +0000 | [diff] [blame] | 511 |     ResType[1] = llvm::PointerType::getUnqual(ResType[0]); | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 512 |     Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2); | 
 | 513 |     Value *OldVal = EmitScalarExpr(E->getArg(1)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 514 |     Value *PrevVal = Builder.CreateCall3(AtomF, | 
| Daniel Dunbar | 0002d23 | 2009-04-07 00:55:51 +0000 | [diff] [blame] | 515 |                                         EmitScalarExpr(E->getArg(0)), | 
 | 516 |                                         OldVal, | 
 | 517 |                                         EmitScalarExpr(E->getArg(2))); | 
 | 518 |     Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal); | 
 | 519 |     // zext bool to int. | 
 | 520 |     return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType()))); | 
 | 521 |   } | 
 | 522 |  | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 523 |   case Builtin::BI__sync_lock_test_and_set_1: | 
 | 524 |   case Builtin::BI__sync_lock_test_and_set_2: | 
 | 525 |   case Builtin::BI__sync_lock_test_and_set_4: | 
 | 526 |   case Builtin::BI__sync_lock_test_and_set_8: | 
 | 527 |   case Builtin::BI__sync_lock_test_and_set_16: | 
| Nate Begeman | 7ea2e3f | 2008-05-15 07:38:03 +0000 | [diff] [blame] | 528 |     return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); | 
| Chris Lattner | 5caa370 | 2009-05-08 06:58:22 +0000 | [diff] [blame] | 529 |   case Builtin::BI__sync_lock_release_1: | 
 | 530 |   case Builtin::BI__sync_lock_release_2: | 
 | 531 |   case Builtin::BI__sync_lock_release_4: | 
 | 532 |   case Builtin::BI__sync_lock_release_8: | 
| Chris Lattner | f58cd9b | 2009-05-13 04:46:13 +0000 | [diff] [blame] | 533 |   case Builtin::BI__sync_lock_release_16: { | 
 | 534 |     Value *Ptr = EmitScalarExpr(E->getArg(0)); | 
 | 535 |     const llvm::Type *ElTy = | 
 | 536 |       cast<llvm::PointerType>(Ptr->getType())->getElementType(); | 
| Daniel Dunbar | 007b567 | 2009-11-29 21:11:47 +0000 | [diff] [blame] | 537 |     llvm::StoreInst *Store =  | 
 | 538 |       Builder.CreateStore(llvm::Constant::getNullValue(ElTy), Ptr); | 
 | 539 |     Store->setVolatile(true); | 
| Daniel Dunbar | eb4f81e | 2009-05-27 23:45:33 +0000 | [diff] [blame] | 540 |     return RValue::get(0); | 
| Chris Lattner | f58cd9b | 2009-05-13 04:46:13 +0000 | [diff] [blame] | 541 |   } | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 542 |  | 
| Chris Lattner | f58cd9b | 2009-05-13 04:46:13 +0000 | [diff] [blame] | 543 |   case Builtin::BI__sync_synchronize: { | 
 | 544 |     Value *C[5]; | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 545 |     C[0] = C[1] = C[2] = C[3] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 1); | 
 | 546 |     C[4] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0); | 
| Chris Lattner | f58cd9b | 2009-05-13 04:46:13 +0000 | [diff] [blame] | 547 |     Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5); | 
| Daniel Dunbar | eb4f81e | 2009-05-27 23:45:33 +0000 | [diff] [blame] | 548 |     return RValue::get(0); | 
| Chris Lattner | f58cd9b | 2009-05-13 04:46:13 +0000 | [diff] [blame] | 549 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 550 |  | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 551 |     // Library functions with special handling. | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 552 |   case Builtin::BIsqrt: | 
 | 553 |   case Builtin::BIsqrtf: | 
 | 554 |   case Builtin::BIsqrtl: { | 
 | 555 |     // Rewrite sqrt to intrinsic if allowed. | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 556 |     if (!FD->hasAttr<ConstAttr>()) | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 557 |       break; | 
 | 558 |     Value *Arg0 = EmitScalarExpr(E->getArg(0)); | 
 | 559 |     const llvm::Type *ArgType = Arg0->getType(); | 
 | 560 |     Value *F = CGM.getIntrinsic(Intrinsic::sqrt, &ArgType, 1); | 
 | 561 |     return RValue::get(Builder.CreateCall(F, Arg0, "tmp")); | 
 | 562 |   } | 
 | 563 |  | 
 | 564 |   case Builtin::BIpow: | 
 | 565 |   case Builtin::BIpowf: | 
 | 566 |   case Builtin::BIpowl: { | 
 | 567 |     // Rewrite sqrt to intrinsic if allowed. | 
| Argyrios Kyrtzidis | 40b598e | 2009-06-30 02:34:44 +0000 | [diff] [blame] | 568 |     if (!FD->hasAttr<ConstAttr>()) | 
| Daniel Dunbar | ef2abfe | 2009-02-16 22:43:43 +0000 | [diff] [blame] | 569 |       break; | 
 | 570 |     Value *Base = EmitScalarExpr(E->getArg(0)); | 
 | 571 |     Value *Exponent = EmitScalarExpr(E->getArg(1)); | 
 | 572 |     const llvm::Type *ArgType = Base->getType(); | 
 | 573 |     Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1); | 
 | 574 |     return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp")); | 
 | 575 |   } | 
| Nate Begeman | 7ea2e3f | 2008-05-15 07:38:03 +0000 | [diff] [blame] | 576 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 577 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 578 |   // If this is an alias for a libm function (e.g. __builtin_sin) turn it into | 
 | 579 |   // that function. | 
| Douglas Gregor | 3e41d60 | 2009-02-13 23:20:09 +0000 | [diff] [blame] | 580 |   if (getContext().BuiltinInfo.isLibFunction(BuiltinID) || | 
 | 581 |       getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) | 
| Anders Carlsson | 31777a2 | 2009-12-24 19:08:58 +0000 | [diff] [blame] | 582 |     return EmitCall(E->getCallee()->getType(), | 
 | 583 |                     CGM.getBuiltinLibFunction(FD, BuiltinID), | 
 | 584 |                     E->arg_begin(), E->arg_end()); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 585 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 586 |   // See if we have a target specific intrinsic. | 
| Dale Johannesen | a6f80ef | 2009-02-05 01:50:47 +0000 | [diff] [blame] | 587 |   const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); | 
| Daniel Dunbar | 55cc2ed | 2009-08-24 09:54:37 +0000 | [diff] [blame] | 588 |   Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; | 
 | 589 |   if (const char *Prefix = | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 590 |       llvm::Triple::getArchTypePrefix(Target.getTriple().getArch())) | 
| Daniel Dunbar | 55cc2ed | 2009-08-24 09:54:37 +0000 | [diff] [blame] | 591 |     IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 592 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 593 |   if (IntrinsicID != Intrinsic::not_intrinsic) { | 
 | 594 |     SmallVector<Value*, 16> Args; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 595 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 596 |     Function *F = CGM.getIntrinsic(IntrinsicID); | 
 | 597 |     const llvm::FunctionType *FTy = F->getFunctionType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 598 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 599 |     for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { | 
 | 600 |       Value *ArgValue = EmitScalarExpr(E->getArg(i)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 601 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 602 |       // If the intrinsic arg type is different from the builtin arg type | 
 | 603 |       // we need to do a bit cast. | 
 | 604 |       const llvm::Type *PTy = FTy->getParamType(i); | 
 | 605 |       if (PTy != ArgValue->getType()) { | 
 | 606 |         assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) && | 
 | 607 |                "Must be able to losslessly bit cast to param"); | 
 | 608 |         ArgValue = Builder.CreateBitCast(ArgValue, PTy); | 
 | 609 |       } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 610 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 611 |       Args.push_back(ArgValue); | 
 | 612 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 613 |  | 
| Jay Foad | beaaccd | 2009-05-21 09:52:38 +0000 | [diff] [blame] | 614 |     Value *V = Builder.CreateCall(F, Args.data(), Args.data() + Args.size()); | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 615 |     QualType BuiltinRetType = E->getType(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 616 |  | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 617 |     const llvm::Type *RetTy = llvm::Type::getVoidTy(VMContext); | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 618 |     if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 619 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 620 |     if (RetTy != V->getType()) { | 
 | 621 |       assert(V->getType()->canLosslesslyBitCastTo(RetTy) && | 
 | 622 |              "Must be able to losslessly bit cast result type"); | 
 | 623 |       V = Builder.CreateBitCast(V, RetTy); | 
 | 624 |     } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 625 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 626 |     return RValue::get(V); | 
 | 627 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 628 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 629 |   // See if we have a target specific builtin that needs to be lowered. | 
| Daniel Dunbar | f02e9dd | 2008-10-10 00:24:54 +0000 | [diff] [blame] | 630 |   if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E)) | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 631 |     return RValue::get(V); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 632 |  | 
| Daniel Dunbar | 488e993 | 2008-08-16 00:56:44 +0000 | [diff] [blame] | 633 |   ErrorUnsupported(E, "builtin function"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 634 |  | 
| Chris Lattner | b7cfe88 | 2008-06-30 18:32:54 +0000 | [diff] [blame] | 635 |   // Unknown builtin, for now just dump it out and return undef. | 
 | 636 |   if (hasAggregateLLVMType(E->getType())) | 
 | 637 |     return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType()))); | 
| Owen Anderson | 03e2050 | 2009-07-30 23:11:26 +0000 | [diff] [blame] | 638 |   return RValue::get(llvm::UndefValue::get(ConvertType(E->getType()))); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 639 | } | 
| Anders Carlsson | 564f1de | 2007-12-09 23:17:02 +0000 | [diff] [blame] | 640 |  | 
| Daniel Dunbar | f02e9dd | 2008-10-10 00:24:54 +0000 | [diff] [blame] | 641 | Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, | 
 | 642 |                                               const CallExpr *E) { | 
| Daniel Dunbar | 55cc2ed | 2009-08-24 09:54:37 +0000 | [diff] [blame] | 643 |   switch (Target.getTriple().getArch()) { | 
 | 644 |   case llvm::Triple::x86: | 
 | 645 |   case llvm::Triple::x86_64: | 
| Daniel Dunbar | f02e9dd | 2008-10-10 00:24:54 +0000 | [diff] [blame] | 646 |     return EmitX86BuiltinExpr(BuiltinID, E); | 
| Daniel Dunbar | 55cc2ed | 2009-08-24 09:54:37 +0000 | [diff] [blame] | 647 |   case llvm::Triple::ppc: | 
 | 648 |   case llvm::Triple::ppc64: | 
| Daniel Dunbar | f02e9dd | 2008-10-10 00:24:54 +0000 | [diff] [blame] | 649 |     return EmitPPCBuiltinExpr(BuiltinID, E); | 
| Daniel Dunbar | 55cc2ed | 2009-08-24 09:54:37 +0000 | [diff] [blame] | 650 |   default: | 
 | 651 |     return 0; | 
 | 652 |   } | 
| Daniel Dunbar | f02e9dd | 2008-10-10 00:24:54 +0000 | [diff] [blame] | 653 | } | 
 | 654 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 655 | Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 656 |                                            const CallExpr *E) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 657 |  | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 658 |   llvm::SmallVector<Value*, 4> Ops; | 
 | 659 |  | 
 | 660 |   for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) | 
 | 661 |     Ops.push_back(EmitScalarExpr(E->getArg(i))); | 
 | 662 |  | 
| Anders Carlsson | 564f1de | 2007-12-09 23:17:02 +0000 | [diff] [blame] | 663 |   switch (BuiltinID) { | 
| Anders Carlsson | 46a26b0 | 2007-12-09 23:39:18 +0000 | [diff] [blame] | 664 |   default: return 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 665 |   case X86::BI__builtin_ia32_pslldi128: | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 666 |   case X86::BI__builtin_ia32_psllqi128: | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 667 |   case X86::BI__builtin_ia32_psllwi128: | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 668 |   case X86::BI__builtin_ia32_psradi128: | 
 | 669 |   case X86::BI__builtin_ia32_psrawi128: | 
 | 670 |   case X86::BI__builtin_ia32_psrldi128: | 
 | 671 |   case X86::BI__builtin_ia32_psrlqi128: | 
 | 672 |   case X86::BI__builtin_ia32_psrlwi128: { | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 673 |     Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext"); | 
 | 674 |     const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 2); | 
 | 675 |     llvm::Value *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0); | 
| Owen Anderson | 03e2050 | 2009-07-30 23:11:26 +0000 | [diff] [blame] | 676 |     Ops[1] = Builder.CreateInsertElement(llvm::UndefValue::get(Ty), | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 677 |                                          Ops[1], Zero, "insert"); | 
 | 678 |     Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType(), "bitcast"); | 
 | 679 |     const char *name = 0; | 
 | 680 |     Intrinsic::ID ID = Intrinsic::not_intrinsic; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 681 |  | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 682 |     switch (BuiltinID) { | 
 | 683 |     default: assert(0 && "Unsupported shift intrinsic!"); | 
 | 684 |     case X86::BI__builtin_ia32_pslldi128: | 
 | 685 |       name = "pslldi"; | 
 | 686 |       ID = Intrinsic::x86_sse2_psll_d; | 
 | 687 |       break; | 
 | 688 |     case X86::BI__builtin_ia32_psllqi128: | 
 | 689 |       name = "psllqi"; | 
 | 690 |       ID = Intrinsic::x86_sse2_psll_q; | 
 | 691 |       break; | 
 | 692 |     case X86::BI__builtin_ia32_psllwi128: | 
 | 693 |       name = "psllwi"; | 
 | 694 |       ID = Intrinsic::x86_sse2_psll_w; | 
 | 695 |       break; | 
 | 696 |     case X86::BI__builtin_ia32_psradi128: | 
 | 697 |       name = "psradi"; | 
 | 698 |       ID = Intrinsic::x86_sse2_psra_d; | 
 | 699 |       break; | 
 | 700 |     case X86::BI__builtin_ia32_psrawi128: | 
 | 701 |       name = "psrawi"; | 
 | 702 |       ID = Intrinsic::x86_sse2_psra_w; | 
 | 703 |       break; | 
 | 704 |     case X86::BI__builtin_ia32_psrldi128: | 
 | 705 |       name = "psrldi"; | 
 | 706 |       ID = Intrinsic::x86_sse2_psrl_d; | 
 | 707 |       break; | 
 | 708 |     case X86::BI__builtin_ia32_psrlqi128: | 
 | 709 |       name = "psrlqi"; | 
 | 710 |       ID = Intrinsic::x86_sse2_psrl_q; | 
 | 711 |       break; | 
 | 712 |     case X86::BI__builtin_ia32_psrlwi128: | 
 | 713 |       name = "psrlwi"; | 
 | 714 |       ID = Intrinsic::x86_sse2_psrl_w; | 
 | 715 |       break; | 
 | 716 |     } | 
 | 717 |     llvm::Function *F = CGM.getIntrinsic(ID); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 718 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 719 |   } | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 720 |   case X86::BI__builtin_ia32_pslldi: | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 721 |   case X86::BI__builtin_ia32_psllqi: | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 722 |   case X86::BI__builtin_ia32_psllwi: | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 723 |   case X86::BI__builtin_ia32_psradi: | 
 | 724 |   case X86::BI__builtin_ia32_psrawi: | 
 | 725 |   case X86::BI__builtin_ia32_psrldi: | 
 | 726 |   case X86::BI__builtin_ia32_psrlqi: | 
 | 727 |   case X86::BI__builtin_ia32_psrlwi: { | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 728 |     Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext"); | 
 | 729 |     const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 1); | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 730 |     Ops[1] = Builder.CreateBitCast(Ops[1], Ty, "bitcast"); | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 731 |     const char *name = 0; | 
 | 732 |     Intrinsic::ID ID = Intrinsic::not_intrinsic; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 733 |  | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 734 |     switch (BuiltinID) { | 
 | 735 |     default: assert(0 && "Unsupported shift intrinsic!"); | 
 | 736 |     case X86::BI__builtin_ia32_pslldi: | 
 | 737 |       name = "pslldi"; | 
 | 738 |       ID = Intrinsic::x86_mmx_psll_d; | 
 | 739 |       break; | 
 | 740 |     case X86::BI__builtin_ia32_psllqi: | 
 | 741 |       name = "psllqi"; | 
 | 742 |       ID = Intrinsic::x86_mmx_psll_q; | 
 | 743 |       break; | 
 | 744 |     case X86::BI__builtin_ia32_psllwi: | 
 | 745 |       name = "psllwi"; | 
 | 746 |       ID = Intrinsic::x86_mmx_psll_w; | 
 | 747 |       break; | 
 | 748 |     case X86::BI__builtin_ia32_psradi: | 
 | 749 |       name = "psradi"; | 
 | 750 |       ID = Intrinsic::x86_mmx_psra_d; | 
 | 751 |       break; | 
 | 752 |     case X86::BI__builtin_ia32_psrawi: | 
 | 753 |       name = "psrawi"; | 
 | 754 |       ID = Intrinsic::x86_mmx_psra_w; | 
 | 755 |       break; | 
 | 756 |     case X86::BI__builtin_ia32_psrldi: | 
 | 757 |       name = "psrldi"; | 
 | 758 |       ID = Intrinsic::x86_mmx_psrl_d; | 
 | 759 |       break; | 
 | 760 |     case X86::BI__builtin_ia32_psrlqi: | 
 | 761 |       name = "psrlqi"; | 
 | 762 |       ID = Intrinsic::x86_mmx_psrl_q; | 
 | 763 |       break; | 
 | 764 |     case X86::BI__builtin_ia32_psrlwi: | 
 | 765 |       name = "psrlwi"; | 
 | 766 |       ID = Intrinsic::x86_mmx_psrl_w; | 
 | 767 |       break; | 
 | 768 |     } | 
| Chris Lattner | 7acda7c | 2007-12-18 00:25:38 +0000 | [diff] [blame] | 769 |     llvm::Function *F = CGM.getIntrinsic(ID); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 770 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name); | 
| Anders Carlsson | 2929cfa | 2007-12-14 17:48:24 +0000 | [diff] [blame] | 771 |   } | 
| Anders Carlsson | 79dcf5f | 2009-05-18 19:16:46 +0000 | [diff] [blame] | 772 |   case X86::BI__builtin_ia32_cmpps: { | 
 | 773 |     llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps); | 
 | 774 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpps"); | 
 | 775 |   } | 
 | 776 |   case X86::BI__builtin_ia32_cmpss: { | 
 | 777 |     llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ss); | 
 | 778 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpss"); | 
| Anders Carlsson | cc8b7f9 | 2007-12-16 22:33:50 +0000 | [diff] [blame] | 779 |   } | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 780 |   case X86::BI__builtin_ia32_ldmxcsr: { | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 781 |     const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 782 |     Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1); | 
 | 783 |     Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp"); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 784 |     Builder.CreateStore(Ops[0], Tmp); | 
 | 785 |     return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr), | 
| Chris Lattner | 3eae03e | 2008-05-06 00:56:42 +0000 | [diff] [blame] | 786 |                               Builder.CreateBitCast(Tmp, PtrTy)); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 787 |   } | 
 | 788 |   case X86::BI__builtin_ia32_stmxcsr: { | 
| Benjamin Kramer | 3c0ef8c | 2009-10-13 10:07:13 +0000 | [diff] [blame] | 789 |     const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext); | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 790 |     Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1); | 
 | 791 |     Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp"); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 792 |     One = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr), | 
| Chris Lattner | 3eae03e | 2008-05-06 00:56:42 +0000 | [diff] [blame] | 793 |                              Builder.CreateBitCast(Tmp, PtrTy)); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 794 |     return Builder.CreateLoad(Tmp, "stmxcsr"); | 
 | 795 |   } | 
| Anders Carlsson | 79dcf5f | 2009-05-18 19:16:46 +0000 | [diff] [blame] | 796 |   case X86::BI__builtin_ia32_cmppd: { | 
 | 797 |     llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_pd); | 
 | 798 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmppd"); | 
 | 799 |   } | 
 | 800 |   case X86::BI__builtin_ia32_cmpsd: { | 
 | 801 |     llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_sd); | 
 | 802 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpsd"); | 
| Anders Carlsson | cc8b7f9 | 2007-12-16 22:33:50 +0000 | [diff] [blame] | 803 |   } | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 804 |   case X86::BI__builtin_ia32_storehps: | 
 | 805 |   case X86::BI__builtin_ia32_storelps: { | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 806 |     const llvm::Type *EltTy = llvm::Type::getInt64Ty(VMContext); | 
| Owen Anderson | 96e0fc7 | 2009-07-29 22:16:19 +0000 | [diff] [blame] | 807 |     llvm::Type *PtrTy = llvm::PointerType::getUnqual(EltTy); | 
 | 808 |     llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 809 |  | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 810 |     // cast val v2i64 | 
 | 811 |     Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 812 |  | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 813 |     // extract (0, 1) | 
 | 814 |     unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1; | 
| Owen Anderson | 0032b27 | 2009-08-13 21:57:51 +0000 | [diff] [blame] | 815 |     llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Index); | 
| Nate Begeman | e772210 | 2008-04-14 04:49:57 +0000 | [diff] [blame] | 816 |     Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract"); | 
 | 817 |  | 
 | 818 |     // cast pointer to i64 & store | 
 | 819 |     Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy); | 
 | 820 |     return Builder.CreateStore(Ops[1], Ops[0]); | 
 | 821 |   } | 
| Eric Christopher | 91b5927 | 2009-12-01 05:00:51 +0000 | [diff] [blame] | 822 |   case X86::BI__builtin_ia32_palignr: { | 
| Nate Begeman | c3420ff | 2009-12-14 05:15:02 +0000 | [diff] [blame] | 823 |     Function *F = CGM.getIntrinsic(Intrinsic::x86_ssse3_palign_r); | 
 | 824 |     return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size()); | 
 | 825 |   } | 
 | 826 |   case X86::BI__builtin_ia32_palignr128: { | 
| Nate Begeman | ce5818a | 2009-12-14 04:57:03 +0000 | [diff] [blame] | 827 |     unsigned shiftVal = cast<llvm::ConstantInt>(Ops[2])->getZExtValue(); | 
 | 828 |      | 
 | 829 |     // If palignr is shifting the pair of input vectors less than 17 bytes, | 
 | 830 |     // emit a shuffle instruction. | 
 | 831 |     if (shiftVal <= 16) { | 
 | 832 |       const llvm::Type *IntTy = llvm::Type::getInt32Ty(VMContext); | 
 | 833 |  | 
 | 834 |       llvm::SmallVector<llvm::Constant*, 16> Indices; | 
 | 835 |       for (unsigned i = 0; i != 16; ++i) | 
 | 836 |         Indices.push_back(llvm::ConstantInt::get(IntTy, shiftVal + i)); | 
 | 837 |        | 
 | 838 |       Value* SV = llvm::ConstantVector::get(Indices.begin(), Indices.size()); | 
 | 839 |       return Builder.CreateShuffleVector(Ops[1], Ops[0], SV, "palignr"); | 
 | 840 |     } | 
 | 841 |      | 
 | 842 |     // If palignr is shifting the pair of input vectors more than 16 but less | 
 | 843 |     // than 32 bytes, emit a logical right shift of the destination. | 
 | 844 |     if (shiftVal < 32) { | 
 | 845 |       const llvm::Type *EltTy = llvm::Type::getInt64Ty(VMContext); | 
 | 846 |       const llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2); | 
 | 847 |       const llvm::Type *IntTy = llvm::Type::getInt32Ty(VMContext); | 
 | 848 |        | 
 | 849 |       Ops[0] = Builder.CreateBitCast(Ops[0], VecTy, "cast"); | 
 | 850 |       Ops[1] = llvm::ConstantInt::get(IntTy, (shiftVal-16) * 8); | 
 | 851 |        | 
 | 852 |       // create i32 constant | 
 | 853 |       llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_psrl_dq); | 
 | 854 |       return Builder.CreateCall(F, &Ops[0], &Ops[0] + 2, "palignr"); | 
 | 855 |     } | 
 | 856 |      | 
 | 857 |     // If palignr is shifting the pair of vectors more than 32 bytes, emit zero. | 
 | 858 |     return llvm::Constant::getNullValue(ConvertType(E->getType())); | 
| Eric Christopher | 91b5927 | 2009-12-01 05:00:51 +0000 | [diff] [blame] | 859 |   } | 
| Anders Carlsson | 564f1de | 2007-12-09 23:17:02 +0000 | [diff] [blame] | 860 |   } | 
 | 861 | } | 
 | 862 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 863 | Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, | 
| Chris Lattner | 1feedd8 | 2007-12-13 07:34:23 +0000 | [diff] [blame] | 864 |                                            const CallExpr *E) { | 
| Daniel Dunbar | b0b8438 | 2009-12-18 20:58:47 +0000 | [diff] [blame] | 865 |   return 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 866 | } |