blob: 7f3bd0ad319907719a5cdc2b567ecd1a6bb6386f [file] [log] [blame]
Anders Carlsson022012e2007-08-20 18:05:56 +00001//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Anders Carlsson and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
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 Carlssonca6fcfa2007-12-09 21:20:04 +000016#include "clang/Basic/TargetInfo.h"
Chris Lattnerbef20ac2007-08-31 04:31:45 +000017#include "clang/AST/ASTContext.h"
Anders Carlsson022012e2007-08-20 18:05:56 +000018#include "clang/AST/Builtins.h"
19#include "clang/AST/Expr.h"
Chris Lattner6de93ff2007-08-26 04:17:05 +000020#include "llvm/Constants.h"
Chris Lattnerc5e940f2007-08-31 04:44:06 +000021#include "llvm/Function.h"
Anders Carlsson793680e2007-10-12 23:56:29 +000022#include "llvm/Intrinsics.h"
23
Anders Carlsson022012e2007-08-20 18:05:56 +000024using namespace clang;
25using namespace CodeGen;
26
Anders Carlssonca6fcfa2007-12-09 21:20:04 +000027using namespace llvm;
28
Chris Lattner6de93ff2007-08-26 04:17:05 +000029RValue CodeGenFunction::EmitBuiltinExpr(unsigned BuiltinID, const CallExpr *E) {
30 switch (BuiltinID) {
Anders Carlssonca6fcfa2007-12-09 21:20:04 +000031 default: {
Chris Lattnerc5e940f2007-08-31 04:44:06 +000032 if (getContext().BuiltinInfo.isLibFunction(BuiltinID))
33 return EmitCallExpr(CGM.getBuiltinLibFunction(BuiltinID), E);
Anders Carlssonca6fcfa2007-12-09 21:20:04 +000034
35 // See if we have a target specific intrinsic.
36 llvm::Intrinsic::ID IntrinsicID;
37 const char *TargetPrefix = Target.getTargetPrefix();
38 const char *BuiltinName = getContext().BuiltinInfo.GetName(BuiltinID);
39#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
40#include "llvm/Intrinsics.gen"
41#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
42
43 if (IntrinsicID != Intrinsic::not_intrinsic) {
44 llvm::SmallVector<llvm::Value*, 16> Args;
45
46 llvm::Function *F = llvm::Intrinsic::getDeclaration(&CGM.getModule(),
47 IntrinsicID);
48
49 const llvm::FunctionType *FTy = F->getFunctionType();
50
51 for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
52 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(i));
53
54 // If the intrinsic arg type is different from the builtin arg type
55 // we need to do a bit cast.
56 const llvm::Type *PTy = FTy->getParamType(i);
57 if (PTy != ArgValue->getType()) {
58 assert(PTy->canLosslesslyBitCastTo(FTy->getParamType(i)) &&
59 "Must be able to losslessly bit cast to param");
60 ArgValue = Builder.CreateBitCast(ArgValue, PTy);
61 }
62
63 Args.push_back(ArgValue);
64 }
65
66 llvm::Value *V = Builder.CreateCall(F, &Args[0], &Args[0] + Args.size());
67
68 QualType BuiltinRetType = E->getType();
69
70 const llvm::Type *RetTy = BuiltinRetType->isVoidType() ?
71 llvm::Type::VoidTy : ConvertType(BuiltinRetType);
72
73 if (RetTy != V->getType()) {
74 assert(V->getType()->canLosslesslyBitCastTo(RetTy) &&
75 "Must be able to losslessly bit cast result type");
76
77 V = Builder.CreateBitCast(V, RetTy);
78 }
79
80 return RValue::get(V);
81 }
Chris Lattnerc5e940f2007-08-31 04:44:06 +000082
Anders Carlsson5adb5702007-12-09 21:51:19 +000083 if (strcmp(TargetPrefix, "x86") == 0) {
84 if (strcmp(BuiltinName, "__builtin_ia32_mulps") == 0) {
85 llvm::Value *V = Builder.CreateMul(EmitScalarExpr(E->getArg(0)),
86 EmitScalarExpr(E->getArg(1)),
87 "result");
88 return RValue::get(V);
89 }
90 }
91
Chris Lattnerdc4d2802007-12-02 01:49:16 +000092 WarnUnsupported(E, "builtin function");
Chris Lattner6de93ff2007-08-26 04:17:05 +000093
94 // Unknown builtin, for now just dump it out and return undef.
95 if (hasAggregateLLVMType(E->getType()))
96 return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType())));
97 return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
Anders Carlssonca6fcfa2007-12-09 21:20:04 +000098 }
Chris Lattner6de93ff2007-08-26 04:17:05 +000099 case Builtin::BI__builtin___CFStringMakeConstantString: {
100 const Expr *Arg = E->getArg(0);
101
Anders Carlssond6a275f2007-11-01 00:39:26 +0000102 while (1) {
103 if (const ParenExpr *PE = dyn_cast<ParenExpr>(Arg))
104 Arg = PE->getSubExpr();
105 else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Arg))
106 Arg = CE->getSubExpr();
107 else
108 break;
109 }
Chris Lattner6de93ff2007-08-26 04:17:05 +0000110
111 const StringLiteral *Literal = cast<StringLiteral>(Arg);
112 std::string S(Literal->getStrData(), Literal->getByteLength());
113
114 return RValue::get(CGM.GetAddrOfConstantCFString(S));
Anders Carlsson793680e2007-10-12 23:56:29 +0000115 }
116 case Builtin::BI__builtin_va_start:
117 case Builtin::BI__builtin_va_end: {
118 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
119 const llvm::Type *DestType = llvm::PointerType::get(llvm::Type::Int8Ty);
120 if (ArgValue->getType() != DestType)
121 ArgValue = Builder.CreateBitCast(ArgValue, DestType,
122 ArgValue->getNameStart());
123
124 llvm::Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_start) ?
125 llvm::Intrinsic::vastart : llvm::Intrinsic::vaend;
126 llvm::Value *F = llvm::Intrinsic::getDeclaration(&CGM.getModule(), inst);
127 llvm::Value *V = Builder.CreateCall(F, ArgValue);
128
129 return RValue::get(V);
130 }
Anders Carlsson89799cf2007-10-29 02:59:40 +0000131 case Builtin::BI__builtin_classify_type: {
132 llvm::APSInt Result(32);
133
134 if (!E->isBuiltinClassifyType(Result))
135 assert(0 && "Expr not __builtin_classify_type!");
136
137 return RValue::get(llvm::ConstantInt::get(Result));
Anders Carlsson022012e2007-08-20 18:05:56 +0000138 }
Anders Carlssond6a275f2007-11-01 00:39:26 +0000139 case Builtin::BI__builtin_constant_p: {
140 llvm::APSInt Result(32);
141
142 // FIXME: Analyze the parameter and check if it is a constant.
143 Result = 0;
144
145 return RValue::get(llvm::ConstantInt::get(Result));
146 }
Anders Carlssonc2251dc2007-11-20 19:05:17 +0000147 case Builtin::BI__builtin_abs: {
148 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
149
150 llvm::BinaryOperator *NegOp =
151 Builder.CreateNeg(ArgValue, (ArgValue->getName() + "neg").c_str());
152 llvm::Value *CmpResult =
153 Builder.CreateICmpSGE(ArgValue, NegOp->getOperand(0), "abscond");
154 llvm::Value *Result =
155 Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs");
156
157 return RValue::get(Result);
158 }
Oliver Hunt6f0768b2007-12-02 01:03:24 +0000159 case Builtin::BI__builtin_expect: {
160 llvm::Value *Condition = EmitScalarExpr(E->getArg(0));
161 return RValue::get(Condition);
162 }
Anders Carlssondf4852a2007-12-02 21:58:10 +0000163 case Builtin::BI__builtin_bswap32:
164 case Builtin::BI__builtin_bswap64: {
165 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
166 const llvm::Type *ArgType = ArgValue->getType();
167 llvm::Value *F =
168 llvm::Intrinsic::getDeclaration(&CGM.getModule(),
169 llvm::Intrinsic::bswap,
170 &ArgType, 1);
171 llvm::Value *V = Builder.CreateCall(F, ArgValue, "tmp");
172
173 return RValue::get(V);
174 }
Anders Carlssonc8ee7982007-12-05 07:22:48 +0000175 case Builtin::BI__builtin_inff: {
176 llvm::APFloat f(llvm::APFloat::IEEEsingle,
177 llvm::APFloat::fcInfinity, false);
178
179 llvm::Value *V = llvm::ConstantFP::get(llvm::Type::FloatTy, f);
180 return RValue::get(V);
181 }
182 case Builtin::BI__builtin_inf:
183 // FIXME: mapping long double onto double.
184 case Builtin::BI__builtin_infl: {
185 llvm::APFloat f(llvm::APFloat::IEEEdouble,
186 llvm::APFloat::fcInfinity, false);
187
188 llvm::Value *V = llvm::ConstantFP::get(llvm::Type::DoubleTy, f);
189 return RValue::get(V);
190 }
Anders Carlsson5adb5702007-12-09 21:51:19 +0000191
Anders Carlsson89799cf2007-10-29 02:59:40 +0000192 }
193
Anders Carlsson022012e2007-08-20 18:05:56 +0000194 return RValue::get(0);
195}