xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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