1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Builtin calls as CIR or a function call to be
10*700637cbSDimitry Andric // later resolved.
11*700637cbSDimitry Andric //
12*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
13*700637cbSDimitry Andric
14*700637cbSDimitry Andric #include "CIRGenCall.h"
15*700637cbSDimitry Andric #include "CIRGenConstantEmitter.h"
16*700637cbSDimitry Andric #include "CIRGenFunction.h"
17*700637cbSDimitry Andric #include "CIRGenModule.h"
18*700637cbSDimitry Andric #include "CIRGenValue.h"
19*700637cbSDimitry Andric #include "mlir/IR/BuiltinAttributes.h"
20*700637cbSDimitry Andric #include "mlir/IR/Value.h"
21*700637cbSDimitry Andric #include "mlir/Support/LLVM.h"
22*700637cbSDimitry Andric #include "clang/AST/Expr.h"
23*700637cbSDimitry Andric #include "clang/AST/GlobalDecl.h"
24*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
25*700637cbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
26*700637cbSDimitry Andric
27*700637cbSDimitry Andric using namespace clang;
28*700637cbSDimitry Andric using namespace clang::CIRGen;
29*700637cbSDimitry Andric using namespace llvm;
30*700637cbSDimitry Andric
emitLibraryCall(CIRGenFunction & cgf,const FunctionDecl * fd,const CallExpr * e,mlir::Operation * calleeValue)31*700637cbSDimitry Andric static RValue emitLibraryCall(CIRGenFunction &cgf, const FunctionDecl *fd,
32*700637cbSDimitry Andric const CallExpr *e, mlir::Operation *calleeValue) {
33*700637cbSDimitry Andric CIRGenCallee callee = CIRGenCallee::forDirect(calleeValue, GlobalDecl(fd));
34*700637cbSDimitry Andric return cgf.emitCall(e->getCallee()->getType(), callee, e, ReturnValueSlot());
35*700637cbSDimitry Andric }
36*700637cbSDimitry Andric
37*700637cbSDimitry Andric template <typename Op>
emitBuiltinBitOp(CIRGenFunction & cgf,const CallExpr * e,bool poisonZero=false)38*700637cbSDimitry Andric static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e,
39*700637cbSDimitry Andric bool poisonZero = false) {
40*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCheckKind());
41*700637cbSDimitry Andric
42*700637cbSDimitry Andric mlir::Value arg = cgf.emitScalarExpr(e->getArg(0));
43*700637cbSDimitry Andric CIRGenBuilderTy &builder = cgf.getBuilder();
44*700637cbSDimitry Andric
45*700637cbSDimitry Andric Op op;
46*700637cbSDimitry Andric if constexpr (std::is_same_v<Op, cir::BitClzOp> ||
47*700637cbSDimitry Andric std::is_same_v<Op, cir::BitCtzOp>)
48*700637cbSDimitry Andric op = builder.create<Op>(cgf.getLoc(e->getSourceRange()), arg, poisonZero);
49*700637cbSDimitry Andric else
50*700637cbSDimitry Andric op = builder.create<Op>(cgf.getLoc(e->getSourceRange()), arg);
51*700637cbSDimitry Andric
52*700637cbSDimitry Andric mlir::Value result = op.getResult();
53*700637cbSDimitry Andric mlir::Type exprTy = cgf.convertType(e->getType());
54*700637cbSDimitry Andric if (exprTy != result.getType())
55*700637cbSDimitry Andric result = builder.createIntCast(result, exprTy);
56*700637cbSDimitry Andric
57*700637cbSDimitry Andric return RValue::get(result);
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric
emitBuiltinExpr(const GlobalDecl & gd,unsigned builtinID,const CallExpr * e,ReturnValueSlot returnValue)60*700637cbSDimitry Andric RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
61*700637cbSDimitry Andric const CallExpr *e,
62*700637cbSDimitry Andric ReturnValueSlot returnValue) {
63*700637cbSDimitry Andric mlir::Location loc = getLoc(e->getSourceRange());
64*700637cbSDimitry Andric
65*700637cbSDimitry Andric // See if we can constant fold this builtin. If so, don't emit it at all.
66*700637cbSDimitry Andric // TODO: Extend this handling to all builtin calls that we can constant-fold.
67*700637cbSDimitry Andric Expr::EvalResult result;
68*700637cbSDimitry Andric if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
69*700637cbSDimitry Andric !result.hasSideEffects()) {
70*700637cbSDimitry Andric if (result.Val.isInt())
71*700637cbSDimitry Andric return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
72*700637cbSDimitry Andric if (result.Val.isFloat()) {
73*700637cbSDimitry Andric // Note: we are using result type of CallExpr to determine the type of
74*700637cbSDimitry Andric // the constant. Classic codegen uses the result value to determine the
75*700637cbSDimitry Andric // type. We feel it should be Ok to use expression type because it is
76*700637cbSDimitry Andric // hard to imagine a builtin function evaluates to a value that
77*700637cbSDimitry Andric // over/underflows its own defined type.
78*700637cbSDimitry Andric mlir::Type type = convertType(e->getType());
79*700637cbSDimitry Andric return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
80*700637cbSDimitry Andric }
81*700637cbSDimitry Andric }
82*700637cbSDimitry Andric
83*700637cbSDimitry Andric const FunctionDecl *fd = gd.getDecl()->getAsFunction();
84*700637cbSDimitry Andric
85*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCallF128());
86*700637cbSDimitry Andric
87*700637cbSDimitry Andric // If the builtin has been declared explicitly with an assembler label,
88*700637cbSDimitry Andric // disable the specialized emitting below. Ideally we should communicate the
89*700637cbSDimitry Andric // rename in IR, or at least avoid generating the intrinsic calls that are
90*700637cbSDimitry Andric // likely to get lowered to the renamed library functions.
91*700637cbSDimitry Andric unsigned builtinIDIfNoAsmLabel = fd->hasAttr<AsmLabelAttr>() ? 0 : builtinID;
92*700637cbSDimitry Andric
93*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCallMathErrno());
94*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCall());
95*700637cbSDimitry Andric
96*700637cbSDimitry Andric switch (builtinIDIfNoAsmLabel) {
97*700637cbSDimitry Andric default:
98*700637cbSDimitry Andric break;
99*700637cbSDimitry Andric
100*700637cbSDimitry Andric case Builtin::BI__assume:
101*700637cbSDimitry Andric case Builtin::BI__builtin_assume: {
102*700637cbSDimitry Andric if (e->getArg(0)->HasSideEffects(getContext()))
103*700637cbSDimitry Andric return RValue::get(nullptr);
104*700637cbSDimitry Andric
105*700637cbSDimitry Andric mlir::Value argValue = emitCheckedArgForAssume(e->getArg(0));
106*700637cbSDimitry Andric builder.create<cir::AssumeOp>(loc, argValue);
107*700637cbSDimitry Andric return RValue::get(nullptr);
108*700637cbSDimitry Andric }
109*700637cbSDimitry Andric
110*700637cbSDimitry Andric case Builtin::BI__builtin_complex: {
111*700637cbSDimitry Andric mlir::Value real = emitScalarExpr(e->getArg(0));
112*700637cbSDimitry Andric mlir::Value imag = emitScalarExpr(e->getArg(1));
113*700637cbSDimitry Andric mlir::Value complex = builder.createComplexCreate(loc, real, imag);
114*700637cbSDimitry Andric return RValue::get(complex);
115*700637cbSDimitry Andric }
116*700637cbSDimitry Andric
117*700637cbSDimitry Andric case Builtin::BI__builtin_creal:
118*700637cbSDimitry Andric case Builtin::BI__builtin_crealf:
119*700637cbSDimitry Andric case Builtin::BI__builtin_creall:
120*700637cbSDimitry Andric case Builtin::BIcreal:
121*700637cbSDimitry Andric case Builtin::BIcrealf:
122*700637cbSDimitry Andric case Builtin::BIcreall: {
123*700637cbSDimitry Andric mlir::Value complex = emitComplexExpr(e->getArg(0));
124*700637cbSDimitry Andric mlir::Value real = builder.createComplexReal(loc, complex);
125*700637cbSDimitry Andric return RValue::get(real);
126*700637cbSDimitry Andric }
127*700637cbSDimitry Andric
128*700637cbSDimitry Andric case Builtin::BI__builtin_cimag:
129*700637cbSDimitry Andric case Builtin::BI__builtin_cimagf:
130*700637cbSDimitry Andric case Builtin::BI__builtin_cimagl:
131*700637cbSDimitry Andric case Builtin::BIcimag:
132*700637cbSDimitry Andric case Builtin::BIcimagf:
133*700637cbSDimitry Andric case Builtin::BIcimagl: {
134*700637cbSDimitry Andric mlir::Value complex = emitComplexExpr(e->getArg(0));
135*700637cbSDimitry Andric mlir::Value imag = builder.createComplexImag(loc, complex);
136*700637cbSDimitry Andric return RValue::get(imag);
137*700637cbSDimitry Andric }
138*700637cbSDimitry Andric
139*700637cbSDimitry Andric case Builtin::BI__builtin_clrsb:
140*700637cbSDimitry Andric case Builtin::BI__builtin_clrsbl:
141*700637cbSDimitry Andric case Builtin::BI__builtin_clrsbll:
142*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitClrsbOp>(*this, e);
143*700637cbSDimitry Andric
144*700637cbSDimitry Andric case Builtin::BI__builtin_ctzs:
145*700637cbSDimitry Andric case Builtin::BI__builtin_ctz:
146*700637cbSDimitry Andric case Builtin::BI__builtin_ctzl:
147*700637cbSDimitry Andric case Builtin::BI__builtin_ctzll:
148*700637cbSDimitry Andric case Builtin::BI__builtin_ctzg:
149*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCheckKind());
150*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitCtzOp>(*this, e, /*poisonZero=*/true);
151*700637cbSDimitry Andric
152*700637cbSDimitry Andric case Builtin::BI__builtin_clzs:
153*700637cbSDimitry Andric case Builtin::BI__builtin_clz:
154*700637cbSDimitry Andric case Builtin::BI__builtin_clzl:
155*700637cbSDimitry Andric case Builtin::BI__builtin_clzll:
156*700637cbSDimitry Andric case Builtin::BI__builtin_clzg:
157*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCheckKind());
158*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitClzOp>(*this, e, /*poisonZero=*/true);
159*700637cbSDimitry Andric
160*700637cbSDimitry Andric case Builtin::BI__builtin_parity:
161*700637cbSDimitry Andric case Builtin::BI__builtin_parityl:
162*700637cbSDimitry Andric case Builtin::BI__builtin_parityll:
163*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitParityOp>(*this, e);
164*700637cbSDimitry Andric
165*700637cbSDimitry Andric case Builtin::BI__lzcnt16:
166*700637cbSDimitry Andric case Builtin::BI__lzcnt:
167*700637cbSDimitry Andric case Builtin::BI__lzcnt64:
168*700637cbSDimitry Andric assert(!cir::MissingFeatures::builtinCheckKind());
169*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitClzOp>(*this, e, /*poisonZero=*/false);
170*700637cbSDimitry Andric
171*700637cbSDimitry Andric case Builtin::BI__popcnt16:
172*700637cbSDimitry Andric case Builtin::BI__popcnt:
173*700637cbSDimitry Andric case Builtin::BI__popcnt64:
174*700637cbSDimitry Andric case Builtin::BI__builtin_popcount:
175*700637cbSDimitry Andric case Builtin::BI__builtin_popcountl:
176*700637cbSDimitry Andric case Builtin::BI__builtin_popcountll:
177*700637cbSDimitry Andric case Builtin::BI__builtin_popcountg:
178*700637cbSDimitry Andric return emitBuiltinBitOp<cir::BitPopcountOp>(*this, e);
179*700637cbSDimitry Andric
180*700637cbSDimitry Andric case Builtin::BI__builtin_expect:
181*700637cbSDimitry Andric case Builtin::BI__builtin_expect_with_probability: {
182*700637cbSDimitry Andric mlir::Value argValue = emitScalarExpr(e->getArg(0));
183*700637cbSDimitry Andric mlir::Value expectedValue = emitScalarExpr(e->getArg(1));
184*700637cbSDimitry Andric
185*700637cbSDimitry Andric mlir::FloatAttr probAttr;
186*700637cbSDimitry Andric if (builtinIDIfNoAsmLabel == Builtin::BI__builtin_expect_with_probability) {
187*700637cbSDimitry Andric llvm::APFloat probability(0.0);
188*700637cbSDimitry Andric const Expr *probArg = e->getArg(2);
189*700637cbSDimitry Andric [[maybe_unused]] bool evalSucceeded =
190*700637cbSDimitry Andric probArg->EvaluateAsFloat(probability, cgm.getASTContext());
191*700637cbSDimitry Andric assert(evalSucceeded &&
192*700637cbSDimitry Andric "probability should be able to evaluate as float");
193*700637cbSDimitry Andric bool loseInfo = false; // ignored
194*700637cbSDimitry Andric probability.convert(llvm::APFloat::IEEEdouble(),
195*700637cbSDimitry Andric llvm::RoundingMode::Dynamic, &loseInfo);
196*700637cbSDimitry Andric probAttr = mlir::FloatAttr::get(mlir::Float64Type::get(&getMLIRContext()),
197*700637cbSDimitry Andric probability);
198*700637cbSDimitry Andric }
199*700637cbSDimitry Andric
200*700637cbSDimitry Andric auto result = builder.create<cir::ExpectOp>(
201*700637cbSDimitry Andric loc, argValue.getType(), argValue, expectedValue, probAttr);
202*700637cbSDimitry Andric return RValue::get(result);
203*700637cbSDimitry Andric }
204*700637cbSDimitry Andric
205*700637cbSDimitry Andric case Builtin::BI__builtin_bswap16:
206*700637cbSDimitry Andric case Builtin::BI__builtin_bswap32:
207*700637cbSDimitry Andric case Builtin::BI__builtin_bswap64:
208*700637cbSDimitry Andric case Builtin::BI_byteswap_ushort:
209*700637cbSDimitry Andric case Builtin::BI_byteswap_ulong:
210*700637cbSDimitry Andric case Builtin::BI_byteswap_uint64: {
211*700637cbSDimitry Andric mlir::Value arg = emitScalarExpr(e->getArg(0));
212*700637cbSDimitry Andric return RValue::get(builder.create<cir::ByteSwapOp>(loc, arg));
213*700637cbSDimitry Andric }
214*700637cbSDimitry Andric
215*700637cbSDimitry Andric case Builtin::BI__builtin_bitreverse8:
216*700637cbSDimitry Andric case Builtin::BI__builtin_bitreverse16:
217*700637cbSDimitry Andric case Builtin::BI__builtin_bitreverse32:
218*700637cbSDimitry Andric case Builtin::BI__builtin_bitreverse64: {
219*700637cbSDimitry Andric mlir::Value arg = emitScalarExpr(e->getArg(0));
220*700637cbSDimitry Andric return RValue::get(builder.create<cir::BitReverseOp>(loc, arg));
221*700637cbSDimitry Andric }
222*700637cbSDimitry Andric }
223*700637cbSDimitry Andric
224*700637cbSDimitry Andric // If this is an alias for a lib function (e.g. __builtin_sin), emit
225*700637cbSDimitry Andric // the call using the normal call path, but using the unmangled
226*700637cbSDimitry Andric // version of the function name.
227*700637cbSDimitry Andric if (getContext().BuiltinInfo.isLibFunction(builtinID))
228*700637cbSDimitry Andric return emitLibraryCall(*this, fd, e,
229*700637cbSDimitry Andric cgm.getBuiltinLibFunction(fd, builtinID));
230*700637cbSDimitry Andric
231*700637cbSDimitry Andric cgm.errorNYI(e->getSourceRange(), "unimplemented builtin call");
232*700637cbSDimitry Andric return getUndefRValue(e->getType());
233*700637cbSDimitry Andric }
234*700637cbSDimitry Andric
235*700637cbSDimitry Andric /// Given a builtin id for a function like "__builtin_fabsf", return a Function*
236*700637cbSDimitry Andric /// for "fabsf".
getBuiltinLibFunction(const FunctionDecl * fd,unsigned builtinID)237*700637cbSDimitry Andric cir::FuncOp CIRGenModule::getBuiltinLibFunction(const FunctionDecl *fd,
238*700637cbSDimitry Andric unsigned builtinID) {
239*700637cbSDimitry Andric assert(astContext.BuiltinInfo.isLibFunction(builtinID));
240*700637cbSDimitry Andric
241*700637cbSDimitry Andric // Get the name, skip over the __builtin_ prefix (if necessary). We may have
242*700637cbSDimitry Andric // to build this up so provide a small stack buffer to handle the vast
243*700637cbSDimitry Andric // majority of names.
244*700637cbSDimitry Andric llvm::SmallString<64> name;
245*700637cbSDimitry Andric
246*700637cbSDimitry Andric assert(!cir::MissingFeatures::asmLabelAttr());
247*700637cbSDimitry Andric name = astContext.BuiltinInfo.getName(builtinID).substr(10);
248*700637cbSDimitry Andric
249*700637cbSDimitry Andric GlobalDecl d(fd);
250*700637cbSDimitry Andric mlir::Type type = convertType(fd->getType());
251*700637cbSDimitry Andric return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
252*700637cbSDimitry Andric }
253*700637cbSDimitry Andric
emitCheckedArgForAssume(const Expr * e)254*700637cbSDimitry Andric mlir::Value CIRGenFunction::emitCheckedArgForAssume(const Expr *e) {
255*700637cbSDimitry Andric mlir::Value argValue = evaluateExprAsBool(e);
256*700637cbSDimitry Andric if (!sanOpts.has(SanitizerKind::Builtin))
257*700637cbSDimitry Andric return argValue;
258*700637cbSDimitry Andric
259*700637cbSDimitry Andric assert(!cir::MissingFeatures::sanitizers());
260*700637cbSDimitry Andric cgm.errorNYI(e->getSourceRange(),
261*700637cbSDimitry Andric "emitCheckedArgForAssume: sanitizers are NYI");
262*700637cbSDimitry Andric return {};
263*700637cbSDimitry Andric }
264