blob: 987cd24e2c8b5fc8580e0f515e0c5b6c3c58c1bc [file] [log] [blame]
Anders Carlsson1d8e5212007-08-20 18:05:56 +00001//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5b12ab82007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Anders Carlsson1d8e5212007-08-20 18:05:56 +00007//
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 Carlssona020c432007-12-09 21:20:04 +000016#include "clang/Basic/TargetInfo.h"
Chris Lattnera1518b12008-10-06 06:09:18 +000017#include "clang/AST/APValue.h"
Chris Lattner1eec6602007-08-31 04:31:45 +000018#include "clang/AST/ASTContext.h"
Daniel Dunbar6e8aa532008-08-11 05:35:13 +000019#include "clang/AST/Decl.h"
Chris Lattner5abdec72009-06-14 01:05:48 +000020#include "clang/Basic/TargetBuiltins.h"
Anders Carlsson24ebce62007-10-12 23:56:29 +000021#include "llvm/Intrinsics.h"
Anders Carlsson1d8e5212007-08-20 18:05:56 +000022using namespace clang;
23using namespace CodeGen;
Anders Carlssona020c432007-12-09 21:20:04 +000024using namespace llvm;
25
Daniel Dunbar4fab57d2009-04-07 00:55:51 +000026/// Utility to insert an atomic instruction based on Instrinsic::ID
27/// and the expression node.
Mike Stump11289f42009-09-09 15:08:12 +000028static RValue EmitBinaryAtomic(CodeGenFunction& CGF,
Mon P Wangb84407d2008-05-09 22:40:52 +000029 Intrinsic::ID Id, const CallExpr *E) {
Mon P Wangb160a0d2008-07-31 03:28:23 +000030 const llvm::Type *ResType[2];
Daniel Dunbar4fab57d2009-04-07 00:55:51 +000031 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 Stump11289f42009-09-09 15:08:12 +000034 return RValue::get(CGF.Builder.CreateCall2(AtomF,
35 CGF.EmitScalarExpr(E->getArg(0)),
Daniel Dunbar4fab57d2009-04-07 00:55:51 +000036 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 Stump11289f42009-09-09 15:08:12 +000042static RValue EmitBinaryAtomicPost(CodeGenFunction& CGF,
Daniel Dunbar4fab57d2009-04-07 00:55:51 +000043 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 Stump11289f42009-09-09 15:08:12 +000052
Chris Lattner94578cb2009-05-13 04:37:52 +000053 if (Id == Intrinsic::atomic_load_nand)
54 Result = CGF.Builder.CreateNot(Result);
Mike Stump11289f42009-09-09 15:08:12 +000055
56
Daniel Dunbar4fab57d2009-04-07 00:55:51 +000057 return RValue::get(CGF.Builder.CreateBinOp(Op, Result, Operand));
Mon P Wangb84407d2008-05-09 22:40:52 +000058}
59
Mike Stump11289f42009-09-09 15:08:12 +000060RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
Daniel Dunbar8eb018a2009-02-16 22:43:43 +000061 unsigned BuiltinID, const CallExpr *E) {
Chris Lattner24355b52008-10-06 06:56:41 +000062 // See if we can constant fold this builtin. If so, don't emit it at all.
Anders Carlssonc9687902008-12-01 02:31:41 +000063 Expr::EvalResult Result;
Chris Lattner67d7b922008-11-16 21:24:15 +000064 if (E->Evaluate(Result, CGM.getContext())) {
Anders Carlssonc9687902008-12-01 02:31:41 +000065 if (Result.Val.isInt())
Mike Stump11289f42009-09-09 15:08:12 +000066 return RValue::get(llvm::ConstantInt::get(VMContext,
Owen Andersonb7a2fe62009-07-24 23:12:58 +000067 Result.Val.getInt()));
Eli Friedmanc69d4542009-01-25 01:54:01 +000068 else if (Result.Val.isFloat())
Owen Andersone05f2ed2009-07-27 21:00:51 +000069 return RValue::get(ConstantFP::get(VMContext, Result.Val.getFloat()));
Chris Lattnera1518b12008-10-06 06:09:18 +000070 }
Mike Stump11289f42009-09-09 15:08:12 +000071
Chris Lattner24355b52008-10-06 06:56:41 +000072 switch (BuiltinID) {
73 default: break; // Handle intrinsics and libm functions below.
Chris Lattnera97132a2008-10-06 07:26:43 +000074 case Builtin::BI__builtin___CFStringMakeConstantString:
Anders Carlsson80f97ab2009-04-08 04:48:15 +000075 return RValue::get(CGM.EmitConstantExpr(E, E->getType(), 0));
Chris Lattner0bf67912008-07-09 17:28:44 +000076 case Builtin::BI__builtin_stdarg_start:
Anders Carlsson24ebce62007-10-12 23:56:29 +000077 case Builtin::BI__builtin_va_start:
78 case Builtin::BI__builtin_va_end: {
Daniel Dunbare9fcadd22009-02-11 22:25:55 +000079 Value *ArgValue = EmitVAListRef(E->getArg(0));
Benjamin Kramerabd5b902009-10-13 10:07:13 +000080 const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext);
Anders Carlsson24ebce62007-10-12 23:56:29 +000081 if (ArgValue->getType() != DestType)
Mike Stump11289f42009-09-09 15:08:12 +000082 ArgValue = Builder.CreateBitCast(ArgValue, DestType,
Daniel Dunbare59313a2009-07-26 09:28:40 +000083 ArgValue->getName().data());
Anders Carlsson24ebce62007-10-12 23:56:29 +000084
Mike Stump11289f42009-09-09 15:08:12 +000085 Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_end) ?
Chris Lattner0bf67912008-07-09 17:28:44 +000086 Intrinsic::vaend : Intrinsic::vastart;
Chris Lattnerb8be97e2007-12-18 00:25:38 +000087 return RValue::get(Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue));
Anders Carlsson24ebce62007-10-12 23:56:29 +000088 }
Anders Carlssonc0b0e592008-02-09 20:26:43 +000089 case Builtin::BI__builtin_va_copy: {
Eli Friedmanddea0ad2009-01-20 17:46:04 +000090 Value *DstPtr = EmitVAListRef(E->getArg(0));
91 Value *SrcPtr = EmitVAListRef(E->getArg(1));
Anders Carlssonc0b0e592008-02-09 20:26:43 +000092
Benjamin Kramerabd5b902009-10-13 10:07:13 +000093 const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext);
Anders Carlssonc0b0e592008-02-09 20:26:43 +000094
95 DstPtr = Builder.CreateBitCast(DstPtr, Type);
96 SrcPtr = Builder.CreateBitCast(SrcPtr, Type);
Mike Stump11289f42009-09-09 15:08:12 +000097 return RValue::get(Builder.CreateCall2(CGM.getIntrinsic(Intrinsic::vacopy),
Chris Lattnerdbcc2ca2008-05-06 00:56:42 +000098 DstPtr, SrcPtr));
Anders Carlssonc0b0e592008-02-09 20:26:43 +000099 }
Anders Carlsson4f8eb122007-11-20 19:05:17 +0000100 case Builtin::BI__builtin_abs: {
Mike Stump11289f42009-09-09 15:08:12 +0000101 Value *ArgValue = EmitScalarExpr(E->getArg(0));
102
Chris Lattner28ee5b32008-07-23 06:53:34 +0000103 Value *NegOp = Builder.CreateNeg(ArgValue, "neg");
Mike Stump11289f42009-09-09 15:08:12 +0000104 Value *CmpResult =
105 Builder.CreateICmpSGE(ArgValue,
Owen Anderson0b75f232009-07-31 20:28:54 +0000106 llvm::Constant::getNullValue(ArgValue->getType()),
Chris Lattner28ee5b32008-07-23 06:53:34 +0000107 "abscond");
Mike Stump11289f42009-09-09 15:08:12 +0000108 Value *Result =
Anders Carlsson4f8eb122007-11-20 19:05:17 +0000109 Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs");
Mike Stump11289f42009-09-09 15:08:12 +0000110
Anders Carlsson4f8eb122007-11-20 19:05:17 +0000111 return RValue::get(Result);
112 }
Anders Carlsson093f1a02008-02-06 07:19:27 +0000113 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 Stump11289f42009-09-09 15:08:12 +0000117
Anders Carlsson093f1a02008-02-06 07:19:27 +0000118 const llvm::Type *ArgType = ArgValue->getType();
119 Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1);
120
Mike Stump11289f42009-09-09 15:08:12 +0000121 const llvm::Type *ResultType = ConvertType(E->getType());
Anders Carlsson093f1a02008-02-06 07:19:27 +0000122 Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
123 if (Result->getType() != ResultType)
124 Result = Builder.CreateIntCast(Result, ResultType, "cast");
125 return RValue::get(Result);
126 }
Eli Friedman5e2281e2008-05-27 15:32:46 +0000127 case Builtin::BI__builtin_clz:
128 case Builtin::BI__builtin_clzl:
129 case Builtin::BI__builtin_clzll: {
130 Value *ArgValue = EmitScalarExpr(E->getArg(0));
Mike Stump11289f42009-09-09 15:08:12 +0000131
Eli Friedman5e2281e2008-05-27 15:32:46 +0000132 const llvm::Type *ArgType = ArgValue->getType();
133 Value *F = CGM.getIntrinsic(Intrinsic::ctlz, &ArgType, 1);
134
Mike Stump11289f42009-09-09 15:08:12 +0000135 const llvm::Type *ResultType = ConvertType(E->getType());
Eli Friedman5e2281e2008-05-27 15:32:46 +0000136 Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
137 if (Result->getType() != ResultType)
138 Result = Builder.CreateIntCast(Result, ResultType, "cast");
139 return RValue::get(Result);
140 }
Daniel Dunbard93abc32008-07-21 17:19:41 +0000141 case Builtin::BI__builtin_ffs:
142 case Builtin::BI__builtin_ffsl:
143 case Builtin::BI__builtin_ffsll: {
144 // ffs(x) -> x ? cttz(x) + 1 : 0
145 Value *ArgValue = EmitScalarExpr(E->getArg(0));
Mike Stump11289f42009-09-09 15:08:12 +0000146
Daniel Dunbard93abc32008-07-21 17:19:41 +0000147 const llvm::Type *ArgType = ArgValue->getType();
148 Value *F = CGM.getIntrinsic(Intrinsic::cttz, &ArgType, 1);
Mike Stump11289f42009-09-09 15:08:12 +0000149
Daniel Dunbard93abc32008-07-21 17:19:41 +0000150 const llvm::Type *ResultType = ConvertType(E->getType());
Mike Stump11289f42009-09-09 15:08:12 +0000151 Value *Tmp = Builder.CreateAdd(Builder.CreateCall(F, ArgValue, "tmp"),
Owen Andersonb7a2fe62009-07-24 23:12:58 +0000152 llvm::ConstantInt::get(ArgType, 1), "tmp");
Owen Anderson0b75f232009-07-31 20:28:54 +0000153 Value *Zero = llvm::Constant::getNullValue(ArgType);
Daniel Dunbard93abc32008-07-21 17:19:41 +0000154 Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero, "iszero");
155 Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp, "ffs");
156 if (Result->getType() != ResultType)
157 Result = Builder.CreateIntCast(Result, ResultType, "cast");
158 return RValue::get(Result);
159 }
160 case Builtin::BI__builtin_parity:
161 case Builtin::BI__builtin_parityl:
162 case Builtin::BI__builtin_parityll: {
163 // parity(x) -> ctpop(x) & 1
164 Value *ArgValue = EmitScalarExpr(E->getArg(0));
Mike Stump11289f42009-09-09 15:08:12 +0000165
Daniel Dunbard93abc32008-07-21 17:19:41 +0000166 const llvm::Type *ArgType = ArgValue->getType();
167 Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1);
Mike Stump11289f42009-09-09 15:08:12 +0000168
Daniel Dunbard93abc32008-07-21 17:19:41 +0000169 const llvm::Type *ResultType = ConvertType(E->getType());
170 Value *Tmp = Builder.CreateCall(F, ArgValue, "tmp");
Mike Stump11289f42009-09-09 15:08:12 +0000171 Value *Result = Builder.CreateAnd(Tmp, llvm::ConstantInt::get(ArgType, 1),
Daniel Dunbard93abc32008-07-21 17:19:41 +0000172 "tmp");
173 if (Result->getType() != ResultType)
174 Result = Builder.CreateIntCast(Result, ResultType, "cast");
175 return RValue::get(Result);
176 }
177 case Builtin::BI__builtin_popcount:
178 case Builtin::BI__builtin_popcountl:
179 case Builtin::BI__builtin_popcountll: {
180 Value *ArgValue = EmitScalarExpr(E->getArg(0));
Mike Stump11289f42009-09-09 15:08:12 +0000181
Daniel Dunbard93abc32008-07-21 17:19:41 +0000182 const llvm::Type *ArgType = ArgValue->getType();
183 Value *F = CGM.getIntrinsic(Intrinsic::ctpop, &ArgType, 1);
Mike Stump11289f42009-09-09 15:08:12 +0000184
Daniel Dunbard93abc32008-07-21 17:19:41 +0000185 const llvm::Type *ResultType = ConvertType(E->getType());
186 Value *Result = Builder.CreateCall(F, ArgValue, "tmp");
187 if (Result->getType() != ResultType)
188 Result = Builder.CreateIntCast(Result, ResultType, "cast");
189 return RValue::get(Result);
190 }
Chris Lattner13653d72007-12-13 07:34:23 +0000191 case Builtin::BI__builtin_expect:
Daniel Dunbarc2f67962008-07-21 18:44:41 +0000192 // FIXME: pass expect through to LLVM
Chris Lattner13653d72007-12-13 07:34:23 +0000193 return RValue::get(EmitScalarExpr(E->getArg(0)));
Anders Carlssonef93b9d2007-12-02 21:58:10 +0000194 case Builtin::BI__builtin_bswap32:
195 case Builtin::BI__builtin_bswap64: {
Chris Lattner13653d72007-12-13 07:34:23 +0000196 Value *ArgValue = EmitScalarExpr(E->getArg(0));
Anders Carlssonef93b9d2007-12-02 21:58:10 +0000197 const llvm::Type *ArgType = ArgValue->getType();
Chris Lattnerb8be97e2007-12-18 00:25:38 +0000198 Value *F = CGM.getIntrinsic(Intrinsic::bswap, &ArgType, 1);
Chris Lattner13653d72007-12-13 07:34:23 +0000199 return RValue::get(Builder.CreateCall(F, ArgValue, "tmp"));
Mike Stump11289f42009-09-09 15:08:12 +0000200 }
Daniel Dunbarb0d34c82008-09-03 21:13:56 +0000201 case Builtin::BI__builtin_object_size: {
202 // FIXME: Implement. For now we just always fail and pretend we
203 // don't know the object size.
Eli Friedman1c4a1752009-04-26 19:19:15 +0000204 llvm::APSInt TypeArg = E->getArg(1)->EvaluateAsInt(CGM.getContext());
Daniel Dunbarb0d34c82008-09-03 21:13:56 +0000205 const llvm::Type *ResType = ConvertType(E->getType());
206 // bool UseSubObject = TypeArg.getZExtValue() & 1;
207 bool UseMinimum = TypeArg.getZExtValue() & 2;
Owen Anderson170229f2009-07-14 23:10:40 +0000208 return RValue::get(
Owen Andersonb7a2fe62009-07-24 23:12:58 +0000209 llvm::ConstantInt::get(ResType, UseMinimum ? 0 : -1LL));
Daniel Dunbarb0d34c82008-09-03 21:13:56 +0000210 }
Daniel Dunbarb7257262008-07-21 22:59:13 +0000211 case Builtin::BI__builtin_prefetch: {
212 Value *Locality, *RW, *Address = EmitScalarExpr(E->getArg(0));
213 // FIXME: Technically these constants should of type 'int', yes?
Mike Stump11289f42009-09-09 15:08:12 +0000214 RW = (E->getNumArgs() > 1) ? EmitScalarExpr(E->getArg(1)) :
Owen Anderson41a75022009-08-13 21:57:51 +0000215 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0);
Mike Stump11289f42009-09-09 15:08:12 +0000216 Locality = (E->getNumArgs() > 2) ? EmitScalarExpr(E->getArg(2)) :
Owen Anderson41a75022009-08-13 21:57:51 +0000217 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 3);
Daniel Dunbarb7257262008-07-21 22:59:13 +0000218 Value *F = CGM.getIntrinsic(Intrinsic::prefetch, 0, 0);
219 return RValue::get(Builder.CreateCall3(F, Address, RW, Locality));
Anders Carlssonef93b9d2007-12-02 21:58:10 +0000220 }
Daniel Dunbarb7257262008-07-21 22:59:13 +0000221 case Builtin::BI__builtin_trap: {
222 Value *F = CGM.getIntrinsic(Intrinsic::trap, 0, 0);
223 return RValue::get(Builder.CreateCall(F));
224 }
Chris Lattnerbf206382009-09-21 03:09:59 +0000225 case Builtin::BI__builtin_unreachable: {
226 Value *V = Builder.CreateUnreachable();
227 Builder.ClearInsertionPoint();
228 return RValue::get(V);
229 }
230
Daniel Dunbarc2f67962008-07-21 18:44:41 +0000231 case Builtin::BI__builtin_powi:
232 case Builtin::BI__builtin_powif:
233 case Builtin::BI__builtin_powil: {
234 Value *Base = EmitScalarExpr(E->getArg(0));
235 Value *Exponent = EmitScalarExpr(E->getArg(1));
Daniel Dunbarc2f67962008-07-21 18:44:41 +0000236 const llvm::Type *ArgType = Base->getType();
237 Value *F = CGM.getIntrinsic(Intrinsic::powi, &ArgType, 1);
Daniel Dunbarc2f67962008-07-21 18:44:41 +0000238 return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp"));
239 }
240
Chris Lattner6c9ffe92007-12-20 00:44:32 +0000241 case Builtin::BI__builtin_isgreater:
242 case Builtin::BI__builtin_isgreaterequal:
243 case Builtin::BI__builtin_isless:
244 case Builtin::BI__builtin_islessequal:
245 case Builtin::BI__builtin_islessgreater:
246 case Builtin::BI__builtin_isunordered: {
247 // Ordered comparisons: we know the arguments to these are matching scalar
248 // floating point values.
Mike Stump11289f42009-09-09 15:08:12 +0000249 Value *LHS = EmitScalarExpr(E->getArg(0));
Chris Lattner6c9ffe92007-12-20 00:44:32 +0000250 Value *RHS = EmitScalarExpr(E->getArg(1));
Mike Stump11289f42009-09-09 15:08:12 +0000251
Chris Lattner6c9ffe92007-12-20 00:44:32 +0000252 switch (BuiltinID) {
253 default: assert(0 && "Unknown ordered comparison");
254 case Builtin::BI__builtin_isgreater:
255 LHS = Builder.CreateFCmpOGT(LHS, RHS, "cmp");
256 break;
257 case Builtin::BI__builtin_isgreaterequal:
258 LHS = Builder.CreateFCmpOGE(LHS, RHS, "cmp");
259 break;
260 case Builtin::BI__builtin_isless:
261 LHS = Builder.CreateFCmpOLT(LHS, RHS, "cmp");
262 break;
263 case Builtin::BI__builtin_islessequal:
264 LHS = Builder.CreateFCmpOLE(LHS, RHS, "cmp");
265 break;
266 case Builtin::BI__builtin_islessgreater:
267 LHS = Builder.CreateFCmpONE(LHS, RHS, "cmp");
268 break;
Mike Stump11289f42009-09-09 15:08:12 +0000269 case Builtin::BI__builtin_isunordered:
Chris Lattner6c9ffe92007-12-20 00:44:32 +0000270 LHS = Builder.CreateFCmpUNO(LHS, RHS, "cmp");
271 break;
272 }
273 // ZExt bool to int type.
274 return RValue::get(Builder.CreateZExt(LHS, ConvertType(E->getType()),
275 "tmp"));
276 }
Eli Friedman1c277d02009-09-01 04:19:44 +0000277 case Builtin::BI__builtin_isnan: {
278 Value *V = EmitScalarExpr(E->getArg(0));
279 V = Builder.CreateFCmpUNO(V, V, "cmp");
280 return RValue::get(Builder.CreateZExt(V, ConvertType(E->getType()), "tmp"));
281 }
Eli Friedmanf6bd1502009-06-02 07:10:30 +0000282 case Builtin::BIalloca:
Chris Lattner22b9ff42008-06-16 17:15:14 +0000283 case Builtin::BI__builtin_alloca: {
284 // FIXME: LLVM IR Should allow alloca with an i64 size!
285 Value *Size = EmitScalarExpr(E->getArg(0));
Owen Anderson41a75022009-08-13 21:57:51 +0000286 Size = Builder.CreateIntCast(Size, llvm::Type::getInt32Ty(VMContext), false, "tmp");
287 return RValue::get(Builder.CreateAlloca(llvm::Type::getInt8Ty(VMContext), Size, "tmp"));
Daniel Dunbar327acd72008-07-22 00:26:45 +0000288 }
289 case Builtin::BI__builtin_bzero: {
290 Value *Address = EmitScalarExpr(E->getArg(0));
291 Builder.CreateCall4(CGM.getMemSetFn(), Address,
Owen Anderson41a75022009-08-13 21:57:51 +0000292 llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 0),
Daniel Dunbar327acd72008-07-22 00:26:45 +0000293 EmitScalarExpr(E->getArg(1)),
Owen Anderson41a75022009-08-13 21:57:51 +0000294 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1));
Daniel Dunbar327acd72008-07-22 00:26:45 +0000295 return RValue::get(Address);
Chris Lattner22b9ff42008-06-16 17:15:14 +0000296 }
Eli Friedmana3a40682008-05-19 23:27:48 +0000297 case Builtin::BI__builtin_memcpy: {
Daniel Dunbar327acd72008-07-22 00:26:45 +0000298 Value *Address = EmitScalarExpr(E->getArg(0));
299 Builder.CreateCall4(CGM.getMemCpyFn(), Address,
300 EmitScalarExpr(E->getArg(1)),
301 EmitScalarExpr(E->getArg(2)),
Owen Anderson41a75022009-08-13 21:57:51 +0000302 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1));
Daniel Dunbar327acd72008-07-22 00:26:45 +0000303 return RValue::get(Address);
304 }
305 case Builtin::BI__builtin_memmove: {
306 Value *Address = EmitScalarExpr(E->getArg(0));
307 Builder.CreateCall4(CGM.getMemMoveFn(), Address,
308 EmitScalarExpr(E->getArg(1)),
309 EmitScalarExpr(E->getArg(2)),
Owen Anderson41a75022009-08-13 21:57:51 +0000310 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1));
Daniel Dunbar327acd72008-07-22 00:26:45 +0000311 return RValue::get(Address);
312 }
313 case Builtin::BI__builtin_memset: {
314 Value *Address = EmitScalarExpr(E->getArg(0));
315 Builder.CreateCall4(CGM.getMemSetFn(), Address,
Daniel Dunbare28b3592009-02-16 21:52:05 +0000316 Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
Owen Anderson41a75022009-08-13 21:57:51 +0000317 llvm::Type::getInt8Ty(VMContext)),
Daniel Dunbar327acd72008-07-22 00:26:45 +0000318 EmitScalarExpr(E->getArg(2)),
Owen Anderson41a75022009-08-13 21:57:51 +0000319 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1));
Daniel Dunbar327acd72008-07-22 00:26:45 +0000320 return RValue::get(Address);
Eli Friedmana3a40682008-05-19 23:27:48 +0000321 }
Eli Friedman53e38bd2008-05-20 08:59:34 +0000322 case Builtin::BI__builtin_return_address: {
323 Value *F = CGM.getIntrinsic(Intrinsic::returnaddress, 0, 0);
324 return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0))));
325 }
326 case Builtin::BI__builtin_frame_address: {
327 Value *F = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0);
328 return RValue::get(Builder.CreateCall(F, EmitScalarExpr(E->getArg(0))));
329 }
Eli Friedman5b73b5e2009-05-03 19:23:23 +0000330 case Builtin::BI__builtin_extract_return_addr: {
331 // FIXME: There should be a target hook for this
332 return RValue::get(EmitScalarExpr(E->getArg(0)));
333 }
Eli Friedmancb9d07c2009-06-02 09:37:50 +0000334 case Builtin::BI__builtin_unwind_init: {
335 Value *F = CGM.getIntrinsic(Intrinsic::eh_unwind_init, 0, 0);
336 return RValue::get(Builder.CreateCall(F));
337 }
338#if 0
339 // FIXME: Finish/enable when LLVM backend support stabilizes
340 case Builtin::BI__builtin_setjmp: {
341 Value *Buf = EmitScalarExpr(E->getArg(0));
342 // Store the frame pointer to the buffer
343 Value *FrameAddrF = CGM.getIntrinsic(Intrinsic::frameaddress, 0, 0);
344 Value *FrameAddr =
345 Builder.CreateCall(FrameAddrF,
Owen Anderson41a75022009-08-13 21:57:51 +0000346 Constant::getNullValue(llvm::Type::getInt32Ty(VMContext)));
Eli Friedmancb9d07c2009-06-02 09:37:50 +0000347 Builder.CreateStore(FrameAddr, Buf);
348 // Call the setjmp intrinsic
349 Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_setjmp, 0, 0);
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000350 const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext);
Eli Friedmancb9d07c2009-06-02 09:37:50 +0000351 Buf = Builder.CreateBitCast(Buf, DestType);
352 return RValue::get(Builder.CreateCall(F, Buf));
353 }
354 case Builtin::BI__builtin_longjmp: {
355 Value *F = CGM.getIntrinsic(Intrinsic::eh_sjlj_longjmp, 0, 0);
356 Value *Buf = EmitScalarExpr(E->getArg(0));
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000357 const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext);
Eli Friedmancb9d07c2009-06-02 09:37:50 +0000358 Buf = Builder.CreateBitCast(Buf, DestType);
359 return RValue::get(Builder.CreateCall(F, Buf));
360 }
361#endif
Mon P Wangb84407d2008-05-09 22:40:52 +0000362 case Builtin::BI__sync_fetch_and_add:
Mon P Wangb84407d2008-05-09 22:40:52 +0000363 case Builtin::BI__sync_fetch_and_sub:
Chris Lattnerdc046542009-05-08 06:58:22 +0000364 case Builtin::BI__sync_fetch_and_or:
365 case Builtin::BI__sync_fetch_and_and:
366 case Builtin::BI__sync_fetch_and_xor:
367 case Builtin::BI__sync_add_and_fetch:
368 case Builtin::BI__sync_sub_and_fetch:
369 case Builtin::BI__sync_and_and_fetch:
370 case Builtin::BI__sync_or_and_fetch:
371 case Builtin::BI__sync_xor_and_fetch:
372 case Builtin::BI__sync_val_compare_and_swap:
373 case Builtin::BI__sync_bool_compare_and_swap:
374 case Builtin::BI__sync_lock_test_and_set:
375 case Builtin::BI__sync_lock_release:
376 assert(0 && "Shouldn't make it through sema");
377 case Builtin::BI__sync_fetch_and_add_1:
378 case Builtin::BI__sync_fetch_and_add_2:
379 case Builtin::BI__sync_fetch_and_add_4:
380 case Builtin::BI__sync_fetch_and_add_8:
381 case Builtin::BI__sync_fetch_and_add_16:
382 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_add, E);
383 case Builtin::BI__sync_fetch_and_sub_1:
384 case Builtin::BI__sync_fetch_and_sub_2:
385 case Builtin::BI__sync_fetch_and_sub_4:
386 case Builtin::BI__sync_fetch_and_sub_8:
387 case Builtin::BI__sync_fetch_and_sub_16:
Mon P Wang28898b22008-06-25 08:21:36 +0000388 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_sub, E);
Chris Lattnerdc046542009-05-08 06:58:22 +0000389 case Builtin::BI__sync_fetch_and_or_1:
390 case Builtin::BI__sync_fetch_and_or_2:
391 case Builtin::BI__sync_fetch_and_or_4:
392 case Builtin::BI__sync_fetch_and_or_8:
393 case Builtin::BI__sync_fetch_and_or_16:
394 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_or, E);
395 case Builtin::BI__sync_fetch_and_and_1:
396 case Builtin::BI__sync_fetch_and_and_2:
397 case Builtin::BI__sync_fetch_and_and_4:
398 case Builtin::BI__sync_fetch_and_and_8:
399 case Builtin::BI__sync_fetch_and_and_16:
400 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_and, E);
401 case Builtin::BI__sync_fetch_and_xor_1:
402 case Builtin::BI__sync_fetch_and_xor_2:
403 case Builtin::BI__sync_fetch_and_xor_4:
404 case Builtin::BI__sync_fetch_and_xor_8:
405 case Builtin::BI__sync_fetch_and_xor_16:
406 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_xor, E);
Chris Lattner94578cb2009-05-13 04:37:52 +0000407 case Builtin::BI__sync_fetch_and_nand_1:
408 case Builtin::BI__sync_fetch_and_nand_2:
409 case Builtin::BI__sync_fetch_and_nand_4:
410 case Builtin::BI__sync_fetch_and_nand_8:
411 case Builtin::BI__sync_fetch_and_nand_16:
412 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_nand, E);
Mike Stump11289f42009-09-09 15:08:12 +0000413
Chris Lattnerdc046542009-05-08 06:58:22 +0000414 // Clang extensions: not overloaded yet.
Mon P Wangb84407d2008-05-09 22:40:52 +0000415 case Builtin::BI__sync_fetch_and_min:
416 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E);
417 case Builtin::BI__sync_fetch_and_max:
418 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_max, E);
419 case Builtin::BI__sync_fetch_and_umin:
420 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umin, E);
421 case Builtin::BI__sync_fetch_and_umax:
422 return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umax, E);
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000423
Chris Lattnerdc046542009-05-08 06:58:22 +0000424 case Builtin::BI__sync_add_and_fetch_1:
425 case Builtin::BI__sync_add_and_fetch_2:
426 case Builtin::BI__sync_add_and_fetch_4:
427 case Builtin::BI__sync_add_and_fetch_8:
428 case Builtin::BI__sync_add_and_fetch_16:
Mike Stump11289f42009-09-09 15:08:12 +0000429 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E,
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000430 llvm::Instruction::Add);
Chris Lattnerdc046542009-05-08 06:58:22 +0000431 case Builtin::BI__sync_sub_and_fetch_1:
432 case Builtin::BI__sync_sub_and_fetch_2:
433 case Builtin::BI__sync_sub_and_fetch_4:
434 case Builtin::BI__sync_sub_and_fetch_8:
435 case Builtin::BI__sync_sub_and_fetch_16:
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000436 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_sub, E,
437 llvm::Instruction::Sub);
Chris Lattnerdc046542009-05-08 06:58:22 +0000438 case Builtin::BI__sync_and_and_fetch_1:
439 case Builtin::BI__sync_and_and_fetch_2:
440 case Builtin::BI__sync_and_and_fetch_4:
441 case Builtin::BI__sync_and_and_fetch_8:
442 case Builtin::BI__sync_and_and_fetch_16:
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000443 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_and, E,
444 llvm::Instruction::And);
Chris Lattnerdc046542009-05-08 06:58:22 +0000445 case Builtin::BI__sync_or_and_fetch_1:
446 case Builtin::BI__sync_or_and_fetch_2:
447 case Builtin::BI__sync_or_and_fetch_4:
448 case Builtin::BI__sync_or_and_fetch_8:
449 case Builtin::BI__sync_or_and_fetch_16:
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000450 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_or, E,
451 llvm::Instruction::Or);
Chris Lattnerdc046542009-05-08 06:58:22 +0000452 case Builtin::BI__sync_xor_and_fetch_1:
453 case Builtin::BI__sync_xor_and_fetch_2:
454 case Builtin::BI__sync_xor_and_fetch_4:
455 case Builtin::BI__sync_xor_and_fetch_8:
456 case Builtin::BI__sync_xor_and_fetch_16:
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000457 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_xor, E,
458 llvm::Instruction::Xor);
Chris Lattner94578cb2009-05-13 04:37:52 +0000459 case Builtin::BI__sync_nand_and_fetch_1:
460 case Builtin::BI__sync_nand_and_fetch_2:
461 case Builtin::BI__sync_nand_and_fetch_4:
462 case Builtin::BI__sync_nand_and_fetch_8:
463 case Builtin::BI__sync_nand_and_fetch_16:
464 return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_nand, E,
465 llvm::Instruction::And);
Mike Stump11289f42009-09-09 15:08:12 +0000466
Chris Lattnerdc046542009-05-08 06:58:22 +0000467 case Builtin::BI__sync_val_compare_and_swap_1:
468 case Builtin::BI__sync_val_compare_and_swap_2:
469 case Builtin::BI__sync_val_compare_and_swap_4:
470 case Builtin::BI__sync_val_compare_and_swap_8:
471 case Builtin::BI__sync_val_compare_and_swap_16:
472 {
Mon P Wangb160a0d2008-07-31 03:28:23 +0000473 const llvm::Type *ResType[2];
474 ResType[0]= ConvertType(E->getType());
475 ResType[1] = ConvertType(E->getArg(0)->getType());
476 Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
Mike Stump11289f42009-09-09 15:08:12 +0000477 return RValue::get(Builder.CreateCall3(AtomF,
Anders Carlsson7e1e5712008-08-30 16:17:45 +0000478 EmitScalarExpr(E->getArg(0)),
479 EmitScalarExpr(E->getArg(1)),
480 EmitScalarExpr(E->getArg(2))));
Anders Carlssonceced4c2007-10-29 02:59:40 +0000481 }
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000482
Chris Lattnerdc046542009-05-08 06:58:22 +0000483 case Builtin::BI__sync_bool_compare_and_swap_1:
484 case Builtin::BI__sync_bool_compare_and_swap_2:
485 case Builtin::BI__sync_bool_compare_and_swap_4:
486 case Builtin::BI__sync_bool_compare_and_swap_8:
487 case Builtin::BI__sync_bool_compare_and_swap_16:
488 {
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000489 const llvm::Type *ResType[2];
Chris Lattnerdc046542009-05-08 06:58:22 +0000490 ResType[0]= ConvertType(E->getArg(1)->getType());
Owen Anderson9793f0e2009-07-29 22:16:19 +0000491 ResType[1] = llvm::PointerType::getUnqual(ResType[0]);
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000492 Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, ResType, 2);
493 Value *OldVal = EmitScalarExpr(E->getArg(1));
Mike Stump11289f42009-09-09 15:08:12 +0000494 Value *PrevVal = Builder.CreateCall3(AtomF,
Daniel Dunbar4fab57d2009-04-07 00:55:51 +0000495 EmitScalarExpr(E->getArg(0)),
496 OldVal,
497 EmitScalarExpr(E->getArg(2)));
498 Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal);
499 // zext bool to int.
500 return RValue::get(Builder.CreateZExt(Result, ConvertType(E->getType())));
501 }
502
Chris Lattnerdc046542009-05-08 06:58:22 +0000503 case Builtin::BI__sync_lock_test_and_set_1:
504 case Builtin::BI__sync_lock_test_and_set_2:
505 case Builtin::BI__sync_lock_test_and_set_4:
506 case Builtin::BI__sync_lock_test_and_set_8:
507 case Builtin::BI__sync_lock_test_and_set_16:
Nate Begeman6c591322008-05-15 07:38:03 +0000508 return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
Chris Lattnerdc046542009-05-08 06:58:22 +0000509 case Builtin::BI__sync_lock_release_1:
510 case Builtin::BI__sync_lock_release_2:
511 case Builtin::BI__sync_lock_release_4:
512 case Builtin::BI__sync_lock_release_8:
Chris Lattnerafde2592009-05-13 04:46:13 +0000513 case Builtin::BI__sync_lock_release_16: {
514 Value *Ptr = EmitScalarExpr(E->getArg(0));
515 const llvm::Type *ElTy =
516 cast<llvm::PointerType>(Ptr->getType())->getElementType();
Owen Anderson0b75f232009-07-31 20:28:54 +0000517 Builder.CreateStore(llvm::Constant::getNullValue(ElTy), Ptr, true);
Daniel Dunbar16f422e2009-05-27 23:45:33 +0000518 return RValue::get(0);
Chris Lattnerafde2592009-05-13 04:46:13 +0000519 }
Daniel Dunbar8eb018a2009-02-16 22:43:43 +0000520
Chris Lattnerafde2592009-05-13 04:46:13 +0000521 case Builtin::BI__sync_synchronize: {
522 Value *C[5];
Owen Anderson41a75022009-08-13 21:57:51 +0000523 C[0] = C[1] = C[2] = C[3] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 1);
524 C[4] = llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), 0);
Chris Lattnerafde2592009-05-13 04:46:13 +0000525 Builder.CreateCall(CGM.getIntrinsic(Intrinsic::memory_barrier), C, C + 5);
Daniel Dunbar16f422e2009-05-27 23:45:33 +0000526 return RValue::get(0);
Chris Lattnerafde2592009-05-13 04:46:13 +0000527 }
Mike Stump11289f42009-09-09 15:08:12 +0000528
Daniel Dunbar8eb018a2009-02-16 22:43:43 +0000529 // Library functions with special handling.
Daniel Dunbar8eb018a2009-02-16 22:43:43 +0000530 case Builtin::BIsqrt:
531 case Builtin::BIsqrtf:
532 case Builtin::BIsqrtl: {
533 // Rewrite sqrt to intrinsic if allowed.
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +0000534 if (!FD->hasAttr<ConstAttr>())
Daniel Dunbar8eb018a2009-02-16 22:43:43 +0000535 break;
536 Value *Arg0 = EmitScalarExpr(E->getArg(0));
537 const llvm::Type *ArgType = Arg0->getType();
538 Value *F = CGM.getIntrinsic(Intrinsic::sqrt, &ArgType, 1);
539 return RValue::get(Builder.CreateCall(F, Arg0, "tmp"));
540 }
541
542 case Builtin::BIpow:
543 case Builtin::BIpowf:
544 case Builtin::BIpowl: {
545 // Rewrite sqrt to intrinsic if allowed.
Argyrios Kyrtzidisb4b64ca2009-06-30 02:34:44 +0000546 if (!FD->hasAttr<ConstAttr>())
Daniel Dunbar8eb018a2009-02-16 22:43:43 +0000547 break;
548 Value *Base = EmitScalarExpr(E->getArg(0));
549 Value *Exponent = EmitScalarExpr(E->getArg(1));
550 const llvm::Type *ArgType = Base->getType();
551 Value *F = CGM.getIntrinsic(Intrinsic::pow, &ArgType, 1);
552 return RValue::get(Builder.CreateCall2(F, Base, Exponent, "tmp"));
553 }
Nate Begeman6c591322008-05-15 07:38:03 +0000554 }
Mike Stump11289f42009-09-09 15:08:12 +0000555
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000556 // If this is an alias for a libm function (e.g. __builtin_sin) turn it into
557 // that function.
Douglas Gregorb9063fc2009-02-13 23:20:09 +0000558 if (getContext().BuiltinInfo.isLibFunction(BuiltinID) ||
559 getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID))
Daniel Dunbarff0553e2009-09-14 04:33:21 +0000560 return EmitCall(CGM.getBuiltinLibFunction(FD, BuiltinID),
Anders Carlsson3a9463b2009-05-27 01:22:39 +0000561 E->getCallee()->getType(), E->arg_begin(),
562 E->arg_end());
Mike Stump11289f42009-09-09 15:08:12 +0000563
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000564 // See if we have a target specific intrinsic.
Dale Johannesen621c3512009-02-05 01:50:47 +0000565 const char *Name = getContext().BuiltinInfo.GetName(BuiltinID);
Daniel Dunbar576d90d2009-08-24 09:54:37 +0000566 Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
567 if (const char *Prefix =
Mike Stump11289f42009-09-09 15:08:12 +0000568 llvm::Triple::getArchTypePrefix(Target.getTriple().getArch()))
Daniel Dunbar576d90d2009-08-24 09:54:37 +0000569 IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name);
Mike Stump11289f42009-09-09 15:08:12 +0000570
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000571 if (IntrinsicID != Intrinsic::not_intrinsic) {
572 SmallVector<Value*, 16> Args;
Mike Stump11289f42009-09-09 15:08:12 +0000573
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000574 Function *F = CGM.getIntrinsic(IntrinsicID);
575 const llvm::FunctionType *FTy = F->getFunctionType();
Mike Stump11289f42009-09-09 15:08:12 +0000576
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000577 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
578 Value *ArgValue = EmitScalarExpr(E->getArg(i));
Mike Stump11289f42009-09-09 15:08:12 +0000579
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000580 // If the intrinsic arg type is different from the builtin arg type
581 // we need to do a bit cast.
582 const llvm::Type *PTy = FTy->getParamType(i);
583 if (PTy != ArgValue->getType()) {
584 assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
585 "Must be able to losslessly bit cast to param");
586 ArgValue = Builder.CreateBitCast(ArgValue, PTy);
587 }
Mike Stump11289f42009-09-09 15:08:12 +0000588
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000589 Args.push_back(ArgValue);
590 }
Mike Stump11289f42009-09-09 15:08:12 +0000591
Jay Foad7d0479f2009-05-21 09:52:38 +0000592 Value *V = Builder.CreateCall(F, Args.data(), Args.data() + Args.size());
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000593 QualType BuiltinRetType = E->getType();
Mike Stump11289f42009-09-09 15:08:12 +0000594
Owen Anderson41a75022009-08-13 21:57:51 +0000595 const llvm::Type *RetTy = llvm::Type::getVoidTy(VMContext);
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000596 if (!BuiltinRetType->isVoidType()) RetTy = ConvertType(BuiltinRetType);
Mike Stump11289f42009-09-09 15:08:12 +0000597
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000598 if (RetTy != V->getType()) {
599 assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
600 "Must be able to losslessly bit cast result type");
601 V = Builder.CreateBitCast(V, RetTy);
602 }
Mike Stump11289f42009-09-09 15:08:12 +0000603
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000604 return RValue::get(V);
605 }
Mike Stump11289f42009-09-09 15:08:12 +0000606
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000607 // See if we have a target specific builtin that needs to be lowered.
Daniel Dunbareca513d2008-10-10 00:24:54 +0000608 if (Value *V = EmitTargetBuiltinExpr(BuiltinID, E))
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000609 return RValue::get(V);
Mike Stump11289f42009-09-09 15:08:12 +0000610
Daniel Dunbara7c8cf62008-08-16 00:56:44 +0000611 ErrorUnsupported(E, "builtin function");
Mike Stump11289f42009-09-09 15:08:12 +0000612
Chris Lattner9a8d1d92008-06-30 18:32:54 +0000613 // Unknown builtin, for now just dump it out and return undef.
614 if (hasAggregateLLVMType(E->getType()))
615 return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType())));
Owen Anderson7ec07a52009-07-30 23:11:26 +0000616 return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
Mike Stump11289f42009-09-09 15:08:12 +0000617}
Anders Carlsson895af082007-12-09 23:17:02 +0000618
Daniel Dunbareca513d2008-10-10 00:24:54 +0000619Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID,
620 const CallExpr *E) {
Daniel Dunbar576d90d2009-08-24 09:54:37 +0000621 switch (Target.getTriple().getArch()) {
622 case llvm::Triple::x86:
623 case llvm::Triple::x86_64:
Daniel Dunbareca513d2008-10-10 00:24:54 +0000624 return EmitX86BuiltinExpr(BuiltinID, E);
Daniel Dunbar576d90d2009-08-24 09:54:37 +0000625 case llvm::Triple::ppc:
626 case llvm::Triple::ppc64:
Daniel Dunbareca513d2008-10-10 00:24:54 +0000627 return EmitPPCBuiltinExpr(BuiltinID, E);
Daniel Dunbar576d90d2009-08-24 09:54:37 +0000628 default:
629 return 0;
630 }
Daniel Dunbareca513d2008-10-10 00:24:54 +0000631}
632
Mike Stump11289f42009-09-09 15:08:12 +0000633Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Chris Lattner13653d72007-12-13 07:34:23 +0000634 const CallExpr *E) {
Mike Stump11289f42009-09-09 15:08:12 +0000635
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000636 llvm::SmallVector<Value*, 4> Ops;
637
638 for (unsigned i = 0, e = E->getNumArgs(); i != e; i++)
639 Ops.push_back(EmitScalarExpr(E->getArg(i)));
640
Anders Carlsson895af082007-12-09 23:17:02 +0000641 switch (BuiltinID) {
Anders Carlsson92c4e442007-12-09 23:39:18 +0000642 default: return 0;
Mike Stump11289f42009-09-09 15:08:12 +0000643 case X86::BI__builtin_ia32_pslldi128:
Nate Begeman91f40e32008-04-14 04:49:57 +0000644 case X86::BI__builtin_ia32_psllqi128:
Mike Stump11289f42009-09-09 15:08:12 +0000645 case X86::BI__builtin_ia32_psllwi128:
Nate Begeman91f40e32008-04-14 04:49:57 +0000646 case X86::BI__builtin_ia32_psradi128:
647 case X86::BI__builtin_ia32_psrawi128:
648 case X86::BI__builtin_ia32_psrldi128:
649 case X86::BI__builtin_ia32_psrlqi128:
650 case X86::BI__builtin_ia32_psrlwi128: {
Owen Anderson41a75022009-08-13 21:57:51 +0000651 Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext");
652 const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 2);
653 llvm::Value *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0);
Owen Anderson7ec07a52009-07-30 23:11:26 +0000654 Ops[1] = Builder.CreateInsertElement(llvm::UndefValue::get(Ty),
Nate Begeman91f40e32008-04-14 04:49:57 +0000655 Ops[1], Zero, "insert");
656 Ops[1] = Builder.CreateBitCast(Ops[1], Ops[0]->getType(), "bitcast");
657 const char *name = 0;
658 Intrinsic::ID ID = Intrinsic::not_intrinsic;
Mike Stump11289f42009-09-09 15:08:12 +0000659
Nate Begeman91f40e32008-04-14 04:49:57 +0000660 switch (BuiltinID) {
661 default: assert(0 && "Unsupported shift intrinsic!");
662 case X86::BI__builtin_ia32_pslldi128:
663 name = "pslldi";
664 ID = Intrinsic::x86_sse2_psll_d;
665 break;
666 case X86::BI__builtin_ia32_psllqi128:
667 name = "psllqi";
668 ID = Intrinsic::x86_sse2_psll_q;
669 break;
670 case X86::BI__builtin_ia32_psllwi128:
671 name = "psllwi";
672 ID = Intrinsic::x86_sse2_psll_w;
673 break;
674 case X86::BI__builtin_ia32_psradi128:
675 name = "psradi";
676 ID = Intrinsic::x86_sse2_psra_d;
677 break;
678 case X86::BI__builtin_ia32_psrawi128:
679 name = "psrawi";
680 ID = Intrinsic::x86_sse2_psra_w;
681 break;
682 case X86::BI__builtin_ia32_psrldi128:
683 name = "psrldi";
684 ID = Intrinsic::x86_sse2_psrl_d;
685 break;
686 case X86::BI__builtin_ia32_psrlqi128:
687 name = "psrlqi";
688 ID = Intrinsic::x86_sse2_psrl_q;
689 break;
690 case X86::BI__builtin_ia32_psrlwi128:
691 name = "psrlwi";
692 ID = Intrinsic::x86_sse2_psrl_w;
693 break;
694 }
695 llvm::Function *F = CGM.getIntrinsic(ID);
Mike Stump11289f42009-09-09 15:08:12 +0000696 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name);
Nate Begeman91f40e32008-04-14 04:49:57 +0000697 }
Mike Stump11289f42009-09-09 15:08:12 +0000698 case X86::BI__builtin_ia32_pslldi:
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000699 case X86::BI__builtin_ia32_psllqi:
Mike Stump11289f42009-09-09 15:08:12 +0000700 case X86::BI__builtin_ia32_psllwi:
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000701 case X86::BI__builtin_ia32_psradi:
702 case X86::BI__builtin_ia32_psrawi:
703 case X86::BI__builtin_ia32_psrldi:
704 case X86::BI__builtin_ia32_psrlqi:
705 case X86::BI__builtin_ia32_psrlwi: {
Owen Anderson41a75022009-08-13 21:57:51 +0000706 Ops[1] = Builder.CreateZExt(Ops[1], llvm::Type::getInt64Ty(VMContext), "zext");
707 const llvm::Type *Ty = llvm::VectorType::get(llvm::Type::getInt64Ty(VMContext), 1);
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000708 Ops[1] = Builder.CreateBitCast(Ops[1], Ty, "bitcast");
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000709 const char *name = 0;
710 Intrinsic::ID ID = Intrinsic::not_intrinsic;
Mike Stump11289f42009-09-09 15:08:12 +0000711
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000712 switch (BuiltinID) {
713 default: assert(0 && "Unsupported shift intrinsic!");
714 case X86::BI__builtin_ia32_pslldi:
715 name = "pslldi";
716 ID = Intrinsic::x86_mmx_psll_d;
717 break;
718 case X86::BI__builtin_ia32_psllqi:
719 name = "psllqi";
720 ID = Intrinsic::x86_mmx_psll_q;
721 break;
722 case X86::BI__builtin_ia32_psllwi:
723 name = "psllwi";
724 ID = Intrinsic::x86_mmx_psll_w;
725 break;
726 case X86::BI__builtin_ia32_psradi:
727 name = "psradi";
728 ID = Intrinsic::x86_mmx_psra_d;
729 break;
730 case X86::BI__builtin_ia32_psrawi:
731 name = "psrawi";
732 ID = Intrinsic::x86_mmx_psra_w;
733 break;
734 case X86::BI__builtin_ia32_psrldi:
735 name = "psrldi";
736 ID = Intrinsic::x86_mmx_psrl_d;
737 break;
738 case X86::BI__builtin_ia32_psrlqi:
739 name = "psrlqi";
740 ID = Intrinsic::x86_mmx_psrl_q;
741 break;
742 case X86::BI__builtin_ia32_psrlwi:
743 name = "psrlwi";
744 ID = Intrinsic::x86_mmx_psrl_w;
745 break;
746 }
Chris Lattnerb8be97e2007-12-18 00:25:38 +0000747 llvm::Function *F = CGM.getIntrinsic(ID);
Mike Stump11289f42009-09-09 15:08:12 +0000748 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), name);
Anders Carlsson4d3094a2007-12-14 17:48:24 +0000749 }
Anders Carlsson20812002009-05-18 19:16:46 +0000750 case X86::BI__builtin_ia32_cmpps: {
751 llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ps);
752 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpps");
753 }
754 case X86::BI__builtin_ia32_cmpss: {
755 llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse_cmp_ss);
756 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpss");
Anders Carlssonca6bcae2007-12-16 22:33:50 +0000757 }
Nate Begeman91f40e32008-04-14 04:49:57 +0000758 case X86::BI__builtin_ia32_ldmxcsr: {
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000759 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Owen Anderson41a75022009-08-13 21:57:51 +0000760 Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1);
761 Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp");
Nate Begeman91f40e32008-04-14 04:49:57 +0000762 Builder.CreateStore(Ops[0], Tmp);
763 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_ldmxcsr),
Chris Lattnerdbcc2ca2008-05-06 00:56:42 +0000764 Builder.CreateBitCast(Tmp, PtrTy));
Nate Begeman91f40e32008-04-14 04:49:57 +0000765 }
766 case X86::BI__builtin_ia32_stmxcsr: {
Benjamin Kramerabd5b902009-10-13 10:07:13 +0000767 const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
Owen Anderson41a75022009-08-13 21:57:51 +0000768 Value *One = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1);
769 Value *Tmp = Builder.CreateAlloca(llvm::Type::getInt32Ty(VMContext), One, "tmp");
Nate Begeman91f40e32008-04-14 04:49:57 +0000770 One = Builder.CreateCall(CGM.getIntrinsic(Intrinsic::x86_sse_stmxcsr),
Chris Lattnerdbcc2ca2008-05-06 00:56:42 +0000771 Builder.CreateBitCast(Tmp, PtrTy));
Nate Begeman91f40e32008-04-14 04:49:57 +0000772 return Builder.CreateLoad(Tmp, "stmxcsr");
773 }
Anders Carlsson20812002009-05-18 19:16:46 +0000774 case X86::BI__builtin_ia32_cmppd: {
775 llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_pd);
776 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmppd");
777 }
778 case X86::BI__builtin_ia32_cmpsd: {
779 llvm::Function *F = CGM.getIntrinsic(Intrinsic::x86_sse2_cmp_sd);
780 return Builder.CreateCall(F, &Ops[0], &Ops[0] + Ops.size(), "cmpsd");
Anders Carlssonca6bcae2007-12-16 22:33:50 +0000781 }
Nate Begeman91f40e32008-04-14 04:49:57 +0000782 case X86::BI__builtin_ia32_storehps:
783 case X86::BI__builtin_ia32_storelps: {
Owen Anderson41a75022009-08-13 21:57:51 +0000784 const llvm::Type *EltTy = llvm::Type::getInt64Ty(VMContext);
Owen Anderson9793f0e2009-07-29 22:16:19 +0000785 llvm::Type *PtrTy = llvm::PointerType::getUnqual(EltTy);
786 llvm::Type *VecTy = llvm::VectorType::get(EltTy, 2);
Mike Stump11289f42009-09-09 15:08:12 +0000787
Nate Begeman91f40e32008-04-14 04:49:57 +0000788 // cast val v2i64
789 Ops[1] = Builder.CreateBitCast(Ops[1], VecTy, "cast");
Mike Stump11289f42009-09-09 15:08:12 +0000790
Nate Begeman91f40e32008-04-14 04:49:57 +0000791 // extract (0, 1)
792 unsigned Index = BuiltinID == X86::BI__builtin_ia32_storelps ? 0 : 1;
Owen Anderson41a75022009-08-13 21:57:51 +0000793 llvm::Value *Idx = llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), Index);
Nate Begeman91f40e32008-04-14 04:49:57 +0000794 Ops[1] = Builder.CreateExtractElement(Ops[1], Idx, "extract");
795
796 // cast pointer to i64 & store
797 Ops[0] = Builder.CreateBitCast(Ops[0], PtrTy);
798 return Builder.CreateStore(Ops[1], Ops[0]);
799 }
Anders Carlsson895af082007-12-09 23:17:02 +0000800 }
801}
802
Mike Stump11289f42009-09-09 15:08:12 +0000803Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Chris Lattner13653d72007-12-13 07:34:23 +0000804 const CallExpr *E) {
Anders Carlsson895af082007-12-09 23:17:02 +0000805 switch (BuiltinID) {
Anders Carlsson92c4e442007-12-09 23:39:18 +0000806 default: return 0;
Anders Carlsson895af082007-12-09 23:17:02 +0000807 }
Mike Stump11289f42009-09-09 15:08:12 +0000808}