clang 22.0.0git
CIRGenBuiltin.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code to emit Builtin calls as CIR or a function call to be
10// later resolved.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIRGenCall.h"
15#include "CIRGenFunction.h"
16#include "CIRGenModule.h"
17#include "CIRGenValue.h"
18#include "mlir/IR/BuiltinAttributes.h"
19#include "mlir/IR/Value.h"
20#include "mlir/Support/LLVM.h"
21#include "clang/AST/DeclBase.h"
22#include "clang/AST/Expr.h"
28#include "llvm/Support/ErrorHandling.h"
29
30using namespace clang;
31using namespace clang::CIRGen;
32using namespace llvm;
33
35 const CallExpr *e, mlir::Operation *calleeValue) {
36 CIRGenCallee callee = CIRGenCallee::forDirect(calleeValue, GlobalDecl(fd));
37 return cgf.emitCall(e->getCallee()->getType(), callee, e, ReturnValueSlot());
38}
39
40template <typename Op>
42 bool poisonZero = false) {
44
45 mlir::Value arg = cgf.emitScalarExpr(e->getArg(0));
46 CIRGenBuilderTy &builder = cgf.getBuilder();
47
48 Op op;
49 if constexpr (std::is_same_v<Op, cir::BitClzOp> ||
50 std::is_same_v<Op, cir::BitCtzOp>)
51 op = Op::create(builder, cgf.getLoc(e->getSourceRange()), arg, poisonZero);
52 else
53 op = Op::create(builder, cgf.getLoc(e->getSourceRange()), arg);
54
55 mlir::Value result = op.getResult();
56 mlir::Type exprTy = cgf.convertType(e->getType());
57 if (exprTy != result.getType())
58 result = builder.createIntCast(result, exprTy);
59
60 return RValue::get(result);
61}
62
63namespace {
64struct WidthAndSignedness {
65 unsigned width;
66 bool isSigned;
67};
68} // namespace
69
70static WidthAndSignedness
72 const clang::QualType type) {
73 assert(type->isIntegerType() && "Given type is not an integer.");
74 unsigned width = type->isBooleanType() ? 1
75 : type->isBitIntType() ? astContext.getIntWidth(type)
76 : astContext.getTypeInfo(type).Width;
77 bool isSigned = type->isSignedIntegerType();
78 return {width, isSigned};
79}
80
81// Given one or more integer types, this function produces an integer type that
82// encompasses them: any value in one of the given types could be expressed in
83// the encompassing type.
84static struct WidthAndSignedness
85EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> types) {
86 assert(types.size() > 0 && "Empty list of types.");
87
88 // If any of the given types is signed, we must return a signed type.
89 bool isSigned = llvm::any_of(types, [](const auto &t) { return t.isSigned; });
90
91 // The encompassing type must have a width greater than or equal to the width
92 // of the specified types. Additionally, if the encompassing type is signed,
93 // its width must be strictly greater than the width of any unsigned types
94 // given.
95 unsigned width = 0;
96 for (const auto &type : types)
97 width = std::max(width, type.width + (isSigned && !type.isSigned));
98
99 return {width, isSigned};
100}
101
102RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) {
103 mlir::Value input = emitScalarExpr(e->getArg(0));
104 mlir::Value amount = emitScalarExpr(e->getArg(1));
105
106 // TODO(cir): MSVC flavor bit rotate builtins use different types for input
107 // and amount, but cir.rotate requires them to have the same type. Cast amount
108 // to the type of input when necessary.
110
111 auto r = cir::RotateOp::create(builder, getLoc(e->getSourceRange()), input,
112 amount, isRotateLeft);
113 return RValue::get(r);
114}
115
116template <class Operation>
118 const CallExpr &e) {
119 mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
120
123
124 auto call =
125 Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(), arg);
126 return RValue::get(call->getResult(0));
127}
128
129template <class Operation>
131 mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
132 auto call =
133 Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(), arg);
134 return RValue::get(call->getResult(0));
135}
136
138 unsigned builtinID) {
139
140 if (cgf.getContext().BuiltinInfo.isLibFunction(builtinID)) {
141 cgf.cgm.errorNYI(
142 e->getSourceRange(),
143 std::string("unimplemented X86 library function builtin call: ") +
144 cgf.getContext().BuiltinInfo.getName(builtinID));
145 } else {
146 cgf.cgm.errorNYI(e->getSourceRange(),
147 std::string("unimplemented X86 builtin call: ") +
148 cgf.getContext().BuiltinInfo.getName(builtinID));
149 }
150
151 return cgf.getUndefRValue(e->getType());
152}
153
155 unsigned builtinID) {
156 assert(builtinID == Builtin::BI__builtin_alloca ||
157 builtinID == Builtin::BI__builtin_alloca_uninitialized ||
158 builtinID == Builtin::BIalloca || builtinID == Builtin::BI_alloca);
159
160 // Get alloca size input
161 mlir::Value size = cgf.emitScalarExpr(e->getArg(0));
162
163 // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__.
164 const TargetInfo &ti = cgf.getContext().getTargetInfo();
165 const CharUnits suitableAlignmentInBytes =
167
168 // Emit the alloca op with type `u8 *` to match the semantics of
169 // `llvm.alloca`. We later bitcast the type to `void *` to match the
170 // semantics of C/C++
171 // FIXME(cir): It may make sense to allow AllocaOp of type `u8` to return a
172 // pointer of type `void *`. This will require a change to the allocaOp
173 // verifier.
174 CIRGenBuilderTy &builder = cgf.getBuilder();
175 mlir::Value allocaAddr = builder.createAlloca(
176 cgf.getLoc(e->getSourceRange()), builder.getUInt8PtrTy(),
177 builder.getUInt8Ty(), "bi_alloca", suitableAlignmentInBytes, size);
178
179 // Initialize the allocated buffer if required.
180 if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
181 // Initialize the alloca with the given size and alignment according to
182 // the lang opts. Only the trivial non-initialization is supported for
183 // now.
184
185 switch (cgf.getLangOpts().getTrivialAutoVarInit()) {
187 // Nothing to initialize.
188 break;
191 cgf.cgm.errorNYI("trivial auto var init");
192 break;
193 }
194 }
195
196 // An alloca will always return a pointer to the alloca (stack) address
197 // space. This address space need not be the same as the AST / Language
198 // default (e.g. in C / C++ auto vars are in the generic address space). At
199 // the AST level this is handled within CreateTempAlloca et al., but for the
200 // builtin / dynamic alloca we have to handle it here.
201
205 cgf.cgm.errorNYI(e->getSourceRange(),
206 "Non-default address space for alloca");
207 }
208
209 // Bitcast the alloca to the expected type.
210 return RValue::get(builder.createBitcast(
211 allocaAddr, builder.getVoidPtrTy(cgf.getCIRAllocaAddressSpace())));
212}
213
215 const CallExpr *e,
217 mlir::Location loc = getLoc(e->getSourceRange());
218
219 // See if we can constant fold this builtin. If so, don't emit it at all.
220 // TODO: Extend this handling to all builtin calls that we can constant-fold.
221 Expr::EvalResult result;
222 if (e->isPRValue() && e->EvaluateAsRValue(result, cgm.getASTContext()) &&
223 !result.hasSideEffects()) {
224 if (result.Val.isInt())
225 return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
226 if (result.Val.isFloat()) {
227 // Note: we are using result type of CallExpr to determine the type of
228 // the constant. Classic codegen uses the result value to determine the
229 // type. We feel it should be Ok to use expression type because it is
230 // hard to imagine a builtin function evaluates to a value that
231 // over/underflows its own defined type.
232 mlir::Type type = convertType(e->getType());
233 return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
234 }
235 }
236
237 const FunctionDecl *fd = gd.getDecl()->getAsFunction();
238
240
241 // If the builtin has been declared explicitly with an assembler label,
242 // disable the specialized emitting below. Ideally we should communicate the
243 // rename in IR, or at least avoid generating the intrinsic calls that are
244 // likely to get lowered to the renamed library functions.
245 unsigned builtinIDIfNoAsmLabel = fd->hasAttr<AsmLabelAttr>() ? 0 : builtinID;
246
249
250 switch (builtinIDIfNoAsmLabel) {
251 default:
252 break;
253
254 // C stdarg builtins.
255 case Builtin::BI__builtin_stdarg_start:
256 case Builtin::BI__builtin_va_start:
257 case Builtin::BI__va_start: {
258 mlir::Value vaList = builtinID == Builtin::BI__va_start
259 ? emitScalarExpr(e->getArg(0))
261 mlir::Value count = emitScalarExpr(e->getArg(1));
262 emitVAStart(vaList, count);
263 return {};
264 }
265
266 case Builtin::BI__builtin_va_end:
268 return {};
269
270 case Builtin::BIcos:
271 case Builtin::BIcosf:
272 case Builtin::BIcosl:
273 case Builtin::BI__builtin_cos:
274 case Builtin::BI__builtin_cosf:
275 case Builtin::BI__builtin_cosf16:
276 case Builtin::BI__builtin_cosl:
277 case Builtin::BI__builtin_cosf128:
280
281 case Builtin::BIceil:
282 case Builtin::BIceilf:
283 case Builtin::BIceill:
284 case Builtin::BI__builtin_ceil:
285 case Builtin::BI__builtin_ceilf:
286 case Builtin::BI__builtin_ceilf16:
287 case Builtin::BI__builtin_ceill:
288 case Builtin::BI__builtin_ceilf128:
291
292 case Builtin::BIexp:
293 case Builtin::BIexpf:
294 case Builtin::BIexpl:
295 case Builtin::BI__builtin_exp:
296 case Builtin::BI__builtin_expf:
297 case Builtin::BI__builtin_expf16:
298 case Builtin::BI__builtin_expl:
299 case Builtin::BI__builtin_expf128:
302
303 case Builtin::BIfabs:
304 case Builtin::BIfabsf:
305 case Builtin::BIfabsl:
306 case Builtin::BI__builtin_fabs:
307 case Builtin::BI__builtin_fabsf:
308 case Builtin::BI__builtin_fabsf16:
309 case Builtin::BI__builtin_fabsl:
310 case Builtin::BI__builtin_fabsf128:
312
313 case Builtin::BI__assume:
314 case Builtin::BI__builtin_assume: {
315 if (e->getArg(0)->HasSideEffects(getContext()))
316 return RValue::get(nullptr);
317
318 mlir::Value argValue = emitCheckedArgForAssume(e->getArg(0));
319 cir::AssumeOp::create(builder, loc, argValue);
320 return RValue::get(nullptr);
321 }
322
323 case Builtin::BI__builtin_assume_separate_storage: {
324 mlir::Value value0 = emitScalarExpr(e->getArg(0));
325 mlir::Value value1 = emitScalarExpr(e->getArg(1));
326 cir::AssumeSepStorageOp::create(builder, loc, value0, value1);
327 return RValue::get(nullptr);
328 }
329
330 case Builtin::BI__builtin_assume_aligned: {
331 const Expr *ptrExpr = e->getArg(0);
332 mlir::Value ptrValue = emitScalarExpr(ptrExpr);
333 mlir::Value offsetValue =
334 (e->getNumArgs() > 2) ? emitScalarExpr(e->getArg(2)) : nullptr;
335
336 std::optional<llvm::APSInt> alignment =
338 assert(alignment.has_value() &&
339 "the second argument to __builtin_assume_aligned must be an "
340 "integral constant expression");
341
342 mlir::Value result =
343 emitAlignmentAssumption(ptrValue, ptrExpr, ptrExpr->getExprLoc(),
344 alignment->getSExtValue(), offsetValue);
345 return RValue::get(result);
346 }
347
348 case Builtin::BI__builtin_complex: {
349 mlir::Value real = emitScalarExpr(e->getArg(0));
350 mlir::Value imag = emitScalarExpr(e->getArg(1));
351 mlir::Value complex = builder.createComplexCreate(loc, real, imag);
352 return RValue::getComplex(complex);
353 }
354
355 case Builtin::BI__builtin_creal:
356 case Builtin::BI__builtin_crealf:
357 case Builtin::BI__builtin_creall:
358 case Builtin::BIcreal:
359 case Builtin::BIcrealf:
360 case Builtin::BIcreall: {
361 mlir::Value complex = emitComplexExpr(e->getArg(0));
362 mlir::Value real = builder.createComplexReal(loc, complex);
363 return RValue::get(real);
364 }
365
366 case Builtin::BI__builtin_cimag:
367 case Builtin::BI__builtin_cimagf:
368 case Builtin::BI__builtin_cimagl:
369 case Builtin::BIcimag:
370 case Builtin::BIcimagf:
371 case Builtin::BIcimagl: {
372 mlir::Value complex = emitComplexExpr(e->getArg(0));
373 mlir::Value imag = builder.createComplexImag(loc, complex);
374 return RValue::get(imag);
375 }
376
377 case Builtin::BI__builtin_conj:
378 case Builtin::BI__builtin_conjf:
379 case Builtin::BI__builtin_conjl:
380 case Builtin::BIconj:
381 case Builtin::BIconjf:
382 case Builtin::BIconjl: {
383 mlir::Value complex = emitComplexExpr(e->getArg(0));
384 mlir::Value conj = builder.createUnaryOp(getLoc(e->getExprLoc()),
385 cir::UnaryOpKind::Not, complex);
386 return RValue::getComplex(conj);
387 }
388
389 case Builtin::BI__builtin_clrsb:
390 case Builtin::BI__builtin_clrsbl:
391 case Builtin::BI__builtin_clrsbll:
392 return emitBuiltinBitOp<cir::BitClrsbOp>(*this, e);
393
394 case Builtin::BI__builtin_ctzs:
395 case Builtin::BI__builtin_ctz:
396 case Builtin::BI__builtin_ctzl:
397 case Builtin::BI__builtin_ctzll:
398 case Builtin::BI__builtin_ctzg:
400 return emitBuiltinBitOp<cir::BitCtzOp>(*this, e, /*poisonZero=*/true);
401
402 case Builtin::BI__builtin_clzs:
403 case Builtin::BI__builtin_clz:
404 case Builtin::BI__builtin_clzl:
405 case Builtin::BI__builtin_clzll:
406 case Builtin::BI__builtin_clzg:
408 return emitBuiltinBitOp<cir::BitClzOp>(*this, e, /*poisonZero=*/true);
409
410 case Builtin::BI__builtin_ffs:
411 case Builtin::BI__builtin_ffsl:
412 case Builtin::BI__builtin_ffsll:
413 return emitBuiltinBitOp<cir::BitFfsOp>(*this, e);
414
415 case Builtin::BI__builtin_parity:
416 case Builtin::BI__builtin_parityl:
417 case Builtin::BI__builtin_parityll:
418 return emitBuiltinBitOp<cir::BitParityOp>(*this, e);
419
420 case Builtin::BI__lzcnt16:
421 case Builtin::BI__lzcnt:
422 case Builtin::BI__lzcnt64:
424 return emitBuiltinBitOp<cir::BitClzOp>(*this, e, /*poisonZero=*/false);
425
426 case Builtin::BI__popcnt16:
427 case Builtin::BI__popcnt:
428 case Builtin::BI__popcnt64:
429 case Builtin::BI__builtin_popcount:
430 case Builtin::BI__builtin_popcountl:
431 case Builtin::BI__builtin_popcountll:
432 case Builtin::BI__builtin_popcountg:
434
435 case Builtin::BI__builtin_expect:
436 case Builtin::BI__builtin_expect_with_probability: {
437 mlir::Value argValue = emitScalarExpr(e->getArg(0));
438 mlir::Value expectedValue = emitScalarExpr(e->getArg(1));
439
440 mlir::FloatAttr probAttr;
441 if (builtinIDIfNoAsmLabel == Builtin::BI__builtin_expect_with_probability) {
442 llvm::APFloat probability(0.0);
443 const Expr *probArg = e->getArg(2);
444 [[maybe_unused]] bool evalSucceeded =
445 probArg->EvaluateAsFloat(probability, cgm.getASTContext());
446 assert(evalSucceeded &&
447 "probability should be able to evaluate as float");
448 bool loseInfo = false; // ignored
449 probability.convert(llvm::APFloat::IEEEdouble(),
450 llvm::RoundingMode::Dynamic, &loseInfo);
451 probAttr = mlir::FloatAttr::get(mlir::Float64Type::get(&getMLIRContext()),
452 probability);
453 }
454
455 auto result = cir::ExpectOp::create(builder, loc, argValue.getType(),
456 argValue, expectedValue, probAttr);
457 return RValue::get(result);
458 }
459
460 case Builtin::BI__builtin_bswap16:
461 case Builtin::BI__builtin_bswap32:
462 case Builtin::BI__builtin_bswap64:
463 case Builtin::BI_byteswap_ushort:
464 case Builtin::BI_byteswap_ulong:
465 case Builtin::BI_byteswap_uint64: {
466 mlir::Value arg = emitScalarExpr(e->getArg(0));
467 return RValue::get(cir::ByteSwapOp::create(builder, loc, arg));
468 }
469
470 case Builtin::BI__builtin_bitreverse8:
471 case Builtin::BI__builtin_bitreverse16:
472 case Builtin::BI__builtin_bitreverse32:
473 case Builtin::BI__builtin_bitreverse64: {
474 mlir::Value arg = emitScalarExpr(e->getArg(0));
475 return RValue::get(cir::BitReverseOp::create(builder, loc, arg));
476 }
477
478 case Builtin::BI__builtin_rotateleft8:
479 case Builtin::BI__builtin_rotateleft16:
480 case Builtin::BI__builtin_rotateleft32:
481 case Builtin::BI__builtin_rotateleft64:
482 return emitRotate(e, /*isRotateLeft=*/true);
483
484 case Builtin::BI__builtin_rotateright8:
485 case Builtin::BI__builtin_rotateright16:
486 case Builtin::BI__builtin_rotateright32:
487 case Builtin::BI__builtin_rotateright64:
488 return emitRotate(e, /*isRotateLeft=*/false);
489
490 case Builtin::BI__builtin_coro_id:
491 case Builtin::BI__builtin_coro_promise:
492 case Builtin::BI__builtin_coro_resume:
493 case Builtin::BI__builtin_coro_noop:
494 case Builtin::BI__builtin_coro_destroy:
495 case Builtin::BI__builtin_coro_done:
496 case Builtin::BI__builtin_coro_alloc:
497 case Builtin::BI__builtin_coro_begin:
498 case Builtin::BI__builtin_coro_end:
499 case Builtin::BI__builtin_coro_suspend:
500 case Builtin::BI__builtin_coro_align:
501 cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_id like NYI");
502 return getUndefRValue(e->getType());
503
504 case Builtin::BI__builtin_coro_frame: {
505 cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_frame NYI");
507 return getUndefRValue(e->getType());
508 }
509 case Builtin::BI__builtin_coro_free:
510 case Builtin::BI__builtin_coro_size: {
511 GlobalDecl gd{fd};
512 mlir::Type ty = cgm.getTypes().getFunctionType(
513 cgm.getTypes().arrangeGlobalDeclaration(gd));
514 const auto *nd = cast<NamedDecl>(gd.getDecl());
515 cir::FuncOp fnOp =
516 cgm.getOrCreateCIRFunction(nd->getName(), ty, gd, /*ForVTable=*/false);
517 fnOp.setBuiltin(true);
518 return emitCall(e->getCallee()->getType(), CIRGenCallee::forDirect(fnOp), e,
520 }
521 case Builtin::BI__builtin_dynamic_object_size:
522 case Builtin::BI__builtin_object_size: {
523 unsigned type =
524 e->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
525 auto resType = mlir::cast<cir::IntType>(convertType(e->getType()));
526
527 // We pass this builtin onto the optimizer so that it can figure out the
528 // object size in more complex cases.
529 bool isDynamic = builtinID == Builtin::BI__builtin_dynamic_object_size;
530 return RValue::get(emitBuiltinObjectSize(e->getArg(0), type, resType,
531 /*EmittedE=*/nullptr, isDynamic));
532 }
533
534 case Builtin::BI__builtin_prefetch: {
535 auto evaluateOperandAsInt = [&](const Expr *arg) {
537 [[maybe_unused]] bool evalSucceed =
538 arg->EvaluateAsInt(res, cgm.getASTContext());
539 assert(evalSucceed && "expression should be able to evaluate as int");
540 return res.Val.getInt().getZExtValue();
541 };
542
543 bool isWrite = false;
544 if (e->getNumArgs() > 1)
545 isWrite = evaluateOperandAsInt(e->getArg(1));
546
547 int locality = 3;
548 if (e->getNumArgs() > 2)
549 locality = evaluateOperandAsInt(e->getArg(2));
550
551 mlir::Value address = emitScalarExpr(e->getArg(0));
552 cir::PrefetchOp::create(builder, loc, address, locality, isWrite);
553 return RValue::get(nullptr);
554 }
555 case Builtin::BI__builtin_readcyclecounter:
556 case Builtin::BI__builtin_readsteadycounter:
557 case Builtin::BI__builtin___clear_cache:
558 return errorBuiltinNYI(*this, e, builtinID);
559 case Builtin::BI__builtin_trap:
560 emitTrap(loc, /*createNewBlock=*/true);
561 return RValue::getIgnored();
562 case Builtin::BI__builtin_verbose_trap:
563 case Builtin::BI__debugbreak:
564 return errorBuiltinNYI(*this, e, builtinID);
565 case Builtin::BI__builtin_unreachable:
566 emitUnreachable(e->getExprLoc(), /*createNewBlock=*/true);
567 return RValue::getIgnored();
568 case Builtin::BI__builtin_powi:
569 case Builtin::BI__builtin_powif:
570 case Builtin::BI__builtin_powil:
571 case Builtin::BI__builtin_frexpl:
572 case Builtin::BI__builtin_frexp:
573 case Builtin::BI__builtin_frexpf:
574 case Builtin::BI__builtin_frexpf128:
575 case Builtin::BI__builtin_frexpf16:
576 case Builtin::BImodf:
577 case Builtin::BImodff:
578 case Builtin::BImodfl:
579 case Builtin::BI__builtin_modf:
580 case Builtin::BI__builtin_modff:
581 case Builtin::BI__builtin_modfl:
582 case Builtin::BI__builtin_isgreater:
583 case Builtin::BI__builtin_isgreaterequal:
584 case Builtin::BI__builtin_isless:
585 case Builtin::BI__builtin_islessequal:
586 case Builtin::BI__builtin_islessgreater:
587 case Builtin::BI__builtin_isunordered:
588 // From https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass
589 //
590 // The `__builtin_isfpclass()` builtin is a generalization of functions
591 // isnan, isinf, isfinite and some others defined by the C standard. It tests
592 // if the floating-point value, specified by the first argument, falls into
593 // any of data classes, specified by the second argument.
594 case Builtin::BI__builtin_isnan: {
596 mlir::Value v = emitScalarExpr(e->getArg(0));
598 mlir::Location loc = getLoc(e->getBeginLoc());
599 return RValue::get(builder.createBoolToInt(
600 builder.createIsFPClass(loc, v, cir::FPClassTest::Nan),
601 convertType(e->getType())));
602 }
603
604 case Builtin::BI__builtin_issignaling: {
606 mlir::Value v = emitScalarExpr(e->getArg(0));
607 mlir::Location loc = getLoc(e->getBeginLoc());
608 return RValue::get(builder.createBoolToInt(
609 builder.createIsFPClass(loc, v, cir::FPClassTest::SignalingNaN),
610 convertType(e->getType())));
611 }
612
613 case Builtin::BI__builtin_isinf: {
615 mlir::Value v = emitScalarExpr(e->getArg(0));
617 mlir::Location loc = getLoc(e->getBeginLoc());
618 return RValue::get(builder.createBoolToInt(
619 builder.createIsFPClass(loc, v, cir::FPClassTest::Infinity),
620 convertType(e->getType())));
621 }
622 case Builtin::BIfinite:
623 case Builtin::BI__finite:
624 case Builtin::BIfinitef:
625 case Builtin::BI__finitef:
626 case Builtin::BIfinitel:
627 case Builtin::BI__finitel:
628 case Builtin::BI__builtin_isfinite: {
630 mlir::Value v = emitScalarExpr(e->getArg(0));
632 mlir::Location loc = getLoc(e->getBeginLoc());
633 return RValue::get(builder.createBoolToInt(
634 builder.createIsFPClass(loc, v, cir::FPClassTest::Finite),
635 convertType(e->getType())));
636 }
637
638 case Builtin::BI__builtin_isnormal: {
640 mlir::Value v = emitScalarExpr(e->getArg(0));
641 mlir::Location loc = getLoc(e->getBeginLoc());
642 return RValue::get(builder.createBoolToInt(
643 builder.createIsFPClass(loc, v, cir::FPClassTest::Normal),
644 convertType(e->getType())));
645 }
646
647 case Builtin::BI__builtin_issubnormal: {
649 mlir::Value v = emitScalarExpr(e->getArg(0));
650 mlir::Location loc = getLoc(e->getBeginLoc());
651 return RValue::get(builder.createBoolToInt(
652 builder.createIsFPClass(loc, v, cir::FPClassTest::Subnormal),
653 convertType(e->getType())));
654 }
655
656 case Builtin::BI__builtin_iszero: {
658 mlir::Value v = emitScalarExpr(e->getArg(0));
659 mlir::Location loc = getLoc(e->getBeginLoc());
660 return RValue::get(builder.createBoolToInt(
661 builder.createIsFPClass(loc, v, cir::FPClassTest::Zero),
662 convertType(e->getType())));
663 }
664 case Builtin::BI__builtin_isfpclass: {
665 Expr::EvalResult result;
666 if (!e->getArg(1)->EvaluateAsInt(result, cgm.getASTContext()))
667 break;
668
670 mlir::Value v = emitScalarExpr(e->getArg(0));
671 uint64_t test = result.Val.getInt().getLimitedValue();
672 mlir::Location loc = getLoc(e->getBeginLoc());
673 //
674 return RValue::get(builder.createBoolToInt(
675 builder.createIsFPClass(loc, v, cir::FPClassTest(test)),
676 convertType(e->getType())));
677 }
678 case Builtin::BI__builtin_nondeterministic_value:
679 case Builtin::BI__builtin_elementwise_abs:
680 return errorBuiltinNYI(*this, e, builtinID);
681 case Builtin::BI__builtin_elementwise_acos:
682 return emitUnaryFPBuiltin<cir::ACosOp>(*this, *e);
683 case Builtin::BI__builtin_elementwise_asin:
684 return emitUnaryFPBuiltin<cir::ASinOp>(*this, *e);
685 case Builtin::BI__builtin_elementwise_atan:
686 return emitUnaryFPBuiltin<cir::ATanOp>(*this, *e);
687 case Builtin::BI__builtin_elementwise_atan2:
688 case Builtin::BI__builtin_elementwise_ceil:
689 case Builtin::BI__builtin_elementwise_exp:
690 case Builtin::BI__builtin_elementwise_exp2:
691 case Builtin::BI__builtin_elementwise_exp10:
692 case Builtin::BI__builtin_elementwise_ldexp:
693 case Builtin::BI__builtin_elementwise_log:
694 case Builtin::BI__builtin_elementwise_log2:
695 case Builtin::BI__builtin_elementwise_log10:
696 case Builtin::BI__builtin_elementwise_pow:
697 case Builtin::BI__builtin_elementwise_bitreverse:
698 return errorBuiltinNYI(*this, e, builtinID);
699 case Builtin::BI__builtin_elementwise_cos:
700 return emitUnaryFPBuiltin<cir::CosOp>(*this, *e);
701 case Builtin::BI__builtin_elementwise_cosh:
702 case Builtin::BI__builtin_elementwise_floor:
703 case Builtin::BI__builtin_elementwise_popcount:
704 case Builtin::BI__builtin_elementwise_roundeven:
705 case Builtin::BI__builtin_elementwise_round:
706 case Builtin::BI__builtin_elementwise_rint:
707 case Builtin::BI__builtin_elementwise_nearbyint:
708 case Builtin::BI__builtin_elementwise_sin:
709 case Builtin::BI__builtin_elementwise_sinh:
710 case Builtin::BI__builtin_elementwise_tan:
711 case Builtin::BI__builtin_elementwise_tanh:
712 case Builtin::BI__builtin_elementwise_trunc:
713 case Builtin::BI__builtin_elementwise_canonicalize:
714 case Builtin::BI__builtin_elementwise_copysign:
715 case Builtin::BI__builtin_elementwise_fma:
716 case Builtin::BI__builtin_elementwise_fshl:
717 case Builtin::BI__builtin_elementwise_fshr:
718 case Builtin::BI__builtin_elementwise_add_sat:
719 case Builtin::BI__builtin_elementwise_sub_sat:
720 case Builtin::BI__builtin_elementwise_max:
721 case Builtin::BI__builtin_elementwise_min:
722 case Builtin::BI__builtin_elementwise_maxnum:
723 case Builtin::BI__builtin_elementwise_minnum:
724 case Builtin::BI__builtin_elementwise_maximum:
725 case Builtin::BI__builtin_elementwise_minimum:
726 case Builtin::BI__builtin_elementwise_maximumnum:
727 case Builtin::BI__builtin_elementwise_minimumnum:
728 case Builtin::BI__builtin_reduce_max:
729 case Builtin::BI__builtin_reduce_min:
730 case Builtin::BI__builtin_reduce_add:
731 case Builtin::BI__builtin_reduce_mul:
732 case Builtin::BI__builtin_reduce_xor:
733 case Builtin::BI__builtin_reduce_or:
734 case Builtin::BI__builtin_reduce_and:
735 case Builtin::BI__builtin_reduce_maximum:
736 case Builtin::BI__builtin_reduce_minimum:
737 case Builtin::BI__builtin_matrix_transpose:
738 case Builtin::BI__builtin_matrix_column_major_load:
739 case Builtin::BI__builtin_matrix_column_major_store:
740 case Builtin::BI__builtin_masked_load:
741 case Builtin::BI__builtin_masked_expand_load:
742 case Builtin::BI__builtin_masked_gather:
743 case Builtin::BI__builtin_masked_store:
744 case Builtin::BI__builtin_masked_compress_store:
745 case Builtin::BI__builtin_masked_scatter:
746 case Builtin::BI__builtin_isinf_sign:
747 case Builtin::BI__builtin_flt_rounds:
748 case Builtin::BI__builtin_set_flt_rounds:
749 case Builtin::BI__builtin_fpclassify:
750 return errorBuiltinNYI(*this, e, builtinID);
751 case Builtin::BIalloca:
752 case Builtin::BI_alloca:
753 case Builtin::BI__builtin_alloca_uninitialized:
754 case Builtin::BI__builtin_alloca:
755 return emitBuiltinAlloca(*this, e, builtinID);
756 case Builtin::BI__builtin_alloca_with_align_uninitialized:
757 case Builtin::BI__builtin_alloca_with_align:
758 case Builtin::BI__builtin_infer_alloc_token:
759 case Builtin::BIbzero:
760 case Builtin::BI__builtin_bzero:
761 case Builtin::BIbcopy:
762 case Builtin::BI__builtin_bcopy:
763 return errorBuiltinNYI(*this, e, builtinID);
764 case Builtin::BImemcpy:
765 case Builtin::BI__builtin_memcpy:
766 case Builtin::BImempcpy:
767 case Builtin::BI__builtin_mempcpy:
768 case Builtin::BI__builtin_memcpy_inline:
769 case Builtin::BI__builtin_char_memchr:
770 case Builtin::BI__builtin___memcpy_chk:
771 case Builtin::BI__builtin_objc_memmove_collectable:
772 case Builtin::BI__builtin___memmove_chk:
773 case Builtin::BI__builtin_trivially_relocate:
774 case Builtin::BImemmove:
775 case Builtin::BI__builtin_memmove:
776 case Builtin::BImemset:
777 case Builtin::BI__builtin_memset:
778 case Builtin::BI__builtin_memset_inline:
779 case Builtin::BI__builtin___memset_chk:
780 case Builtin::BI__builtin_wmemchr:
781 case Builtin::BI__builtin_wmemcmp:
782 break; // Handled as library calls below.
783 case Builtin::BI__builtin_dwarf_cfa:
784 return errorBuiltinNYI(*this, e, builtinID);
785 case Builtin::BI__builtin_return_address:
786 case Builtin::BI_ReturnAddress:
787 case Builtin::BI__builtin_frame_address: {
788 mlir::Location loc = getLoc(e->getExprLoc());
789 llvm::APSInt level = e->getArg(0)->EvaluateKnownConstInt(getContext());
790 if (builtinID == Builtin::BI__builtin_return_address) {
791 return RValue::get(cir::ReturnAddrOp::create(
792 builder, loc,
793 builder.getConstAPInt(loc, builder.getUInt32Ty(), level)));
794 }
795 return RValue::get(cir::FrameAddrOp::create(
796 builder, loc,
797 builder.getConstAPInt(loc, builder.getUInt32Ty(), level)));
798 }
799 case Builtin::BI__builtin_extract_return_addr:
800 case Builtin::BI__builtin_frob_return_addr:
801 case Builtin::BI__builtin_dwarf_sp_column:
802 case Builtin::BI__builtin_init_dwarf_reg_size_table:
803 case Builtin::BI__builtin_eh_return:
804 case Builtin::BI__builtin_unwind_init:
805 case Builtin::BI__builtin_extend_pointer:
806 case Builtin::BI__builtin_setjmp:
807 case Builtin::BI__builtin_longjmp:
808 case Builtin::BI__builtin_launder:
809 case Builtin::BI__sync_fetch_and_add:
810 case Builtin::BI__sync_fetch_and_sub:
811 case Builtin::BI__sync_fetch_and_or:
812 case Builtin::BI__sync_fetch_and_and:
813 case Builtin::BI__sync_fetch_and_xor:
814 case Builtin::BI__sync_fetch_and_nand:
815 case Builtin::BI__sync_add_and_fetch:
816 case Builtin::BI__sync_sub_and_fetch:
817 case Builtin::BI__sync_and_and_fetch:
818 case Builtin::BI__sync_or_and_fetch:
819 case Builtin::BI__sync_xor_and_fetch:
820 case Builtin::BI__sync_nand_and_fetch:
821 case Builtin::BI__sync_val_compare_and_swap:
822 case Builtin::BI__sync_bool_compare_and_swap:
823 case Builtin::BI__sync_lock_test_and_set:
824 case Builtin::BI__sync_lock_release:
825 case Builtin::BI__sync_swap:
826 case Builtin::BI__sync_fetch_and_add_1:
827 case Builtin::BI__sync_fetch_and_add_2:
828 case Builtin::BI__sync_fetch_and_add_4:
829 case Builtin::BI__sync_fetch_and_add_8:
830 case Builtin::BI__sync_fetch_and_add_16:
831 case Builtin::BI__sync_fetch_and_sub_1:
832 case Builtin::BI__sync_fetch_and_sub_2:
833 case Builtin::BI__sync_fetch_and_sub_4:
834 case Builtin::BI__sync_fetch_and_sub_8:
835 case Builtin::BI__sync_fetch_and_sub_16:
836 case Builtin::BI__sync_fetch_and_or_1:
837 case Builtin::BI__sync_fetch_and_or_2:
838 case Builtin::BI__sync_fetch_and_or_4:
839 case Builtin::BI__sync_fetch_and_or_8:
840 case Builtin::BI__sync_fetch_and_or_16:
841 case Builtin::BI__sync_fetch_and_and_1:
842 case Builtin::BI__sync_fetch_and_and_2:
843 case Builtin::BI__sync_fetch_and_and_4:
844 case Builtin::BI__sync_fetch_and_and_8:
845 case Builtin::BI__sync_fetch_and_and_16:
846 case Builtin::BI__sync_fetch_and_xor_1:
847 case Builtin::BI__sync_fetch_and_xor_2:
848 case Builtin::BI__sync_fetch_and_xor_4:
849 case Builtin::BI__sync_fetch_and_xor_8:
850 case Builtin::BI__sync_fetch_and_xor_16:
851 case Builtin::BI__sync_fetch_and_nand_1:
852 case Builtin::BI__sync_fetch_and_nand_2:
853 case Builtin::BI__sync_fetch_and_nand_4:
854 case Builtin::BI__sync_fetch_and_nand_8:
855 case Builtin::BI__sync_fetch_and_nand_16:
856 case Builtin::BI__sync_fetch_and_min:
857 case Builtin::BI__sync_fetch_and_max:
858 case Builtin::BI__sync_fetch_and_umin:
859 case Builtin::BI__sync_fetch_and_umax:
860 case Builtin::BI__sync_add_and_fetch_1:
861 case Builtin::BI__sync_add_and_fetch_2:
862 case Builtin::BI__sync_add_and_fetch_4:
863 case Builtin::BI__sync_add_and_fetch_8:
864 case Builtin::BI__sync_add_and_fetch_16:
865 case Builtin::BI__sync_sub_and_fetch_1:
866 case Builtin::BI__sync_sub_and_fetch_2:
867 case Builtin::BI__sync_sub_and_fetch_4:
868 case Builtin::BI__sync_sub_and_fetch_8:
869 case Builtin::BI__sync_sub_and_fetch_16:
870 case Builtin::BI__sync_and_and_fetch_1:
871 case Builtin::BI__sync_and_and_fetch_2:
872 case Builtin::BI__sync_and_and_fetch_4:
873 case Builtin::BI__sync_and_and_fetch_8:
874 case Builtin::BI__sync_and_and_fetch_16:
875 case Builtin::BI__sync_or_and_fetch_1:
876 case Builtin::BI__sync_or_and_fetch_2:
877 case Builtin::BI__sync_or_and_fetch_4:
878 case Builtin::BI__sync_or_and_fetch_8:
879 case Builtin::BI__sync_or_and_fetch_16:
880 case Builtin::BI__sync_xor_and_fetch_1:
881 case Builtin::BI__sync_xor_and_fetch_2:
882 case Builtin::BI__sync_xor_and_fetch_4:
883 case Builtin::BI__sync_xor_and_fetch_8:
884 case Builtin::BI__sync_xor_and_fetch_16:
885 case Builtin::BI__sync_nand_and_fetch_1:
886 case Builtin::BI__sync_nand_and_fetch_2:
887 case Builtin::BI__sync_nand_and_fetch_4:
888 case Builtin::BI__sync_nand_and_fetch_8:
889 case Builtin::BI__sync_nand_and_fetch_16:
890 case Builtin::BI__sync_val_compare_and_swap_1:
891 case Builtin::BI__sync_val_compare_and_swap_2:
892 case Builtin::BI__sync_val_compare_and_swap_4:
893 case Builtin::BI__sync_val_compare_and_swap_8:
894 case Builtin::BI__sync_val_compare_and_swap_16:
895 case Builtin::BI__sync_bool_compare_and_swap_1:
896 case Builtin::BI__sync_bool_compare_and_swap_2:
897 case Builtin::BI__sync_bool_compare_and_swap_4:
898 case Builtin::BI__sync_bool_compare_and_swap_8:
899 case Builtin::BI__sync_bool_compare_and_swap_16:
900 case Builtin::BI__sync_swap_1:
901 case Builtin::BI__sync_swap_2:
902 case Builtin::BI__sync_swap_4:
903 case Builtin::BI__sync_swap_8:
904 case Builtin::BI__sync_swap_16:
905 case Builtin::BI__sync_lock_test_and_set_1:
906 case Builtin::BI__sync_lock_test_and_set_2:
907 case Builtin::BI__sync_lock_test_and_set_4:
908 case Builtin::BI__sync_lock_test_and_set_8:
909 case Builtin::BI__sync_lock_test_and_set_16:
910 case Builtin::BI__sync_lock_release_1:
911 case Builtin::BI__sync_lock_release_2:
912 case Builtin::BI__sync_lock_release_4:
913 case Builtin::BI__sync_lock_release_8:
914 case Builtin::BI__sync_lock_release_16:
915 case Builtin::BI__sync_synchronize:
916 case Builtin::BI__builtin_nontemporal_load:
917 case Builtin::BI__builtin_nontemporal_store:
918 case Builtin::BI__c11_atomic_is_lock_free:
919 case Builtin::BI__atomic_is_lock_free:
920 case Builtin::BI__atomic_test_and_set:
921 case Builtin::BI__atomic_clear:
922 case Builtin::BI__atomic_thread_fence:
923 case Builtin::BI__atomic_signal_fence:
924 case Builtin::BI__c11_atomic_thread_fence:
925 case Builtin::BI__c11_atomic_signal_fence:
926 case Builtin::BI__scoped_atomic_thread_fence:
927 case Builtin::BI__builtin_signbit:
928 case Builtin::BI__builtin_signbitf:
929 case Builtin::BI__builtin_signbitl:
930 case Builtin::BI__warn_memset_zero_len:
931 case Builtin::BI__annotation:
932 case Builtin::BI__builtin_annotation:
933 case Builtin::BI__builtin_addcb:
934 case Builtin::BI__builtin_addcs:
935 case Builtin::BI__builtin_addc:
936 case Builtin::BI__builtin_addcl:
937 case Builtin::BI__builtin_addcll:
938 case Builtin::BI__builtin_subcb:
939 case Builtin::BI__builtin_subcs:
940 case Builtin::BI__builtin_subc:
941 case Builtin::BI__builtin_subcl:
942 case Builtin::BI__builtin_subcll:
943 return errorBuiltinNYI(*this, e, builtinID);
944
945 case Builtin::BI__builtin_add_overflow:
946 case Builtin::BI__builtin_sub_overflow:
947 case Builtin::BI__builtin_mul_overflow: {
948 const clang::Expr *leftArg = e->getArg(0);
949 const clang::Expr *rightArg = e->getArg(1);
950 const clang::Expr *resultArg = e->getArg(2);
951
952 clang::QualType resultQTy =
954
955 WidthAndSignedness leftInfo =
956 getIntegerWidthAndSignedness(cgm.getASTContext(), leftArg->getType());
957 WidthAndSignedness rightInfo =
958 getIntegerWidthAndSignedness(cgm.getASTContext(), rightArg->getType());
959 WidthAndSignedness resultInfo =
960 getIntegerWidthAndSignedness(cgm.getASTContext(), resultQTy);
961
962 // Note we compute the encompassing type with the consideration to the
963 // result type, so later in LLVM lowering we don't get redundant integral
964 // extension casts.
965 WidthAndSignedness encompassingInfo =
966 EncompassingIntegerType({leftInfo, rightInfo, resultInfo});
967
968 auto encompassingCIRTy = cir::IntType::get(
969 &getMLIRContext(), encompassingInfo.width, encompassingInfo.isSigned);
970 auto resultCIRTy = mlir::cast<cir::IntType>(cgm.convertType(resultQTy));
971
972 mlir::Value left = emitScalarExpr(leftArg);
973 mlir::Value right = emitScalarExpr(rightArg);
974 Address resultPtr = emitPointerWithAlignment(resultArg);
975
976 // Extend each operand to the encompassing type, if necessary.
977 if (left.getType() != encompassingCIRTy)
978 left =
979 builder.createCast(cir::CastKind::integral, left, encompassingCIRTy);
980 if (right.getType() != encompassingCIRTy)
981 right =
982 builder.createCast(cir::CastKind::integral, right, encompassingCIRTy);
983
984 // Perform the operation on the extended values.
985 cir::BinOpOverflowKind opKind;
986 switch (builtinID) {
987 default:
988 llvm_unreachable("Unknown overflow builtin id.");
989 case Builtin::BI__builtin_add_overflow:
990 opKind = cir::BinOpOverflowKind::Add;
991 break;
992 case Builtin::BI__builtin_sub_overflow:
993 opKind = cir::BinOpOverflowKind::Sub;
994 break;
995 case Builtin::BI__builtin_mul_overflow:
996 opKind = cir::BinOpOverflowKind::Mul;
997 break;
998 }
999
1000 mlir::Location loc = getLoc(e->getSourceRange());
1001 auto arithOp = cir::BinOpOverflowOp::create(builder, loc, resultCIRTy,
1002 opKind, left, right);
1003
1004 // Here is a slight difference from the original clang CodeGen:
1005 // - In the original clang CodeGen, the checked arithmetic result is
1006 // first computed as a value of the encompassing type, and then it is
1007 // truncated to the actual result type with a second overflow checking.
1008 // - In CIRGen, the checked arithmetic operation directly produce the
1009 // checked arithmetic result in its expected type.
1010 //
1011 // So we don't need a truncation and a second overflow checking here.
1012
1013 // Finally, store the result using the pointer.
1014 bool isVolatile =
1015 resultArg->getType()->getPointeeType().isVolatileQualified();
1016 builder.createStore(loc, emitToMemory(arithOp.getResult(), resultQTy),
1017 resultPtr, isVolatile);
1018
1019 return RValue::get(arithOp.getOverflow());
1020 }
1021
1022 case Builtin::BI__builtin_uadd_overflow:
1023 case Builtin::BI__builtin_uaddl_overflow:
1024 case Builtin::BI__builtin_uaddll_overflow:
1025 case Builtin::BI__builtin_usub_overflow:
1026 case Builtin::BI__builtin_usubl_overflow:
1027 case Builtin::BI__builtin_usubll_overflow:
1028 case Builtin::BI__builtin_umul_overflow:
1029 case Builtin::BI__builtin_umull_overflow:
1030 case Builtin::BI__builtin_umulll_overflow:
1031 case Builtin::BI__builtin_sadd_overflow:
1032 case Builtin::BI__builtin_saddl_overflow:
1033 case Builtin::BI__builtin_saddll_overflow:
1034 case Builtin::BI__builtin_ssub_overflow:
1035 case Builtin::BI__builtin_ssubl_overflow:
1036 case Builtin::BI__builtin_ssubll_overflow:
1037 case Builtin::BI__builtin_smul_overflow:
1038 case Builtin::BI__builtin_smull_overflow:
1039 case Builtin::BI__builtin_smulll_overflow: {
1040 // Scalarize our inputs.
1041 mlir::Value x = emitScalarExpr(e->getArg(0));
1042 mlir::Value y = emitScalarExpr(e->getArg(1));
1043
1044 const clang::Expr *resultArg = e->getArg(2);
1045 Address resultPtr = emitPointerWithAlignment(resultArg);
1046
1047 // Decide which of the arithmetic operation we are lowering to:
1048 cir::BinOpOverflowKind arithKind;
1049 switch (builtinID) {
1050 default:
1051 llvm_unreachable("Unknown overflow builtin id.");
1052 case Builtin::BI__builtin_uadd_overflow:
1053 case Builtin::BI__builtin_uaddl_overflow:
1054 case Builtin::BI__builtin_uaddll_overflow:
1055 case Builtin::BI__builtin_sadd_overflow:
1056 case Builtin::BI__builtin_saddl_overflow:
1057 case Builtin::BI__builtin_saddll_overflow:
1058 arithKind = cir::BinOpOverflowKind::Add;
1059 break;
1060 case Builtin::BI__builtin_usub_overflow:
1061 case Builtin::BI__builtin_usubl_overflow:
1062 case Builtin::BI__builtin_usubll_overflow:
1063 case Builtin::BI__builtin_ssub_overflow:
1064 case Builtin::BI__builtin_ssubl_overflow:
1065 case Builtin::BI__builtin_ssubll_overflow:
1066 arithKind = cir::BinOpOverflowKind::Sub;
1067 break;
1068 case Builtin::BI__builtin_umul_overflow:
1069 case Builtin::BI__builtin_umull_overflow:
1070 case Builtin::BI__builtin_umulll_overflow:
1071 case Builtin::BI__builtin_smul_overflow:
1072 case Builtin::BI__builtin_smull_overflow:
1073 case Builtin::BI__builtin_smulll_overflow:
1074 arithKind = cir::BinOpOverflowKind::Mul;
1075 break;
1076 }
1077
1078 clang::QualType resultQTy =
1079 resultArg->getType()->castAs<clang::PointerType>()->getPointeeType();
1080 auto resultCIRTy = mlir::cast<cir::IntType>(cgm.convertType(resultQTy));
1081
1082 mlir::Location loc = getLoc(e->getSourceRange());
1083 cir::BinOpOverflowOp arithOp = cir::BinOpOverflowOp::create(
1084 builder, loc, resultCIRTy, arithKind, x, y);
1085
1086 bool isVolatile =
1087 resultArg->getType()->getPointeeType().isVolatileQualified();
1088 builder.createStore(loc, emitToMemory(arithOp.getResult(), resultQTy),
1089 resultPtr, isVolatile);
1090
1091 return RValue::get(arithOp.getOverflow());
1092 }
1093
1094 case Builtin::BIaddressof:
1095 case Builtin::BI__addressof:
1096 case Builtin::BI__builtin_addressof:
1097 case Builtin::BI__builtin_function_start:
1098 return errorBuiltinNYI(*this, e, builtinID);
1099 case Builtin::BI__builtin_operator_new:
1101 e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_New);
1102 case Builtin::BI__builtin_operator_delete:
1104 e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_Delete);
1105 return RValue::get(nullptr);
1106 case Builtin::BI__builtin_is_aligned:
1107 case Builtin::BI__builtin_align_up:
1108 case Builtin::BI__builtin_align_down:
1109 case Builtin::BI__noop:
1110 case Builtin::BI__builtin_call_with_static_chain:
1111 case Builtin::BI_InterlockedExchange8:
1112 case Builtin::BI_InterlockedExchange16:
1113 case Builtin::BI_InterlockedExchange:
1114 case Builtin::BI_InterlockedExchangePointer:
1115 case Builtin::BI_InterlockedCompareExchangePointer:
1116 case Builtin::BI_InterlockedCompareExchangePointer_nf:
1117 case Builtin::BI_InterlockedCompareExchange8:
1118 case Builtin::BI_InterlockedCompareExchange16:
1119 case Builtin::BI_InterlockedCompareExchange:
1120 case Builtin::BI_InterlockedCompareExchange64:
1121 case Builtin::BI_InterlockedIncrement16:
1122 case Builtin::BI_InterlockedIncrement:
1123 case Builtin::BI_InterlockedDecrement16:
1124 case Builtin::BI_InterlockedDecrement:
1125 case Builtin::BI_InterlockedAnd8:
1126 case Builtin::BI_InterlockedAnd16:
1127 case Builtin::BI_InterlockedAnd:
1128 case Builtin::BI_InterlockedExchangeAdd8:
1129 case Builtin::BI_InterlockedExchangeAdd16:
1130 case Builtin::BI_InterlockedExchangeAdd:
1131 case Builtin::BI_InterlockedExchangeSub8:
1132 case Builtin::BI_InterlockedExchangeSub16:
1133 case Builtin::BI_InterlockedExchangeSub:
1134 case Builtin::BI_InterlockedOr8:
1135 case Builtin::BI_InterlockedOr16:
1136 case Builtin::BI_InterlockedOr:
1137 case Builtin::BI_InterlockedXor8:
1138 case Builtin::BI_InterlockedXor16:
1139 case Builtin::BI_InterlockedXor:
1140 case Builtin::BI_bittest64:
1141 case Builtin::BI_bittest:
1142 case Builtin::BI_bittestandcomplement64:
1143 case Builtin::BI_bittestandcomplement:
1144 case Builtin::BI_bittestandreset64:
1145 case Builtin::BI_bittestandreset:
1146 case Builtin::BI_bittestandset64:
1147 case Builtin::BI_bittestandset:
1148 case Builtin::BI_interlockedbittestandreset:
1149 case Builtin::BI_interlockedbittestandreset64:
1150 case Builtin::BI_interlockedbittestandreset64_acq:
1151 case Builtin::BI_interlockedbittestandreset64_rel:
1152 case Builtin::BI_interlockedbittestandreset64_nf:
1153 case Builtin::BI_interlockedbittestandset64:
1154 case Builtin::BI_interlockedbittestandset64_acq:
1155 case Builtin::BI_interlockedbittestandset64_rel:
1156 case Builtin::BI_interlockedbittestandset64_nf:
1157 case Builtin::BI_interlockedbittestandset:
1158 case Builtin::BI_interlockedbittestandset_acq:
1159 case Builtin::BI_interlockedbittestandset_rel:
1160 case Builtin::BI_interlockedbittestandset_nf:
1161 case Builtin::BI_interlockedbittestandreset_acq:
1162 case Builtin::BI_interlockedbittestandreset_rel:
1163 case Builtin::BI_interlockedbittestandreset_nf:
1164 case Builtin::BI__iso_volatile_load8:
1165 case Builtin::BI__iso_volatile_load16:
1166 case Builtin::BI__iso_volatile_load32:
1167 case Builtin::BI__iso_volatile_load64:
1168 case Builtin::BI__iso_volatile_store8:
1169 case Builtin::BI__iso_volatile_store16:
1170 case Builtin::BI__iso_volatile_store32:
1171 case Builtin::BI__iso_volatile_store64:
1172 case Builtin::BI__builtin_ptrauth_sign_constant:
1173 case Builtin::BI__builtin_ptrauth_auth:
1174 case Builtin::BI__builtin_ptrauth_auth_and_resign:
1175 case Builtin::BI__builtin_ptrauth_blend_discriminator:
1176 case Builtin::BI__builtin_ptrauth_sign_generic_data:
1177 case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
1178 case Builtin::BI__builtin_ptrauth_strip:
1179 case Builtin::BI__builtin_get_vtable_pointer:
1180 case Builtin::BI__exception_code:
1181 case Builtin::BI_exception_code:
1182 case Builtin::BI__exception_info:
1183 case Builtin::BI_exception_info:
1184 case Builtin::BI__abnormal_termination:
1185 case Builtin::BI_abnormal_termination:
1186 case Builtin::BI_setjmpex:
1187 case Builtin::BI_setjmp:
1188 case Builtin::BImove:
1189 case Builtin::BImove_if_noexcept:
1190 case Builtin::BIforward:
1191 case Builtin::BIforward_like:
1192 case Builtin::BIas_const:
1193 case Builtin::BI__GetExceptionInfo:
1194 case Builtin::BI__fastfail:
1195 case Builtin::BIread_pipe:
1196 case Builtin::BIwrite_pipe:
1197 case Builtin::BIreserve_read_pipe:
1198 case Builtin::BIreserve_write_pipe:
1199 case Builtin::BIwork_group_reserve_read_pipe:
1200 case Builtin::BIwork_group_reserve_write_pipe:
1201 case Builtin::BIsub_group_reserve_read_pipe:
1202 case Builtin::BIsub_group_reserve_write_pipe:
1203 case Builtin::BIcommit_read_pipe:
1204 case Builtin::BIcommit_write_pipe:
1205 case Builtin::BIwork_group_commit_read_pipe:
1206 case Builtin::BIwork_group_commit_write_pipe:
1207 case Builtin::BIsub_group_commit_read_pipe:
1208 case Builtin::BIsub_group_commit_write_pipe:
1209 case Builtin::BIget_pipe_num_packets:
1210 case Builtin::BIget_pipe_max_packets:
1211 case Builtin::BIto_global:
1212 case Builtin::BIto_local:
1213 case Builtin::BIto_private:
1214 case Builtin::BIenqueue_kernel:
1215 case Builtin::BIget_kernel_work_group_size:
1216 case Builtin::BIget_kernel_preferred_work_group_size_multiple:
1217 case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
1218 case Builtin::BIget_kernel_sub_group_count_for_ndrange:
1219 case Builtin::BI__builtin_store_half:
1220 case Builtin::BI__builtin_store_halff:
1221 case Builtin::BI__builtin_load_half:
1222 case Builtin::BI__builtin_load_halff:
1223 return errorBuiltinNYI(*this, e, builtinID);
1224 case Builtin::BI__builtin_printf:
1225 case Builtin::BIprintf:
1226 break;
1227 case Builtin::BI__builtin_canonicalize:
1228 case Builtin::BI__builtin_canonicalizef:
1229 case Builtin::BI__builtin_canonicalizef16:
1230 case Builtin::BI__builtin_canonicalizel:
1231 case Builtin::BI__builtin_thread_pointer:
1232 case Builtin::BI__builtin_os_log_format:
1233 case Builtin::BI__xray_customevent:
1234 case Builtin::BI__xray_typedevent:
1235 case Builtin::BI__builtin_ms_va_start:
1236 case Builtin::BI__builtin_ms_va_end:
1237 case Builtin::BI__builtin_ms_va_copy:
1238 case Builtin::BI__builtin_get_device_side_mangled_name:
1239 return errorBuiltinNYI(*this, e, builtinID);
1240 }
1241
1242 // If this is an alias for a lib function (e.g. __builtin_sin), emit
1243 // the call using the normal call path, but using the unmangled
1244 // version of the function name.
1245 if (getContext().BuiltinInfo.isLibFunction(builtinID))
1246 return emitLibraryCall(*this, fd, e,
1247 cgm.getBuiltinLibFunction(fd, builtinID));
1248
1249 // Some target-specific builtins can have aggregate return values, e.g.
1250 // __builtin_arm_mve_vld2q_u32. So if the result is an aggregate, force
1251 // returnValue to be non-null, so that the target-specific emission code can
1252 // always just emit into it.
1254 if (evalKind == cir::TEK_Aggregate && returnValue.isNull()) {
1255 cgm.errorNYI(e->getSourceRange(), "aggregate return value from builtin");
1256 return getUndefRValue(e->getType());
1257 }
1258
1259 // Now see if we can emit a target-specific builtin.
1260 if (mlir::Value v = emitTargetBuiltinExpr(builtinID, e, returnValue)) {
1261 switch (evalKind) {
1262 case cir::TEK_Scalar:
1263 if (mlir::isa<cir::VoidType>(v.getType()))
1264 return RValue::get(nullptr);
1265 return RValue::get(v);
1266 case cir::TEK_Aggregate:
1267 cgm.errorNYI(e->getSourceRange(), "aggregate return value from builtin");
1268 return getUndefRValue(e->getType());
1269 case cir::TEK_Complex:
1270 llvm_unreachable("No current target builtin returns complex");
1271 }
1272 llvm_unreachable("Bad evaluation kind in EmitBuiltinExpr");
1273 }
1274
1275 cgm.errorNYI(e->getSourceRange(),
1276 std::string("unimplemented builtin call: ") +
1277 getContext().BuiltinInfo.getName(builtinID));
1278 return getUndefRValue(e->getType());
1279}
1280
1282 unsigned builtinID,
1283 const CallExpr *e,
1284 ReturnValueSlot &returnValue,
1285 llvm::Triple::ArchType arch) {
1286 // When compiling in HipStdPar mode we have to be conservative in rejecting
1287 // target specific features in the FE, and defer the possible error to the
1288 // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
1289 // referenced by an accelerator executable function, we emit an error.
1290 // Returning nullptr here leads to the builtin being handled in
1291 // EmitStdParUnsupportedBuiltin.
1292 if (cgf->getLangOpts().HIPStdPar && cgf->getLangOpts().CUDAIsDevice &&
1293 arch != cgf->getTarget().getTriple().getArch())
1294 return {};
1295
1296 switch (arch) {
1297 case llvm::Triple::arm:
1298 case llvm::Triple::armeb:
1299 case llvm::Triple::thumb:
1300 case llvm::Triple::thumbeb:
1301 case llvm::Triple::aarch64:
1302 case llvm::Triple::aarch64_32:
1303 case llvm::Triple::aarch64_be:
1304 case llvm::Triple::bpfeb:
1305 case llvm::Triple::bpfel:
1306 // These are actually NYI, but that will be reported by emitBuiltinExpr.
1307 // At this point, we don't even know that the builtin is target-specific.
1308 return nullptr;
1309
1310 case llvm::Triple::x86:
1311 case llvm::Triple::x86_64:
1312 return cgf->emitX86BuiltinExpr(builtinID, e);
1313
1314 case llvm::Triple::ppc:
1315 case llvm::Triple::ppcle:
1316 case llvm::Triple::ppc64:
1317 case llvm::Triple::ppc64le:
1318 case llvm::Triple::r600:
1319 case llvm::Triple::amdgcn:
1320 case llvm::Triple::systemz:
1321 case llvm::Triple::nvptx:
1322 case llvm::Triple::nvptx64:
1323 case llvm::Triple::wasm32:
1324 case llvm::Triple::wasm64:
1325 case llvm::Triple::hexagon:
1326 case llvm::Triple::riscv32:
1327 case llvm::Triple::riscv64:
1328 // These are actually NYI, but that will be reported by emitBuiltinExpr.
1329 // At this point, we don't even know that the builtin is target-specific.
1330 return {};
1331 default:
1332 return {};
1333 }
1334}
1335
1336mlir::Value
1339 if (getContext().BuiltinInfo.isAuxBuiltinID(builtinID)) {
1340 assert(getContext().getAuxTargetInfo() && "Missing aux target info");
1342 this, getContext().BuiltinInfo.getAuxBuiltinID(builtinID), e,
1343 returnValue, getContext().getAuxTargetInfo()->getTriple().getArch());
1344 }
1345
1346 return emitTargetArchBuiltinExpr(this, builtinID, e, returnValue,
1347 getTarget().getTriple().getArch());
1348}
1349
1351 const unsigned iceArguments, const unsigned idx, const Expr *argExpr) {
1352 mlir::Value arg = {};
1353 if ((iceArguments & (1 << idx)) == 0) {
1354 arg = emitScalarExpr(argExpr);
1355 } else {
1356 // If this is required to be a constant, constant fold it so that we
1357 // know that the generated intrinsic gets a ConstantInt.
1358 const std::optional<llvm::APSInt> result =
1360 assert(result && "Expected argument to be a constant");
1361 arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result);
1362 }
1363 return arg;
1364}
1365
1366/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
1367/// for "fabsf".
1369 unsigned builtinID) {
1370 assert(astContext.BuiltinInfo.isLibFunction(builtinID));
1371
1372 // Get the name, skip over the __builtin_ prefix (if necessary). We may have
1373 // to build this up so provide a small stack buffer to handle the vast
1374 // majority of names.
1376
1378 name = astContext.BuiltinInfo.getName(builtinID).substr(10);
1379
1380 GlobalDecl d(fd);
1381 mlir::Type type = convertType(fd->getType());
1382 return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
1383}
1384
1386 mlir::Value argValue = evaluateExprAsBool(e);
1387 if (!sanOpts.has(SanitizerKind::Builtin))
1388 return argValue;
1389
1391 cgm.errorNYI(e->getSourceRange(),
1392 "emitCheckedArgForAssume: sanitizers are NYI");
1393 return {};
1394}
1395
1396void CIRGenFunction::emitVAStart(mlir::Value vaList, mlir::Value count) {
1397 // LLVM codegen casts to *i8, no real gain on doing this for CIRGen this
1398 // early, defer to LLVM lowering.
1399 cir::VAStartOp::create(builder, vaList.getLoc(), vaList, count);
1400}
1401
1402void CIRGenFunction::emitVAEnd(mlir::Value vaList) {
1403 cir::VAEndOp::create(builder, vaList.getLoc(), vaList);
1404}
1405
1406// FIXME(cir): This completely abstracts away the ABI with a generic CIR Op. By
1407// default this lowers to llvm.va_arg which is incomplete and not ABI-compliant
1408// on most targets so cir.va_arg will need some ABI handling in LoweringPrepare
1410 assert(!cir::MissingFeatures::msabi());
1411 assert(!cir::MissingFeatures::vlas());
1412 mlir::Location loc = cgm.getLoc(ve->getExprLoc());
1413 mlir::Type type = convertType(ve->getType());
1414 mlir::Value vaList = emitVAListRef(ve->getSubExpr()).getPointer();
1415 return cir::VAArgOp::create(builder, loc, type, vaList);
1416}
1417
1418mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type,
1419 cir::IntType resType,
1420 mlir::Value emittedE,
1421 bool isDynamic) {
1423
1424 // LLVM can't handle type=3 appropriately, and __builtin_object_size shouldn't
1425 // evaluate e for side-effects. In either case, just like original LLVM
1426 // lowering, we shouldn't lower to `cir.objsize` but to a constant instead.
1427 if (type == 3 || (!emittedE && e->HasSideEffects(getContext())))
1428 return builder.getConstInt(getLoc(e->getSourceRange()), resType,
1429 (type & 2) ? 0 : -1);
1430
1431 mlir::Value ptr = emittedE ? emittedE : emitScalarExpr(e);
1432 assert(mlir::isa<cir::PointerType>(ptr.getType()) &&
1433 "Non-pointer passed to __builtin_object_size?");
1434
1436
1437 // Extract the min/max mode from type. CIR only supports type 0
1438 // (max, whole object) and type 2 (min, whole object), not type 1 or 3
1439 // (closest subobject variants).
1440 const bool min = ((type & 2) != 0);
1441 // For GCC compatibility, __builtin_object_size treats NULL as unknown size.
1442 auto op =
1443 cir::ObjSizeOp::create(builder, getLoc(e->getSourceRange()), resType, ptr,
1444 min, /*nullUnknown=*/true, isDynamic);
1445 return op.getResult();
1446}
1447
1449 const Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE,
1450 bool isDynamic) {
1451 uint64_t objectSize;
1452 if (!e->tryEvaluateObjectSize(objectSize, getContext(), type))
1453 return emitBuiltinObjectSize(e, type, resType, emittedE, isDynamic);
1454 return builder.getConstInt(getLoc(e->getSourceRange()), resType, objectSize);
1455}
Defines enum values for all the target-independent builtin functions.
static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static mlir::Value emitTargetArchBuiltinExpr(CIRGenFunction *cgf, unsigned builtinID, const CallExpr *e, ReturnValueSlot &returnValue, llvm::Triple::ArchType arch)
static RValue emitUnaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static RValue emitLibraryCall(CIRGenFunction &cgf, const FunctionDecl *fd, const CallExpr *e, mlir::Operation *calleeValue)
static WidthAndSignedness getIntegerWidthAndSignedness(const clang::ASTContext &astContext, const clang::QualType type)
static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, bool poisonZero=false)
static struct WidthAndSignedness EncompassingIntegerType(ArrayRef< struct WidthAndSignedness > types)
static RValue emitBuiltinAlloca(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
static RValue errorBuiltinNYI(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
Defines an enumeration for C++ overloaded operators.
static QualType getPointeeType(const MemRegion *R)
__DEVICE__ int min(int __a, int __b)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
APSInt & getInt()
Definition APValue.h:489
bool isFloat() const
Definition APValue.h:468
bool isInt() const
Definition APValue.h:467
APFloat & getFloat()
Definition APValue.h:503
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
unsigned getIntWidth(QualType T) const
Builtin::Context & BuiltinInfo
Definition ASTContext.h:774
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:891
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isLibFunction(unsigned ID) const
Return true if this is a builtin for a libc/libm function, with a "__builtin_" prefix (e....
Definition Builtins.h:303
std::string getName(unsigned ID) const
Return the identifier name for the specified builtin, e.g.
Definition Builtins.cpp:80
mlir::Value getPointer() const
Definition Address.h:84
cir::PointerType getUInt8PtrTy()
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
mlir::Type convertType(clang::QualType t)
mlir::Value emitCheckedArgForAssume(const Expr *e)
Emits an argument for a call to a __builtin_assume.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
const clang::LangOptions & getLangOpts() const
void emitTrap(mlir::Location loc, bool createNewBlock)
Emit a trap instruction, which is used to abort the program in an abnormal way, usually for debugging...
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
const TargetInfo & getTarget() const
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Value emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitVAStart(mlir::Value vaList, mlir::Value count)
Emits the start of a CIR variable-argument operation (cir.va_start)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
mlir::Value emitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
Returns a Value corresponding to the size of the given expression by emitting a cir....
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock)
Emit a reached-unreachable diagnostic if loc is valid and runtime checking is enabled.
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
Address returnValue
The temporary alloca to hold the return value.
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
void emitVAEnd(mlir::Value vaList)
Emits the end of a CIR variable-argument operation (cir.va_start)
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty)
Given a value and its clang type, returns the value casted to its memory representation.
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
mlir::Value emitX86BuiltinExpr(unsigned builtinID, const CallExpr *e)
mlir::Value emitAlignmentAssumption(mlir::Value ptrValue, QualType ty, SourceLocation loc, SourceLocation assumptionLoc, int64_t alignment, mlir::Value offsetValue=nullptr)
RValue emitNewOrDeleteBuiltinCall(const FunctionProtoType *type, const CallExpr *callExpr, OverloadedOperatorKind op)
clang::ASTContext & getContext() const
RValue emitBuiltinExpr(const clang::GlobalDecl &gd, unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot returnValue)
Address emitVAListRef(const Expr *e)
Build a "reference" to a va_list; this is either the address or the value of the expression,...
mlir::Value emitScalarOrConstFoldImmArg(unsigned iceArguments, unsigned idx, const Expr *argExpr)
mlir::Value emitVAArg(VAArgExpr *ve)
Generate code to get an argument from the passed in pointer and update it accordingly.
RValue emitRotate(const CallExpr *e, bool isRotateLeft)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::Type convertType(clang::QualType type)
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID)
Given a builtin id for a function like "__builtin_fabsf", return a Function* for "fabsf".
cir::FuncOp getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType, clang::GlobalDecl gd, bool forVTable, bool dontDefer=false, bool isThunk=false, ForDefinition_t isForDefinition=NotForDefinition, mlir::ArrayAttr extraAttrs={})
This trivial value class is used to represent the result of an expression that is evaluated.
Definition CIRGenValue.h:33
static RValue get(mlir::Value v)
Definition CIRGenValue.h:83
static RValue getComplex(mlir::Value v)
Definition CIRGenValue.h:91
static RValue getIgnored()
Definition CIRGenValue.h:78
Contains the address where the return value of a function can be stored, and whether the address is v...
Definition CIRGenCall.h:254
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
SourceLocation getBeginLoc() const
Definition Expr.h:3211
Expr * getCallee()
Definition Expr.h:3024
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3068
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
bool hasAttr() const
Definition DeclBase.h:577
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsFloat - Return true if this is a constant which we can fold and convert to a floating point...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isPRValue() const
Definition Expr.h:285
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3665
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const
If the current Expr is a pointer, this will try to statically determine the number of bytes available...
Represents a function declaration or definition.
Definition Decl.h:2000
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8362
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8404
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
Exposes information about the current target.
Definition TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
unsigned getSuitableAlign() const
Return the alignment that is the largest alignment ever used for any scalar/SIMD data type on the tar...
Definition TargetInfo.h:745
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4891
const Expr * getSubExpr() const
Definition Expr.h:4907
QualType getType() const
Definition Decl.h:723
bool isMatchingAddressSpace(cir::TargetAddressSpaceAttr cirAS, clang::LangAS as)
Definition CIRTypes.cpp:823
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
U cast(CodeGen::Address addr)
Definition Address.h:327
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
static bool builtinCheckKind()
static bool asmLabelAttr()
static bool msvcBuiltins()
static bool coroutineFrame()
static bool cgFPOptionsRAII()
static bool builtinCallF128()
static bool fpConstraints()
static bool countedBySize()
static bool builtinCallMathErrno()
static bool opCallImplicitObjectSizeArgs()
static bool fastMathFlags()
static bool builtinCall()
cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:639
#define conj(__x)
Definition tgmath.h:1303