blob: 14e13e6ffce8d2edc05230e27de4bde32575777b [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
Chris Lattnerdc4d2802007-12-02 01:49:16 +000083 WarnUnsupported(E, "builtin function");
Chris Lattner6de93ff2007-08-26 04:17:05 +000084
85 // Unknown builtin, for now just dump it out and return undef.
86 if (hasAggregateLLVMType(E->getType()))
87 return RValue::getAggregate(CreateTempAlloca(ConvertType(E->getType())));
88 return RValue::get(llvm::UndefValue::get(ConvertType(E->getType())));
Anders Carlssonca6fcfa2007-12-09 21:20:04 +000089 }
Chris Lattner6de93ff2007-08-26 04:17:05 +000090 case Builtin::BI__builtin___CFStringMakeConstantString: {
91 const Expr *Arg = E->getArg(0);
92
Anders Carlssond6a275f2007-11-01 00:39:26 +000093 while (1) {
94 if (const ParenExpr *PE = dyn_cast<ParenExpr>(Arg))
95 Arg = PE->getSubExpr();
96 else if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Arg))
97 Arg = CE->getSubExpr();
98 else
99 break;
100 }
Chris Lattner6de93ff2007-08-26 04:17:05 +0000101
102 const StringLiteral *Literal = cast<StringLiteral>(Arg);
103 std::string S(Literal->getStrData(), Literal->getByteLength());
104
105 return RValue::get(CGM.GetAddrOfConstantCFString(S));
Anders Carlsson793680e2007-10-12 23:56:29 +0000106 }
107 case Builtin::BI__builtin_va_start:
108 case Builtin::BI__builtin_va_end: {
109 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
110 const llvm::Type *DestType = llvm::PointerType::get(llvm::Type::Int8Ty);
111 if (ArgValue->getType() != DestType)
112 ArgValue = Builder.CreateBitCast(ArgValue, DestType,
113 ArgValue->getNameStart());
114
115 llvm::Intrinsic::ID inst = (BuiltinID == Builtin::BI__builtin_va_start) ?
116 llvm::Intrinsic::vastart : llvm::Intrinsic::vaend;
117 llvm::Value *F = llvm::Intrinsic::getDeclaration(&CGM.getModule(), inst);
118 llvm::Value *V = Builder.CreateCall(F, ArgValue);
119
120 return RValue::get(V);
121 }
Anders Carlsson89799cf2007-10-29 02:59:40 +0000122 case Builtin::BI__builtin_classify_type: {
123 llvm::APSInt Result(32);
124
125 if (!E->isBuiltinClassifyType(Result))
126 assert(0 && "Expr not __builtin_classify_type!");
127
128 return RValue::get(llvm::ConstantInt::get(Result));
Anders Carlsson022012e2007-08-20 18:05:56 +0000129 }
Anders Carlssond6a275f2007-11-01 00:39:26 +0000130 case Builtin::BI__builtin_constant_p: {
131 llvm::APSInt Result(32);
132
133 // FIXME: Analyze the parameter and check if it is a constant.
134 Result = 0;
135
136 return RValue::get(llvm::ConstantInt::get(Result));
137 }
Anders Carlssonc2251dc2007-11-20 19:05:17 +0000138 case Builtin::BI__builtin_abs: {
139 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
140
141 llvm::BinaryOperator *NegOp =
142 Builder.CreateNeg(ArgValue, (ArgValue->getName() + "neg").c_str());
143 llvm::Value *CmpResult =
144 Builder.CreateICmpSGE(ArgValue, NegOp->getOperand(0), "abscond");
145 llvm::Value *Result =
146 Builder.CreateSelect(CmpResult, ArgValue, NegOp, "abs");
147
148 return RValue::get(Result);
149 }
Oliver Hunt6f0768b2007-12-02 01:03:24 +0000150 case Builtin::BI__builtin_expect: {
151 llvm::Value *Condition = EmitScalarExpr(E->getArg(0));
152 return RValue::get(Condition);
153 }
Anders Carlssondf4852a2007-12-02 21:58:10 +0000154 case Builtin::BI__builtin_bswap32:
155 case Builtin::BI__builtin_bswap64: {
156 llvm::Value *ArgValue = EmitScalarExpr(E->getArg(0));
157 const llvm::Type *ArgType = ArgValue->getType();
158 llvm::Value *F =
159 llvm::Intrinsic::getDeclaration(&CGM.getModule(),
160 llvm::Intrinsic::bswap,
161 &ArgType, 1);
162 llvm::Value *V = Builder.CreateCall(F, ArgValue, "tmp");
163
164 return RValue::get(V);
165 }
Anders Carlssonc8ee7982007-12-05 07:22:48 +0000166 case Builtin::BI__builtin_inff: {
167 llvm::APFloat f(llvm::APFloat::IEEEsingle,
168 llvm::APFloat::fcInfinity, false);
169
170 llvm::Value *V = llvm::ConstantFP::get(llvm::Type::FloatTy, f);
171 return RValue::get(V);
172 }
173 case Builtin::BI__builtin_inf:
174 // FIXME: mapping long double onto double.
175 case Builtin::BI__builtin_infl: {
176 llvm::APFloat f(llvm::APFloat::IEEEdouble,
177 llvm::APFloat::fcInfinity, false);
178
179 llvm::Value *V = llvm::ConstantFP::get(llvm::Type::DoubleTy, f);
180 return RValue::get(V);
181 }
Anders Carlsson89799cf2007-10-29 02:59:40 +0000182 }
183
Anders Carlsson022012e2007-08-20 18:05:56 +0000184 return RValue::get(0);
185}