clang 23.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"
29#include "llvm/IR/Intrinsics.h"
30#include "llvm/Support/ErrorHandling.h"
31
32using namespace clang;
33using namespace clang::CIRGen;
34using namespace llvm;
35
36static bool shouldEmitBuiltinAsIR(unsigned builtinID,
37 const Builtin::Context &bi,
38 const CIRGenFunction &cgf) {
39 if (!cgf.cgm.getLangOpts().MathErrno &&
43 switch (builtinID) {
44 default:
45 return false;
46 case Builtin::BIlogbf:
47 case Builtin::BI__builtin_logbf:
48 case Builtin::BIlogb:
49 case Builtin::BI__builtin_logb:
50 case Builtin::BIscalbnf:
51 case Builtin::BI__builtin_scalbnf:
52 case Builtin::BIscalbn:
53 case Builtin::BI__builtin_scalbn:
54 return true;
55 }
56 }
57 return false;
58}
59
61 const CallExpr *e, mlir::Operation *calleeValue) {
62 CIRGenCallee callee = CIRGenCallee::forDirect(calleeValue, GlobalDecl(fd));
63 return cgf.emitCall(e->getCallee()->getType(), callee, e, ReturnValueSlot());
64}
65
66template <typename Op, typename... Args>
67static mlir::Value createBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e,
68 mlir::Value arg, Args... args) {
69 CIRGenBuilderTy &builder = cgf.getBuilder();
70 mlir::Location loc = cgf.getLoc(e->getSourceRange());
71 auto op = Op::create(builder, loc, arg, args...);
72 mlir::Value result = op.getResult();
73 mlir::Type resultTy = cgf.convertType(e->getType());
74 if (resultTy != result.getType())
75 result = builder.createIntCast(result, resultTy);
76 return result;
77}
78
79template <typename Op, typename... Args>
81 Args... args) {
82 mlir::Value arg = cgf.emitScalarExpr(e->getArg(0));
83 return RValue::get(createBuiltinBitOp<Op>(cgf, e, arg, args...));
84}
85
86/// Emit a clz/ctz bit op with optional fallback for __builtin_c[lt]zg.
87/// When a fallback is present, the result is the fallback value if the input is
88/// zero, otherwise the bit count.
89template <typename Op>
91 const CallExpr *e) {
92 bool hasFallback = e->getNumArgs() > 1;
93 bool poisonZero = hasFallback || cgf.getTarget().isCLZForZeroUndef();
94
95 if (!hasFallback) {
97 return emitBuiltinBitOp<Op>(cgf, e, poisonZero);
98 }
99
101 mlir::Value arg = cgf.emitScalarExpr(e->getArg(0));
102 mlir::Value result = createBuiltinBitOp<Op>(cgf, e, arg, poisonZero);
103
104 CIRGenBuilderTy &builder = cgf.getBuilder();
105 mlir::Location loc = cgf.getLoc(e->getSourceRange());
106 mlir::Value zero = builder.getNullValue(arg.getType(), loc);
107 mlir::Value isZero =
108 builder.createCompare(loc, cir::CmpOpKind::eq, arg, zero);
109 mlir::Value fallbackValue = cgf.emitScalarExpr(e->getArg(1));
110 return RValue::get(builder.createSelect(loc, isZero, fallbackValue, result));
111}
112
113/// Emit the conversions required to turn the given value into an
114/// integer of the given size.
115static mlir::Value emitToInt(CIRGenFunction &cgf, mlir::Value v, QualType t,
116 cir::IntType intType) {
117 v = cgf.emitToMemory(v, t);
118
119 if (mlir::isa<cir::PointerType>(v.getType()))
120 return cgf.getBuilder().createPtrToInt(v, intType);
121
122 assert(v.getType() == intType);
123 return v;
124}
125
126static mlir::Value emitFromInt(CIRGenFunction &cgf, mlir::Value v, QualType t,
127 mlir::Type resultType) {
128 v = cgf.emitFromMemory(v, t);
129
130 if (mlir::isa<cir::PointerType>(resultType))
131 return cgf.getBuilder().createIntToPtr(v, resultType);
132
133 assert(v.getType() == resultType);
134 return v;
135}
136
137static mlir::Value emitSignBit(mlir::Location loc, CIRGenFunction &cgf,
138 mlir::Value val) {
140 cir::SignBitOp returnValue = cgf.getBuilder().createSignBit(loc, val);
141 return returnValue->getResult(0);
142}
143
145 ASTContext &astContext = cgf.getContext();
146 Address ptr = cgf.emitPointerWithAlignment(e->getArg(0));
147 unsigned bytes =
148 mlir::isa<cir::PointerType>(ptr.getElementType())
149 ? astContext.getTypeSizeInChars(astContext.VoidPtrTy).getQuantity()
152
153 unsigned align = ptr.getAlignment().getQuantity();
154 if (align % bytes != 0) {
155 DiagnosticsEngine &diags = cgf.cgm.getDiags();
156 diags.Report(e->getBeginLoc(), diag::warn_sync_op_misaligned);
157 // Force address to be at least naturally-aligned.
159 }
160 return ptr;
161}
162
163/// Utility to insert an atomic instruction based on Intrinsic::ID
164/// and the expression node.
165static mlir::Value makeBinaryAtomicValue(
166 CIRGenFunction &cgf, cir::AtomicFetchKind kind, const CallExpr *expr,
167 mlir::Type *originalArgType = nullptr,
168 mlir::Value *emittedArgValue = nullptr,
169 cir::MemOrder ordering = cir::MemOrder::SequentiallyConsistent) {
170
171 QualType type = expr->getType();
172 QualType ptrType = expr->getArg(0)->getType();
173
174 assert(ptrType->isPointerType());
175 assert(
178 expr->getArg(1)->getType()));
179
180 Address destAddr = checkAtomicAlignment(cgf, expr);
181 CIRGenBuilderTy &builder = cgf.getBuilder();
182
183 mlir::Value val = cgf.emitScalarExpr(expr->getArg(1));
184 mlir::Type valueType = val.getType();
185 mlir::Value destValue = destAddr.emitRawPointer();
186
187 if (ptrType->getPointeeType()->isPointerType()) {
188 // Pointer to pointer
189 // `cir.atomic.fetch` expects a pointer to an integer type, so we cast
190 // ptr<ptr<T>> to ptr<intPtrSize>
191 cir::IntType ptrSizeInt =
192 builder.getSIntNTy(cgf.getContext().getTypeSize(ptrType));
193 destValue =
194 builder.createBitcast(destValue, builder.getPointerTo(ptrSizeInt));
195 val = emitToInt(cgf, val, type, ptrSizeInt);
196 } else {
197 // Pointer to integer type
198 cir::IntType intType =
200 ? builder.getUIntNTy(cgf.getContext().getTypeSize(type))
201 : builder.getSIntNTy(cgf.getContext().getTypeSize(type));
202 val = emitToInt(cgf, val, type, intType);
203 }
204
205 // This output argument is needed for post atomic fetch operations
206 // that calculate the result of the operation as return value of
207 // <binop>_and_fetch builtins. The `AtomicFetch` operation only updates the
208 // memory location and returns the old value.
209 if (emittedArgValue) {
210 *emittedArgValue = val;
211 assert(originalArgType != nullptr &&
212 "originalArgType must be provided when emittedArgValue is set");
213 *originalArgType = valueType;
214 }
215
216 auto rmwi = cir::AtomicFetchOp::create(
217 builder, cgf.getLoc(expr->getSourceRange()), destValue, val, kind,
218 ordering, cir::SyncScopeKind::System, false, /* is volatile */
219 true); /* fetch first */
220 return rmwi->getResult(0);
221}
222
224 cir::AtomicFetchKind atomicOpkind,
225 const CallExpr *e) {
226 return RValue::get(makeBinaryAtomicValue(cgf, atomicOpkind, e));
227}
228
229template <typename BinOp>
231 cir::AtomicFetchKind atomicOpkind,
232 const CallExpr *e, bool invert = false) {
233 mlir::Value emittedArgValue;
234 mlir::Type originalArgType;
235 clang::QualType typ = e->getType();
236 mlir::Value result = makeBinaryAtomicValue(
237 cgf, atomicOpkind, e, &originalArgType, &emittedArgValue);
239 result = BinOp::create(builder, result.getLoc(), result, emittedArgValue);
240
241 if (invert)
242 result = builder.createNot(result);
243
244 result = emitFromInt(cgf, result, typ, originalArgType);
245 return RValue::get(result);
246}
247
249 cir::SyncScopeKind syncScope) {
250 CIRGenBuilderTy &builder = cgf.getBuilder();
251 mlir::Location loc = cgf.getLoc(expr->getSourceRange());
252
253 auto emitAtomicOpCallBackFn = [&](cir::MemOrder memOrder) {
254 cir::AtomicFenceOp::create(
255 builder, loc, memOrder,
256 cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
257 };
258
259 cgf.emitAtomicExprWithMemOrder(expr->getArg(0), /*isStore*/ false,
260 /*isLoad*/ false, /*isFence*/ true,
261 emitAtomicOpCallBackFn);
262}
263
264namespace {
265struct WidthAndSignedness {
266 unsigned width;
267 bool isSigned;
268};
269} // namespace
270
271static WidthAndSignedness
273 const clang::QualType type) {
274 assert(type->isIntegerType() && "Given type is not an integer.");
275 unsigned width = type->isBooleanType() ? 1
276 : type->isBitIntType() ? astContext.getIntWidth(type)
277 : astContext.getTypeInfo(type).Width;
278 bool isSigned = type->isSignedIntegerType();
279 return {width, isSigned};
280}
281
282/// Create a checked overflow arithmetic op and return its result and overflow
283/// flag.
284template <typename OpTy>
285static std::pair<mlir::Value, mlir::Value>
286emitOverflowOp(CIRGenBuilderTy &builder, mlir::Location loc,
287 cir::IntType resultTy, mlir::Value lhs, mlir::Value rhs) {
288 auto op = OpTy::create(builder, loc, resultTy, lhs, rhs);
289 return {op.getResult(), op.getOverflow()};
290}
291
292// Given one or more integer types, this function produces an integer type that
293// encompasses them: any value in one of the given types could be expressed in
294// the encompassing type.
295static struct WidthAndSignedness
296EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> types) {
297 assert(types.size() > 0 && "Empty list of types.");
298
299 // If any of the given types is signed, we must return a signed type.
300 bool isSigned = llvm::any_of(types, [](const auto &t) { return t.isSigned; });
301
302 // The encompassing type must have a width greater than or equal to the width
303 // of the specified types. Additionally, if the encompassing type is signed,
304 // its width must be strictly greater than the width of any unsigned types
305 // given.
306 unsigned width = 0;
307 for (const auto &type : types)
308 width = std::max(width, type.width + (isSigned && !type.isSigned));
309
310 return {width, isSigned};
311}
312
313RValue CIRGenFunction::emitRotate(const CallExpr *e, bool isRotateLeft) {
314 mlir::Value input = emitScalarExpr(e->getArg(0));
315 mlir::Value amount = emitScalarExpr(e->getArg(1));
316
317 // TODO(cir): MSVC flavor bit rotate builtins use different types for input
318 // and amount, but cir.rotate requires them to have the same type. Cast amount
319 // to the type of input when necessary.
321
322 auto r = cir::RotateOp::create(builder, getLoc(e->getSourceRange()), input,
323 amount, isRotateLeft);
324 return RValue::get(r);
325}
326
327template <class Operation>
329 const CallExpr &e) {
330 mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
331
332 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &e);
334
335 auto call =
336 Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(), arg);
337 return RValue::get(call->getResult(0));
338}
339
340template <class Operation>
342 mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
343 auto call =
344 Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(), arg);
345 return RValue::get(call->getResult(0));
346}
347
348template <typename Op>
350 const CallExpr &e) {
351 mlir::Type resultType = cgf.convertType(e.getType());
352 mlir::Value src = cgf.emitScalarExpr(e.getArg(0));
353
355
356 auto call = Op::create(cgf.getBuilder(), src.getLoc(), resultType, src);
357 return RValue::get(call->getResult(0));
358}
359
360template <typename Op>
362 mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
363 mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
364
365 mlir::Location loc = cgf.getLoc(e.getExprLoc());
366 mlir::Type ty = cgf.convertType(e.getType());
367 auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1);
368
369 return RValue::get(call->getResult(0));
370}
371
372template <typename Op>
374 const CallExpr &e) {
375 mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
376 mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
377
378 mlir::Location loc = cgf.getLoc(e.getExprLoc());
379 mlir::Type ty = cgf.convertType(e.getType());
380
382
383 auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1);
384 return call->getResult(0);
385}
386
388 unsigned builtinID) {
389
390 if (cgf.getContext().BuiltinInfo.isLibFunction(builtinID)) {
391 cgf.cgm.errorNYI(
392 e->getSourceRange(),
393 std::string("unimplemented X86 library function builtin call: ") +
394 cgf.getContext().BuiltinInfo.getName(builtinID));
395 } else {
396 cgf.cgm.errorNYI(e->getSourceRange(),
397 std::string("unimplemented X86 builtin call: ") +
398 cgf.getContext().BuiltinInfo.getName(builtinID));
399 }
400
401 return cgf.getUndefRValue(e->getType());
402}
403
405 unsigned builtinID) {
406 assert(builtinID == Builtin::BI__builtin_alloca ||
407 builtinID == Builtin::BI__builtin_alloca_uninitialized ||
408 builtinID == Builtin::BIalloca || builtinID == Builtin::BI_alloca);
409
410 // Get alloca size input
411 mlir::Value size = cgf.emitScalarExpr(e->getArg(0));
412
413 // The alignment of the alloca should correspond to __BIGGEST_ALIGNMENT__.
414 const TargetInfo &ti = cgf.getContext().getTargetInfo();
415 const CharUnits suitableAlignmentInBytes =
417
418 // Emit the alloca op with type `u8 *` to match the semantics of
419 // `llvm.alloca`. We later bitcast the type to `void *` to match the
420 // semantics of C/C++
421 // FIXME(cir): It may make sense to allow AllocaOp of type `u8` to return a
422 // pointer of type `void *`. This will require a change to the allocaOp
423 // verifier.
424 CIRGenBuilderTy &builder = cgf.getBuilder();
425 mlir::Value allocaAddr = builder.createAlloca(
426 cgf.getLoc(e->getSourceRange()), builder.getUInt8PtrTy(),
427 builder.getUInt8Ty(), "bi_alloca", suitableAlignmentInBytes, size);
428
429 // Initialize the allocated buffer if required.
430 if (builtinID != Builtin::BI__builtin_alloca_uninitialized) {
431 // Initialize the alloca with the given size and alignment according to
432 // the lang opts. Only the trivial non-initialization is supported for
433 // now.
434
435 switch (cgf.getLangOpts().getTrivialAutoVarInit()) {
437 // Nothing to initialize.
438 break;
441 cgf.cgm.errorNYI("trivial auto var init");
442 break;
443 }
444 }
445
446 // An alloca will always return a pointer to the alloca (stack) address
447 // space. This address space need not be the same as the AST / Language
448 // default (e.g. in C / C++ auto vars are in the generic address space). At
449 // the AST level this is handled within CreateTempAlloca et al., but for the
450 // builtin / dynamic alloca we have to handle it here.
451
455 cgf.cgm.errorNYI(e->getSourceRange(),
456 "Address Space Cast for builtin alloca");
457 }
458
459 // Bitcast the alloca to the expected type.
460 return RValue::get(builder.createBitcast(
461 allocaAddr, builder.getVoidPtrTy(cgf.getCIRAllocaAddressSpace())));
462}
463
465 unsigned builtinID) {
466 std::optional<bool> errnoOverriden;
467 // ErrnoOverriden is true if math-errno is overriden via the
468 // '#pragma float_control(precise, on)'. This pragma disables fast-math,
469 // which implies math-errno.
470 if (e->hasStoredFPFeatures()) {
472 if (op.hasMathErrnoOverride())
473 errnoOverriden = op.getMathErrnoOverride();
474 }
475 // True if 'attribute__((optnone))' is used. This attribute overrides
476 // fast-math which implies math-errno.
477 bool optNone =
478 cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<OptimizeNoneAttr>();
479 bool isOptimizationEnabled = cgf.cgm.getCodeGenOpts().OptimizationLevel != 0;
480 bool generateFPMathIntrinsics =
482 builtinID, cgf.cgm.getTriple(), errnoOverriden,
483 cgf.getLangOpts().MathErrno, optNone, isOptimizationEnabled);
484 return generateFPMathIntrinsics;
485}
486
488 unsigned builtinID) {
490 switch (builtinID) {
491 case Builtin::BIacos:
492 case Builtin::BIacosf:
493 case Builtin::BIacosl:
494 case Builtin::BI__builtin_acos:
495 case Builtin::BI__builtin_acosf:
496 case Builtin::BI__builtin_acosf16:
497 case Builtin::BI__builtin_acosl:
498 case Builtin::BI__builtin_acosf128:
499 case Builtin::BI__builtin_elementwise_acos:
501 case Builtin::BIasin:
502 case Builtin::BIasinf:
503 case Builtin::BIasinl:
504 case Builtin::BI__builtin_asin:
505 case Builtin::BI__builtin_asinf:
506 case Builtin::BI__builtin_asinf16:
507 case Builtin::BI__builtin_asinl:
508 case Builtin::BI__builtin_asinf128:
509 case Builtin::BI__builtin_elementwise_asin:
511 case Builtin::BIatan:
512 case Builtin::BIatanf:
513 case Builtin::BIatanl:
514 case Builtin::BI__builtin_atan:
515 case Builtin::BI__builtin_atanf:
516 case Builtin::BI__builtin_atanf16:
517 case Builtin::BI__builtin_atanl:
518 case Builtin::BI__builtin_atanf128:
519 case Builtin::BI__builtin_elementwise_atan:
521 case Builtin::BIatan2:
522 case Builtin::BIatan2f:
523 case Builtin::BIatan2l:
524 case Builtin::BI__builtin_atan2:
525 case Builtin::BI__builtin_atan2f:
526 case Builtin::BI__builtin_atan2f16:
527 case Builtin::BI__builtin_atan2l:
528 case Builtin::BI__builtin_atan2f128:
529 case Builtin::BI__builtin_elementwise_atan2:
530 return RValue::get(
532 case Builtin::BIceil:
533 case Builtin::BIceilf:
534 case Builtin::BIceill:
535 case Builtin::BI__builtin_ceil:
536 case Builtin::BI__builtin_ceilf:
537 case Builtin::BI__builtin_ceilf16:
538 case Builtin::BI__builtin_ceill:
539 case Builtin::BI__builtin_ceilf128:
541 case Builtin::BI__builtin_elementwise_ceil:
542 return RValue::getIgnored();
543 case Builtin::BIcopysign:
544 case Builtin::BIcopysignf:
545 case Builtin::BIcopysignl:
546 case Builtin::BI__builtin_copysign:
547 case Builtin::BI__builtin_copysignf:
548 case Builtin::BI__builtin_copysignf16:
549 case Builtin::BI__builtin_copysignl:
550 case Builtin::BI__builtin_copysignf128:
552 case Builtin::BIcos:
553 case Builtin::BIcosf:
554 case Builtin::BIcosl:
555 case Builtin::BI__builtin_cos:
556 case Builtin::BI__builtin_cosf:
557 case Builtin::BI__builtin_cosf16:
558 case Builtin::BI__builtin_cosl:
559 case Builtin::BI__builtin_cosf128:
561 case Builtin::BI__builtin_elementwise_cos:
562 case Builtin::BIcosh:
563 case Builtin::BIcoshf:
564 case Builtin::BIcoshl:
565 case Builtin::BI__builtin_cosh:
566 case Builtin::BI__builtin_coshf:
567 case Builtin::BI__builtin_coshf16:
568 case Builtin::BI__builtin_coshl:
569 case Builtin::BI__builtin_coshf128:
570 case Builtin::BI__builtin_elementwise_cosh:
571 return RValue::getIgnored();
572 case Builtin::BIexp:
573 case Builtin::BIexpf:
574 case Builtin::BIexpl:
575 case Builtin::BI__builtin_exp:
576 case Builtin::BI__builtin_expf:
577 case Builtin::BI__builtin_expf16:
578 case Builtin::BI__builtin_expl:
579 case Builtin::BI__builtin_expf128:
581 case Builtin::BI__builtin_elementwise_exp:
582 return RValue::getIgnored();
583 case Builtin::BIexp2:
584 case Builtin::BIexp2f:
585 case Builtin::BIexp2l:
586 case Builtin::BI__builtin_exp2:
587 case Builtin::BI__builtin_exp2f:
588 case Builtin::BI__builtin_exp2f16:
589 case Builtin::BI__builtin_exp2l:
590 case Builtin::BI__builtin_exp2f128:
592 case Builtin::BI__builtin_elementwise_exp2:
593 case Builtin::BI__builtin_exp10:
594 case Builtin::BI__builtin_exp10f:
595 case Builtin::BI__builtin_exp10f16:
596 case Builtin::BI__builtin_exp10l:
597 case Builtin::BI__builtin_exp10f128:
598 case Builtin::BI__builtin_elementwise_exp10:
599 return RValue::getIgnored();
600 case Builtin::BIfabs:
601 case Builtin::BIfabsf:
602 case Builtin::BIfabsl:
603 case Builtin::BI__builtin_fabs:
604 case Builtin::BI__builtin_fabsf:
605 case Builtin::BI__builtin_fabsf16:
606 case Builtin::BI__builtin_fabsl:
607 case Builtin::BI__builtin_fabsf128:
609 case Builtin::BIfloor:
610 case Builtin::BIfloorf:
611 case Builtin::BIfloorl:
612 case Builtin::BI__builtin_floor:
613 case Builtin::BI__builtin_floorf:
614 case Builtin::BI__builtin_floorf16:
615 case Builtin::BI__builtin_floorl:
616 case Builtin::BI__builtin_floorf128:
618 case Builtin::BI__builtin_elementwise_floor:
619 case Builtin::BIfma:
620 case Builtin::BIfmaf:
621 case Builtin::BIfmal:
622 case Builtin::BI__builtin_fma:
623 case Builtin::BI__builtin_fmaf:
624 case Builtin::BI__builtin_fmaf16:
625 case Builtin::BI__builtin_fmal:
626 case Builtin::BI__builtin_fmaf128:
627 case Builtin::BI__builtin_elementwise_fma:
628 return RValue::getIgnored();
629 case Builtin::BIfmax:
630 case Builtin::BIfmaxf:
631 case Builtin::BIfmaxl:
632 case Builtin::BI__builtin_fmax:
633 case Builtin::BI__builtin_fmaxf:
634 case Builtin::BI__builtin_fmaxf16:
635 case Builtin::BI__builtin_fmaxl:
636 case Builtin::BI__builtin_fmaxf128:
637 return RValue::get(
639 case Builtin::BIfmin:
640 case Builtin::BIfminf:
641 case Builtin::BIfminl:
642 case Builtin::BI__builtin_fmin:
643 case Builtin::BI__builtin_fminf:
644 case Builtin::BI__builtin_fminf16:
645 case Builtin::BI__builtin_fminl:
646 case Builtin::BI__builtin_fminf128:
647 return RValue::get(
649 case Builtin::BIfmaximum_num:
650 case Builtin::BIfmaximum_numf:
651 case Builtin::BIfmaximum_numl:
652 case Builtin::BI__builtin_fmaximum_num:
653 case Builtin::BI__builtin_fmaximum_numf:
654 case Builtin::BI__builtin_fmaximum_numf16:
655 case Builtin::BI__builtin_fmaximum_numl:
656 case Builtin::BI__builtin_fmaximum_numf128:
657 case Builtin::BIfminimum_num:
658 case Builtin::BIfminimum_numf:
659 case Builtin::BIfminimum_numl:
660 case Builtin::BI__builtin_fminimum_num:
661 case Builtin::BI__builtin_fminimum_numf:
662 case Builtin::BI__builtin_fminimum_numf16:
663 case Builtin::BI__builtin_fminimum_numl:
664 case Builtin::BI__builtin_fminimum_numf128:
665 return RValue::getIgnored();
666 case Builtin::BIfmod:
667 case Builtin::BIfmodf:
668 case Builtin::BIfmodl:
669 case Builtin::BI__builtin_fmod:
670 case Builtin::BI__builtin_fmodf:
671 case Builtin::BI__builtin_fmodf16:
672 case Builtin::BI__builtin_fmodl:
673 case Builtin::BI__builtin_fmodf128:
674 case Builtin::BI__builtin_elementwise_fmod:
675 return RValue::get(
677 case Builtin::BIlog:
678 case Builtin::BIlogf:
679 case Builtin::BIlogl:
680 case Builtin::BI__builtin_log:
681 case Builtin::BI__builtin_logf:
682 case Builtin::BI__builtin_logf16:
683 case Builtin::BI__builtin_logl:
684 case Builtin::BI__builtin_logf128:
685 case Builtin::BI__builtin_elementwise_log:
687 case Builtin::BIlog10:
688 case Builtin::BIlog10f:
689 case Builtin::BIlog10l:
690 case Builtin::BI__builtin_log10:
691 case Builtin::BI__builtin_log10f:
692 case Builtin::BI__builtin_log10f16:
693 case Builtin::BI__builtin_log10l:
694 case Builtin::BI__builtin_log10f128:
695 case Builtin::BI__builtin_elementwise_log10:
697 case Builtin::BIlog2:
698 case Builtin::BIlog2f:
699 case Builtin::BIlog2l:
700 case Builtin::BI__builtin_log2:
701 case Builtin::BI__builtin_log2f:
702 case Builtin::BI__builtin_log2f16:
703 case Builtin::BI__builtin_log2l:
704 case Builtin::BI__builtin_log2f128:
705 case Builtin::BI__builtin_elementwise_log2:
707 case Builtin::BInearbyint:
708 case Builtin::BInearbyintf:
709 case Builtin::BInearbyintl:
710 case Builtin::BI__builtin_nearbyint:
711 case Builtin::BI__builtin_nearbyintf:
712 case Builtin::BI__builtin_nearbyintl:
713 case Builtin::BI__builtin_nearbyintf128:
714 case Builtin::BI__builtin_elementwise_nearbyint:
716 case Builtin::BIpow:
717 case Builtin::BIpowf:
718 case Builtin::BIpowl:
719 case Builtin::BI__builtin_pow:
720 case Builtin::BI__builtin_powf:
721 case Builtin::BI__builtin_powf16:
722 case Builtin::BI__builtin_powl:
723 case Builtin::BI__builtin_powf128:
724 return RValue::get(
726 case Builtin::BI__builtin_elementwise_pow:
727 return RValue::getIgnored();
728 case Builtin::BIrint:
729 case Builtin::BIrintf:
730 case Builtin::BIrintl:
731 case Builtin::BI__builtin_rint:
732 case Builtin::BI__builtin_rintf:
733 case Builtin::BI__builtin_rintf16:
734 case Builtin::BI__builtin_rintl:
735 case Builtin::BI__builtin_rintf128:
736 case Builtin::BI__builtin_elementwise_rint:
738 case Builtin::BIround:
739 case Builtin::BIroundf:
740 case Builtin::BIroundl:
741 case Builtin::BI__builtin_round:
742 case Builtin::BI__builtin_roundf:
743 case Builtin::BI__builtin_roundf16:
744 case Builtin::BI__builtin_roundl:
745 case Builtin::BI__builtin_roundf128:
746 case Builtin::BI__builtin_elementwise_round:
748 case Builtin::BIroundeven:
749 case Builtin::BIroundevenf:
750 case Builtin::BIroundevenl:
751 case Builtin::BI__builtin_roundeven:
752 case Builtin::BI__builtin_roundevenf:
753 case Builtin::BI__builtin_roundevenf16:
754 case Builtin::BI__builtin_roundevenl:
755 case Builtin::BI__builtin_roundevenf128:
756 case Builtin::BI__builtin_elementwise_roundeven:
758 case Builtin::BIsin:
759 case Builtin::BIsinf:
760 case Builtin::BIsinl:
761 case Builtin::BI__builtin_sin:
762 case Builtin::BI__builtin_sinf:
763 case Builtin::BI__builtin_sinf16:
764 case Builtin::BI__builtin_sinl:
765 case Builtin::BI__builtin_sinf128:
766 case Builtin::BI__builtin_elementwise_sin:
768 case Builtin::BIsinh:
769 case Builtin::BIsinhf:
770 case Builtin::BIsinhl:
771 case Builtin::BI__builtin_sinh:
772 case Builtin::BI__builtin_sinhf:
773 case Builtin::BI__builtin_sinhf16:
774 case Builtin::BI__builtin_sinhl:
775 case Builtin::BI__builtin_sinhf128:
776 case Builtin::BI__builtin_elementwise_sinh:
777 case Builtin::BI__builtin_sincospi:
778 case Builtin::BI__builtin_sincospif:
779 case Builtin::BI__builtin_sincospil:
780 case Builtin::BIsincos:
781 case Builtin::BIsincosf:
782 case Builtin::BIsincosl:
783 case Builtin::BI__builtin_sincos:
784 case Builtin::BI__builtin_sincosf:
785 case Builtin::BI__builtin_sincosf16:
786 case Builtin::BI__builtin_sincosl:
787 case Builtin::BI__builtin_sincosf128:
788 return RValue::getIgnored();
789 case Builtin::BIsqrt:
790 case Builtin::BIsqrtf:
791 case Builtin::BIsqrtl:
792 case Builtin::BI__builtin_sqrt:
793 case Builtin::BI__builtin_sqrtf:
794 case Builtin::BI__builtin_sqrtf16:
795 case Builtin::BI__builtin_sqrtl:
796 case Builtin::BI__builtin_sqrtf128:
797 case Builtin::BI__builtin_elementwise_sqrt:
799 case Builtin::BItan:
800 case Builtin::BItanf:
801 case Builtin::BItanl:
802 case Builtin::BI__builtin_tan:
803 case Builtin::BI__builtin_tanf:
804 case Builtin::BI__builtin_tanf16:
805 case Builtin::BI__builtin_tanl:
806 case Builtin::BI__builtin_tanf128:
807 case Builtin::BI__builtin_elementwise_tan:
809 case Builtin::BItanh:
810 case Builtin::BItanhf:
811 case Builtin::BItanhl:
812 case Builtin::BI__builtin_tanh:
813 case Builtin::BI__builtin_tanhf:
814 case Builtin::BI__builtin_tanhf16:
815 case Builtin::BI__builtin_tanhl:
816 case Builtin::BI__builtin_tanhf128:
817 case Builtin::BI__builtin_elementwise_tanh:
818 return RValue::getIgnored();
819 case Builtin::BItrunc:
820 case Builtin::BItruncf:
821 case Builtin::BItruncl:
822 case Builtin::BI__builtin_trunc:
823 case Builtin::BI__builtin_truncf:
824 case Builtin::BI__builtin_truncf16:
825 case Builtin::BI__builtin_truncl:
826 case Builtin::BI__builtin_truncf128:
827 case Builtin::BI__builtin_elementwise_trunc:
829 case Builtin::BIlround:
830 case Builtin::BIlroundf:
831 case Builtin::BIlroundl:
832 case Builtin::BI__builtin_lround:
833 case Builtin::BI__builtin_lroundf:
834 case Builtin::BI__builtin_lroundl:
835 case Builtin::BI__builtin_lroundf128:
837 case Builtin::BIllround:
838 case Builtin::BIllroundf:
839 case Builtin::BIllroundl:
840 case Builtin::BI__builtin_llround:
841 case Builtin::BI__builtin_llroundf:
842 case Builtin::BI__builtin_llroundl:
843 case Builtin::BI__builtin_llroundf128:
845 case Builtin::BIlrint:
846 case Builtin::BIlrintf:
847 case Builtin::BIlrintl:
848 case Builtin::BI__builtin_lrint:
849 case Builtin::BI__builtin_lrintf:
850 case Builtin::BI__builtin_lrintl:
851 case Builtin::BI__builtin_lrintf128:
853 case Builtin::BIllrint:
854 case Builtin::BIllrintf:
855 case Builtin::BIllrintl:
856 case Builtin::BI__builtin_llrint:
857 case Builtin::BI__builtin_llrintf:
858 case Builtin::BI__builtin_llrintl:
859 case Builtin::BI__builtin_llrintf128:
861 case Builtin::BI__builtin_ldexp:
862 case Builtin::BI__builtin_ldexpf:
863 case Builtin::BI__builtin_ldexpl:
864 case Builtin::BI__builtin_ldexpf16:
865 case Builtin::BI__builtin_ldexpf128:
866 case Builtin::BI__builtin_elementwise_ldexp:
867 default:
868 break;
869 }
870
871 return RValue::getIgnored();
872}
873
874// FIXME: Remove cgf parameter when all descriptor kinds are implemented
875static mlir::Type
878 mlir::MLIRContext *context) {
879 using namespace llvm::Intrinsic;
880
881 IITDescriptor descriptor = infos.front();
882 infos = infos.slice(1);
883
884 switch (descriptor.Kind) {
885 case IITDescriptor::Void:
886 return cir::VoidType::get(context);
887 case IITDescriptor::Half:
888 return cir::FP16Type::get(context);
889 case IITDescriptor::BFloat:
890 return cir::BF16Type::get(context);
891 case IITDescriptor::Float:
892 return cir::SingleType::get(context);
893 case IITDescriptor::Double:
894 return cir::DoubleType::get(context);
895 case IITDescriptor::Quad:
896 return cir::FP128Type::get(context);
897 // If the intrinsic expects unsigned integers, the signedness is corrected in
898 // correctIntegerSignedness()
899 case IITDescriptor::Integer:
900 return cir::IntType::get(context, descriptor.IntegerWidth,
901 /*isSigned=*/true);
902 case IITDescriptor::Vector: {
903 mlir::Type elementType = decodeFixedType(cgf, infos, context);
904 unsigned numElements = descriptor.VectorWidth.getFixedValue();
905 return cir::VectorType::get(elementType, numElements);
906 }
907 case IITDescriptor::Pointer: {
908 mlir::Builder builder(context);
909 auto addrSpace = cir::TargetAddressSpaceAttr::get(
910 context, descriptor.PointerAddressSpace);
911 return cir::PointerType::get(cir::VoidType::get(context), addrSpace);
912 }
913 default:
914 cgf.cgm.errorNYI("Unimplemented intrinsic type descriptor");
915 return cir::VoidType::get(context);
916 }
917}
918
919/// Helper function to correct integer signedness for intrinsic arguments and
920/// return type. IIT always returns signed integers, but the actual intrinsic
921/// may expect unsigned integers based on the AST FunctionDecl parameter types.
922static mlir::Type correctIntegerSignedness(mlir::Type iitType, QualType astType,
923 mlir::MLIRContext *context) {
924 auto intTy = dyn_cast<cir::IntType>(iitType);
925 if (!intTy)
926 return iitType;
927
928 if (astType->isUnsignedIntegerType())
929 return cir::IntType::get(context, intTy.getWidth(), /*isSigned=*/false);
930
931 return iitType;
932}
933
934static mlir::Value getCorrectedPtr(mlir::Value argValue, mlir::Type expectedTy,
935 CIRGenBuilderTy &builder) {
936 auto ptrType = mlir::cast<cir::PointerType>(argValue.getType());
937
938 auto expectedPtrType = mlir::cast<cir::PointerType>(expectedTy);
939 assert(ptrType != expectedPtrType && "types should not match");
940
941 if (ptrType.getAddrSpace() != expectedPtrType.getAddrSpace()) {
943 "address space handling not yet implemented");
944 auto newPtrType = cir::PointerType::get(ptrType.getPointee(),
945 expectedPtrType.getAddrSpace());
946 return builder.createAddrSpaceCast(argValue, newPtrType);
947 }
948
949 return builder.createBitcast(argValue, expectedTy);
950}
951
952static cir::FuncType getIntrinsicType(CIRGenFunction &cgf,
953 mlir::MLIRContext *context,
954 llvm::Intrinsic::ID id) {
955 using namespace llvm::Intrinsic;
956
958 auto [tableRef, _, isVarArg] = getIntrinsicInfoTableEntries(id, table);
959
960 mlir::Type resultTy = decodeFixedType(cgf, tableRef, context);
961
963 while (!tableRef.empty())
964 argTypes.push_back(decodeFixedType(cgf, tableRef, context));
965
966 // CIR convention: no explicit void return type
967 if (isa<cir::VoidType>(resultTy))
968 return cir::FuncType::get(context, argTypes, /*optionalReturnType=*/nullptr,
969 isVarArg);
970
971 return cir::FuncType::get(context, argTypes, resultTy, isVarArg);
972}
973
975 const CallExpr *e,
977 mlir::Location loc = getLoc(e->getSourceRange());
978
979 // See if we can constant fold this builtin. If so, don't emit it at all.
980 // TODO: Extend this handling to all builtin calls that we can constant-fold.
981 // Do not constant-fold immediate (target-specific) builtins; their ASTs can
982 // trigger the constant evaluator in cases it cannot safely handle.
983 // Skip EvaluateAsRValue for those.
984 Expr::EvalResult result;
985 if (e->isPRValue() && !getContext().BuiltinInfo.isImmediate(builtinID) &&
986 e->EvaluateAsRValue(result, cgm.getASTContext()) &&
987 !result.hasSideEffects()) {
988 if (result.Val.isInt()) {
989 QualType type = e->getType();
990 if (type->isBooleanType())
991 return RValue::get(
992 builder.getBool(result.Val.getInt().getBoolValue(), loc));
993 return RValue::get(builder.getConstInt(loc, result.Val.getInt()));
994 }
995 if (result.Val.isFloat()) {
996 // Note: we are using result type of CallExpr to determine the type of
997 // the constant. Classic codegen uses the result value to determine the
998 // type. We feel it should be Ok to use expression type because it is
999 // hard to imagine a builtin function evaluates to a value that
1000 // over/underflows its own defined type.
1001 mlir::Type type = convertType(e->getType());
1002 return RValue::get(builder.getConstFP(loc, type, result.Val.getFloat()));
1003 }
1004 }
1005
1006 const FunctionDecl *fd = gd.getDecl()->getAsFunction();
1007
1009
1010 // If the builtin has been declared explicitly with an assembler label,
1011 // disable the specialized emitting below. Ideally we should communicate the
1012 // rename in IR, or at least avoid generating the intrinsic calls that are
1013 // likely to get lowered to the renamed library functions.
1014 unsigned builtinIDIfNoAsmLabel = fd->hasAttr<AsmLabelAttr>() ? 0 : builtinID;
1015
1016 bool generateFPMathIntrinsics =
1017 shouldCIREmitFPMathIntrinsic(*this, e, builtinID);
1018
1019 if (generateFPMathIntrinsics) {
1020 // Try to match the builtinID with a floating point math builtin.
1021 RValue rv = tryEmitFPMathIntrinsic(*this, e, builtinIDIfNoAsmLabel);
1022
1023 // Return the result directly if a math intrinsic was generated.
1024 if (!rv.isIgnored()) {
1025 return rv;
1026 }
1027 }
1028
1030
1031 switch (builtinIDIfNoAsmLabel) {
1032 default:
1033 break;
1034
1035 // C stdarg builtins.
1036 case Builtin::BI__builtin_stdarg_start:
1037 case Builtin::BI__builtin_va_start:
1038 case Builtin::BI__va_start: {
1039 mlir::Value vaList = builtinID == Builtin::BI__va_start
1040 ? emitScalarExpr(e->getArg(0))
1041 : emitVAListRef(e->getArg(0)).getPointer();
1042 emitVAStart(vaList);
1043 return {};
1044 }
1045
1046 case Builtin::BI__builtin_va_end:
1048 return {};
1049 case Builtin::BI__builtin_va_copy: {
1050 mlir::Value dstPtr = emitVAListRef(e->getArg(0)).getPointer();
1051 mlir::Value srcPtr = emitVAListRef(e->getArg(1)).getPointer();
1052 cir::VACopyOp::create(builder, dstPtr.getLoc(), dstPtr, srcPtr);
1053 return {};
1054 }
1055
1056 case Builtin::BIabs:
1057 case Builtin::BIlabs:
1058 case Builtin::BIllabs:
1059 case Builtin::BI__builtin_abs:
1060 case Builtin::BI__builtin_labs:
1061 case Builtin::BI__builtin_llabs: {
1062 bool sanitizeOverflow = sanOpts.has(SanitizerKind::SignedIntegerOverflow);
1063 mlir::Value arg = emitScalarExpr(e->getArg(0));
1064 mlir::Value result;
1065 switch (getLangOpts().getSignedOverflowBehavior()) {
1067 result = cir::AbsOp::create(builder, loc, arg.getType(), arg,
1068 /*minIsPoison=*/false);
1069 break;
1071 if (!sanitizeOverflow) {
1072 result = cir::AbsOp::create(builder, loc, arg.getType(), arg,
1073 /*minIsPoison=*/true);
1074 break;
1075 }
1076 [[fallthrough]];
1078 cgm.errorNYI(e->getSourceRange(), "abs with overflow handling");
1079 return RValue::get(nullptr);
1080 }
1081 return RValue::get(result);
1082 }
1083
1084 case Builtin::BI__assume:
1085 case Builtin::BI__builtin_assume: {
1086 if (e->getArg(0)->HasSideEffects(getContext()))
1087 return RValue::get(nullptr);
1088
1089 mlir::Value argValue = emitCheckedArgForAssume(e->getArg(0));
1090 cir::AssumeOp::create(builder, loc, argValue);
1091 return RValue::get(nullptr);
1092 }
1093
1094 case Builtin::BI__builtin_assume_separate_storage: {
1095 mlir::Value value0 = emitScalarExpr(e->getArg(0));
1096 mlir::Value value1 = emitScalarExpr(e->getArg(1));
1097 cir::AssumeSepStorageOp::create(builder, loc, value0, value1);
1098 return RValue::get(nullptr);
1099 }
1100
1101 case Builtin::BI__builtin_assume_aligned: {
1102 const Expr *ptrExpr = e->getArg(0);
1103 mlir::Value ptrValue = emitScalarExpr(ptrExpr);
1104 mlir::Value offsetValue =
1105 (e->getNumArgs() > 2) ? emitScalarExpr(e->getArg(2)) : nullptr;
1106
1107 std::optional<llvm::APSInt> alignment =
1109 assert(alignment.has_value() &&
1110 "the second argument to __builtin_assume_aligned must be an "
1111 "integral constant expression");
1112
1113 mlir::Value result =
1114 emitAlignmentAssumption(ptrValue, ptrExpr, ptrExpr->getExprLoc(),
1115 alignment->getSExtValue(), offsetValue);
1116 return RValue::get(result);
1117 }
1118
1119 case Builtin::BI__builtin_complex: {
1120 mlir::Value real = emitScalarExpr(e->getArg(0));
1121 mlir::Value imag = emitScalarExpr(e->getArg(1));
1122 mlir::Value complex = builder.createComplexCreate(loc, real, imag);
1123 return RValue::getComplex(complex);
1124 }
1125
1126 case Builtin::BI__builtin_creal:
1127 case Builtin::BI__builtin_crealf:
1128 case Builtin::BI__builtin_creall:
1129 case Builtin::BIcreal:
1130 case Builtin::BIcrealf:
1131 case Builtin::BIcreall: {
1132 mlir::Value complex = emitComplexExpr(e->getArg(0));
1133 mlir::Value real = builder.createComplexReal(loc, complex);
1134 return RValue::get(real);
1135 }
1136
1137 case Builtin::BI__builtin_cimag:
1138 case Builtin::BI__builtin_cimagf:
1139 case Builtin::BI__builtin_cimagl:
1140 case Builtin::BIcimag:
1141 case Builtin::BIcimagf:
1142 case Builtin::BIcimagl: {
1143 mlir::Value complex = emitComplexExpr(e->getArg(0));
1144 mlir::Value imag = builder.createComplexImag(loc, complex);
1145 return RValue::get(imag);
1146 }
1147
1148 case Builtin::BI__builtin_conj:
1149 case Builtin::BI__builtin_conjf:
1150 case Builtin::BI__builtin_conjl:
1151 case Builtin::BIconj:
1152 case Builtin::BIconjf:
1153 case Builtin::BIconjl: {
1154 mlir::Value complex = emitComplexExpr(e->getArg(0));
1155 mlir::Value conj = builder.createNot(complex);
1156 return RValue::getComplex(conj);
1157 }
1158
1159 case Builtin::BI__builtin_clrsb:
1160 case Builtin::BI__builtin_clrsbl:
1161 case Builtin::BI__builtin_clrsbll:
1162 return emitBuiltinBitOp<cir::BitClrsbOp>(*this, e);
1163
1164 case Builtin::BI__builtin_ctzs:
1165 case Builtin::BI__builtin_ctz:
1166 case Builtin::BI__builtin_ctzl:
1167 case Builtin::BI__builtin_ctzll:
1169 return emitBuiltinBitOp<cir::BitCtzOp>(*this, e,
1170 getTarget().isCLZForZeroUndef());
1171 case Builtin::BI__builtin_ctzg:
1173
1174 case Builtin::BI__builtin_clzs:
1175 case Builtin::BI__builtin_clz:
1176 case Builtin::BI__builtin_clzl:
1177 case Builtin::BI__builtin_clzll:
1179 return emitBuiltinBitOp<cir::BitClzOp>(*this, e,
1180 getTarget().isCLZForZeroUndef());
1181 case Builtin::BI__builtin_clzg:
1183
1184 case Builtin::BI__builtin_elementwise_ctzg:
1185 cgm.errorNYI(e->getSourceRange(), "__builtin_elementwise_ctzg");
1186 return RValue::get(nullptr);
1187 case Builtin::BI__builtin_elementwise_clzg:
1188 cgm.errorNYI(e->getSourceRange(), "__builtin_elementwise_clzg");
1189 return RValue::get(nullptr);
1190
1191 case Builtin::BI__builtin_ffs:
1192 case Builtin::BI__builtin_ffsl:
1193 case Builtin::BI__builtin_ffsll:
1194 return emitBuiltinBitOp<cir::BitFfsOp>(*this, e);
1195
1196 case Builtin::BI__builtin_parity:
1197 case Builtin::BI__builtin_parityl:
1198 case Builtin::BI__builtin_parityll:
1199 return emitBuiltinBitOp<cir::BitParityOp>(*this, e);
1200
1201 case Builtin::BI__lzcnt16:
1202 case Builtin::BI__lzcnt:
1203 case Builtin::BI__lzcnt64:
1204 return emitBuiltinBitOp<cir::BitClzOp>(*this, e);
1205
1206 case Builtin::BI__popcnt16:
1207 case Builtin::BI__popcnt:
1208 case Builtin::BI__popcnt64:
1209 case Builtin::BI__builtin_popcount:
1210 case Builtin::BI__builtin_popcountl:
1211 case Builtin::BI__builtin_popcountll:
1212 case Builtin::BI__builtin_popcountg:
1213 return emitBuiltinBitOp<cir::BitPopcountOp>(*this, e);
1214
1215 // Always return the argument of __builtin_unpredictable. LLVM does not
1216 // have an intrinsic corresponding to this builtin. Metadata for this
1217 // builtin should be added directly to instructions such as branches or
1218 // switches that use it.
1219 case Builtin::BI__builtin_unpredictable: {
1220 return RValue::get(emitScalarExpr(e->getArg(0)));
1221 }
1222
1223 case Builtin::BI__builtin_expect:
1224 case Builtin::BI__builtin_expect_with_probability: {
1225 mlir::Value argValue = emitScalarExpr(e->getArg(0));
1226 if (cgm.getCodeGenOpts().OptimizationLevel == 0)
1227 return RValue::get(argValue);
1228
1229 mlir::Value expectedValue = emitScalarExpr(e->getArg(1));
1230
1231 mlir::FloatAttr probAttr;
1232 if (builtinIDIfNoAsmLabel == Builtin::BI__builtin_expect_with_probability) {
1233 llvm::APFloat probability(0.0);
1234 const Expr *probArg = e->getArg(2);
1235 [[maybe_unused]] bool evalSucceeded =
1236 probArg->EvaluateAsFloat(probability, cgm.getASTContext());
1237 assert(evalSucceeded &&
1238 "probability should be able to evaluate as float");
1239 bool loseInfo = false; // ignored
1240 probability.convert(llvm::APFloat::IEEEdouble(),
1241 llvm::RoundingMode::Dynamic, &loseInfo);
1242 probAttr = mlir::FloatAttr::get(mlir::Float64Type::get(&getMLIRContext()),
1243 probability);
1244 }
1245
1246 auto result = cir::ExpectOp::create(builder, loc, argValue.getType(),
1247 argValue, expectedValue, probAttr);
1248 return RValue::get(result);
1249 }
1250
1251 case Builtin::BI__builtin_bswap16:
1252 case Builtin::BI__builtin_bswap32:
1253 case Builtin::BI__builtin_bswap64:
1254 case Builtin::BI_byteswap_ushort:
1255 case Builtin::BI_byteswap_ulong:
1256 case Builtin::BI_byteswap_uint64: {
1257 mlir::Value arg = emitScalarExpr(e->getArg(0));
1258 return RValue::get(cir::ByteSwapOp::create(builder, loc, arg));
1259 }
1260
1261 case Builtin::BI__builtin_bitreverse8:
1262 case Builtin::BI__builtin_bitreverse16:
1263 case Builtin::BI__builtin_bitreverse32:
1264 case Builtin::BI__builtin_bitreverse64: {
1265 mlir::Value arg = emitScalarExpr(e->getArg(0));
1266 return RValue::get(cir::BitReverseOp::create(builder, loc, arg));
1267 }
1268
1269 case Builtin::BI__builtin_rotateleft8:
1270 case Builtin::BI__builtin_rotateleft16:
1271 case Builtin::BI__builtin_rotateleft32:
1272 case Builtin::BI__builtin_rotateleft64:
1273 return emitRotate(e, /*isRotateLeft=*/true);
1274
1275 case Builtin::BI__builtin_rotateright8:
1276 case Builtin::BI__builtin_rotateright16:
1277 case Builtin::BI__builtin_rotateright32:
1278 case Builtin::BI__builtin_rotateright64:
1279 return emitRotate(e, /*isRotateLeft=*/false);
1280
1281 case Builtin::BI__builtin_coro_id:
1282 case Builtin::BI__builtin_coro_promise:
1283 case Builtin::BI__builtin_coro_resume:
1284 case Builtin::BI__builtin_coro_noop:
1285 case Builtin::BI__builtin_coro_destroy:
1286 case Builtin::BI__builtin_coro_done:
1287 case Builtin::BI__builtin_coro_alloc:
1288 case Builtin::BI__builtin_coro_begin:
1289 case Builtin::BI__builtin_coro_end:
1290 case Builtin::BI__builtin_coro_suspend:
1291 case Builtin::BI__builtin_coro_align:
1292 cgm.errorNYI(e->getSourceRange(), "BI__builtin_coro_id like NYI");
1293 return getUndefRValue(e->getType());
1294
1295 case Builtin::BI__builtin_coro_frame: {
1296 return emitCoroutineFrame();
1297 }
1298 case Builtin::BI__builtin_coro_free:
1299 return RValue::get(emitCoroFreeBuiltin(e).getResult());
1300 case Builtin::BI__builtin_coro_size: {
1301 GlobalDecl gd{fd};
1302 mlir::Type ty = cgm.getTypes().getFunctionType(
1303 cgm.getTypes().arrangeGlobalDeclaration(gd));
1304 const auto *nd = cast<NamedDecl>(gd.getDecl());
1305 cir::FuncOp fnOp =
1306 cgm.getOrCreateCIRFunction(nd->getName(), ty, gd, /*ForVTable=*/false);
1307 fnOp.setBuiltin(true);
1308 return emitCall(e->getCallee()->getType(), CIRGenCallee::forDirect(fnOp), e,
1309 returnValue);
1310 }
1311
1312 case Builtin::BI__builtin_constant_p: {
1313 mlir::Type resultType = convertType(e->getType());
1314
1315 const Expr *arg = e->getArg(0);
1316 QualType argType = arg->getType();
1317 // FIXME: The allowance for Obj-C pointers and block pointers is historical
1318 // and likely a mistake.
1319 if (!argType->isIntegralOrEnumerationType() && !argType->isFloatingType() &&
1320 !argType->isObjCObjectPointerType() && !argType->isBlockPointerType()) {
1321 // Per the GCC documentation, only numeric constants are recognized after
1322 // inlining.
1323 return RValue::get(
1324 builder.getConstInt(getLoc(e->getSourceRange()),
1325 mlir::cast<cir::IntType>(resultType), 0));
1326 }
1327
1328 if (arg->HasSideEffects(getContext())) {
1329 // The argument is unevaluated, so be conservative if it might have
1330 // side-effects.
1331 return RValue::get(
1332 builder.getConstInt(getLoc(e->getSourceRange()),
1333 mlir::cast<cir::IntType>(resultType), 0));
1334 }
1335
1336 mlir::Value argValue = emitScalarExpr(arg);
1337 if (argType->isObjCObjectPointerType()) {
1338 cgm.errorNYI(e->getSourceRange(),
1339 "__builtin_constant_p: Obj-C object pointer");
1340 return {};
1341 }
1342 argValue = builder.createBitcast(argValue, convertType(argType));
1343
1344 mlir::Value result = cir::IsConstantOp::create(
1345 builder, getLoc(e->getSourceRange()), argValue);
1346 // IsConstantOp returns a bool, but __builtin_constant_p returns an int.
1347 result = builder.createBoolToInt(result, resultType);
1348 return RValue::get(result);
1349 }
1350 case Builtin::BI__builtin_dynamic_object_size:
1351 case Builtin::BI__builtin_object_size: {
1352 unsigned type =
1353 e->getArg(1)->EvaluateKnownConstInt(getContext()).getZExtValue();
1354 auto resType = mlir::cast<cir::IntType>(convertType(e->getType()));
1355
1356 // We pass this builtin onto the optimizer so that it can figure out the
1357 // object size in more complex cases.
1358 bool isDynamic = builtinID == Builtin::BI__builtin_dynamic_object_size;
1359 return RValue::get(emitBuiltinObjectSize(e->getArg(0), type, resType,
1360 /*EmittedE=*/nullptr, isDynamic));
1361 }
1362
1363 case Builtin::BI__builtin_prefetch: {
1364 auto evaluateOperandAsInt = [&](const Expr *arg) {
1365 Expr::EvalResult res;
1366 [[maybe_unused]] bool evalSucceed =
1367 arg->EvaluateAsInt(res, cgm.getASTContext());
1368 assert(evalSucceed && "expression should be able to evaluate as int");
1369 return res.Val.getInt().getZExtValue();
1370 };
1371
1372 bool isWrite = false;
1373 if (e->getNumArgs() > 1)
1374 isWrite = evaluateOperandAsInt(e->getArg(1));
1375
1376 int locality = 3;
1377 if (e->getNumArgs() > 2)
1378 locality = evaluateOperandAsInt(e->getArg(2));
1379
1380 mlir::Value address = emitScalarExpr(e->getArg(0));
1381 cir::PrefetchOp::create(builder, loc, address, locality, isWrite);
1382 return RValue::get(nullptr);
1383 }
1384 case Builtin::BI__builtin_readcyclecounter:
1385 case Builtin::BI__builtin_readsteadycounter:
1386 return errorBuiltinNYI(*this, e, builtinID);
1387 case Builtin::BI__builtin___clear_cache: {
1388 mlir::Value begin =
1389 builder.createPtrBitcast(emitScalarExpr(e->getArg(0)), cgm.voidTy);
1390 mlir::Value end =
1391 builder.createPtrBitcast(emitScalarExpr(e->getArg(1)), cgm.voidTy);
1392 cir::ClearCacheOp::create(builder, getLoc(e->getSourceRange()), begin, end);
1393 return RValue::get(nullptr);
1394 }
1395 case Builtin::BI__builtin_trap:
1396 emitTrap(loc, /*createNewBlock=*/true);
1397 return RValue::getIgnored();
1398 case Builtin::BI__builtin_verbose_trap:
1400 emitTrap(loc, /*createNewBlock=*/true);
1401 return RValue::getIgnored();
1402 case Builtin::BI__debugbreak:
1403 return errorBuiltinNYI(*this, e, builtinID);
1404 case Builtin::BI__builtin_unreachable:
1405 emitUnreachable(e->getExprLoc(), /*createNewBlock=*/true);
1406 return RValue::getIgnored();
1407 case Builtin::BI__builtin_powi:
1408 case Builtin::BI__builtin_powif:
1409 case Builtin::BI__builtin_powil: {
1410 mlir::Value src0 = emitScalarExpr(e->getArg(0));
1411 mlir::Value src1 = emitScalarExpr(e->getArg(1));
1412 return RValue::get(builder.emitIntrinsicCallOp(
1413 getLoc(e->getExprLoc()), "powi", src0.getType(),
1414 mlir::ValueRange{src0, src1}));
1415 }
1416 case Builtin::BI__builtin_frexpl:
1417 case Builtin::BI__builtin_frexp:
1418 case Builtin::BI__builtin_frexpf:
1419 case Builtin::BI__builtin_frexpf128:
1420 case Builtin::BI__builtin_frexpf16: {
1421 mlir::Value val = emitScalarExpr(e->getArg(0));
1422 mlir::Value ptr = emitScalarExpr(e->getArg(1));
1423 mlir::Type fpTy = val.getType();
1424 QualType intQualTy = e->getArg(1)->getType()->getPointeeType();
1425 mlir::Type intTy = convertType(intQualTy);
1426 mlir::Location callLoc = getLoc(e->getExprLoc());
1427 auto frexpOp = cir::FrexpOp::create(builder, callLoc, fpTy, intTy, val);
1428 LValue lv = makeNaturalAlignAddrLValue(ptr, intQualTy);
1429 emitStoreOfScalar(frexpOp.getExp(), lv, /*isInit=*/false);
1430 return RValue::get(frexpOp.getResult());
1431 }
1432 case Builtin::BImodf:
1433 case Builtin::BImodff:
1434 case Builtin::BImodfl:
1435 case Builtin::BI__builtin_modf:
1436 case Builtin::BI__builtin_modff:
1437 case Builtin::BI__builtin_modfl: {
1438 mlir::Value val = emitScalarExpr(e->getArg(0));
1439 mlir::Value ptr = emitScalarExpr(e->getArg(1));
1440 mlir::Type fpTy = val.getType();
1441 mlir::Location callLoc = getLoc(e->getExprLoc());
1442 auto modfOp = cir::ModfOp::create(builder, callLoc, fpTy, fpTy, val);
1443 QualType destPtrTy = e->getArg(1)->getType()->getPointeeType();
1444 LValue lv = makeNaturalAlignAddrLValue(ptr, destPtrTy);
1445 emitStoreOfScalar(modfOp.getIntegral(), lv, /*isInit=*/false);
1446 return RValue::get(modfOp.getFractional());
1447 }
1448 case Builtin::BI__builtin_isgreater:
1449 case Builtin::BI__builtin_isgreaterequal:
1450 case Builtin::BI__builtin_isless:
1451 case Builtin::BI__builtin_islessequal:
1452 case Builtin::BI__builtin_islessgreater:
1453 case Builtin::BI__builtin_isunordered: {
1454 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1455 mlir::Value lhs = emitScalarExpr(e->getArg(0));
1456 mlir::Value rhs = emitScalarExpr(e->getArg(1));
1457 mlir::Location loc = getLoc(e->getBeginLoc());
1458 mlir::Type intTy = convertType(e->getType());
1459
1460 mlir::Value cmpResult;
1461 switch (builtinID) {
1462 case Builtin::BI__builtin_isgreater:
1463 cmpResult = builder.createCompare(loc, cir::CmpOpKind::gt, lhs, rhs);
1464 break;
1465 case Builtin::BI__builtin_isgreaterequal:
1466 cmpResult = builder.createCompare(loc, cir::CmpOpKind::ge, lhs, rhs);
1467 break;
1468 case Builtin::BI__builtin_isless:
1469 cmpResult = builder.createCompare(loc, cir::CmpOpKind::lt, lhs, rhs);
1470 break;
1471 case Builtin::BI__builtin_islessequal:
1472 cmpResult = builder.createCompare(loc, cir::CmpOpKind::le, lhs, rhs);
1473 break;
1474 case Builtin::BI__builtin_islessgreater:
1475 cmpResult = builder.createCompare(loc, cir::CmpOpKind::one, lhs, rhs);
1476 break;
1477 case Builtin::BI__builtin_isunordered:
1478 cmpResult = builder.createCompare(loc, cir::CmpOpKind::uno, lhs, rhs);
1479 break;
1480 default:
1481 llvm_unreachable("Unknown ordered comparison");
1482 }
1483 return RValue::get(builder.createBoolToInt(cmpResult, intTy));
1484 }
1485 // From https://clang.llvm.org/docs/LanguageExtensions.html#builtin-isfpclass
1486 //
1487 // The `__builtin_isfpclass()` builtin is a generalization of functions
1488 // isnan, isinf, isfinite and some others defined by the C standard. It tests
1489 // if the floating-point value, specified by the first argument, falls into
1490 // any of data classes, specified by the second argument.
1491 case Builtin::BI__builtin_isnan: {
1492 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1493 mlir::Value v = emitScalarExpr(e->getArg(0));
1495 mlir::Location loc = getLoc(e->getBeginLoc());
1496 return RValue::get(builder.createBoolToInt(
1497 builder.createIsFPClass(loc, v, cir::FPClassTest::Nan),
1498 convertType(e->getType())));
1499 }
1500
1501 case Builtin::BI__builtin_issignaling: {
1502 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1503 mlir::Value v = emitScalarExpr(e->getArg(0));
1504 mlir::Location loc = getLoc(e->getBeginLoc());
1505 return RValue::get(builder.createBoolToInt(
1506 builder.createIsFPClass(loc, v, cir::FPClassTest::SignalingNaN),
1507 convertType(e->getType())));
1508 }
1509
1510 case Builtin::BI__builtin_isinf: {
1511 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1512 mlir::Value v = emitScalarExpr(e->getArg(0));
1514 mlir::Location loc = getLoc(e->getBeginLoc());
1515 return RValue::get(builder.createBoolToInt(
1516 builder.createIsFPClass(loc, v, cir::FPClassTest::Infinity),
1517 convertType(e->getType())));
1518 }
1519 case Builtin::BIfinite:
1520 case Builtin::BI__finite:
1521 case Builtin::BIfinitef:
1522 case Builtin::BI__finitef:
1523 case Builtin::BIfinitel:
1524 case Builtin::BI__finitel:
1525 case Builtin::BI__builtin_isfinite: {
1526 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1527 mlir::Value v = emitScalarExpr(e->getArg(0));
1529 mlir::Location loc = getLoc(e->getBeginLoc());
1530 return RValue::get(builder.createBoolToInt(
1531 builder.createIsFPClass(loc, v, cir::FPClassTest::Finite),
1532 convertType(e->getType())));
1533 }
1534
1535 case Builtin::BI__builtin_isnormal: {
1536 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1537 mlir::Value v = emitScalarExpr(e->getArg(0));
1538 mlir::Location loc = getLoc(e->getBeginLoc());
1539 return RValue::get(builder.createBoolToInt(
1540 builder.createIsFPClass(loc, v, cir::FPClassTest::Normal),
1541 convertType(e->getType())));
1542 }
1543
1544 case Builtin::BI__builtin_issubnormal: {
1545 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1546 mlir::Value v = emitScalarExpr(e->getArg(0));
1547 mlir::Location loc = getLoc(e->getBeginLoc());
1548 return RValue::get(builder.createBoolToInt(
1549 builder.createIsFPClass(loc, v, cir::FPClassTest::Subnormal),
1550 convertType(e->getType())));
1551 }
1552
1553 case Builtin::BI__builtin_iszero: {
1554 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1555 mlir::Value v = emitScalarExpr(e->getArg(0));
1556 mlir::Location loc = getLoc(e->getBeginLoc());
1557 return RValue::get(builder.createBoolToInt(
1558 builder.createIsFPClass(loc, v, cir::FPClassTest::Zero),
1559 convertType(e->getType())));
1560 }
1561 case Builtin::BI__builtin_isfpclass: {
1562 Expr::EvalResult result;
1563 if (!e->getArg(1)->EvaluateAsInt(result, cgm.getASTContext()))
1564 break;
1565
1566 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1567 mlir::Value v = emitScalarExpr(e->getArg(0));
1568 uint64_t test = result.Val.getInt().getLimitedValue();
1569 mlir::Location loc = getLoc(e->getBeginLoc());
1570 //
1571 return RValue::get(builder.createBoolToInt(
1572 builder.createIsFPClass(loc, v, cir::FPClassTest(test)),
1573 convertType(e->getType())));
1574 }
1575 case Builtin::BI__builtin_nondeterministic_value:
1576 return errorBuiltinNYI(*this, e, builtinID);
1577 case Builtin::BI__builtin_elementwise_abs: {
1578 mlir::Type cirTy = convertType(e->getArg(0)->getType());
1579 bool isIntTy = cir::isIntOrVectorOfIntType(cirTy);
1580 if (!isIntTy)
1581 return emitUnaryFPBuiltin<cir::FAbsOp>(*this, *e);
1582 mlir::Value arg = emitScalarExpr(e->getArg(0));
1583 mlir::Value result = cir::AbsOp::create(builder, getLoc(e->getExprLoc()),
1584 arg.getType(), arg, false);
1585 return RValue::get(result);
1586 }
1587 case Builtin::BI__builtin_elementwise_acos:
1589 case Builtin::BI__builtin_elementwise_asin:
1591 case Builtin::BI__builtin_elementwise_atan:
1593 case Builtin::BI__builtin_elementwise_atan2:
1594 return RValue::get(
1596 case Builtin::BI__builtin_elementwise_exp:
1598 case Builtin::BI__builtin_elementwise_exp2:
1600 case Builtin::BI__builtin_elementwise_log:
1602 case Builtin::BI__builtin_elementwise_log2:
1604 case Builtin::BI__builtin_elementwise_log10:
1606 case Builtin::BI__builtin_elementwise_cos:
1608 case Builtin::BI__builtin_elementwise_floor:
1610 case Builtin::BI__builtin_elementwise_round:
1612 case Builtin::BI__builtin_elementwise_rint:
1614 case Builtin::BI__builtin_elementwise_nearbyint:
1616 case Builtin::BI__builtin_elementwise_sin:
1618 case Builtin::BI__builtin_elementwise_sqrt:
1620 case Builtin::BI__builtin_elementwise_tan:
1622 case Builtin::BI__builtin_elementwise_trunc:
1624 case Builtin::BI__builtin_elementwise_fmod:
1625 return RValue::get(
1627 case Builtin::BI__builtin_elementwise_ceil:
1628 case Builtin::BI__builtin_elementwise_exp10:
1629 case Builtin::BI__builtin_elementwise_ldexp:
1630 case Builtin::BI__builtin_elementwise_pow:
1631 case Builtin::BI__builtin_elementwise_bitreverse:
1632 case Builtin::BI__builtin_elementwise_cosh:
1633 case Builtin::BI__builtin_elementwise_popcount:
1634 case Builtin::BI__builtin_elementwise_roundeven:
1635 case Builtin::BI__builtin_elementwise_sinh:
1636 case Builtin::BI__builtin_elementwise_tanh:
1637 case Builtin::BI__builtin_elementwise_canonicalize:
1638 case Builtin::BI__builtin_elementwise_copysign:
1639 case Builtin::BI__builtin_elementwise_fma:
1640 return errorBuiltinNYI(*this, e, builtinID);
1641 case Builtin::BI__builtin_elementwise_fshl: {
1642 mlir::Location loc = getLoc(e->getExprLoc());
1643 mlir::Value a = emitScalarExpr(e->getArg(0));
1644 mlir::Value b = emitScalarExpr(e->getArg(1));
1645 mlir::Value c = emitScalarExpr(e->getArg(2));
1646 return RValue::get(builder.emitIntrinsicCallOp(loc, "fshl", a.getType(),
1647 mlir::ValueRange{a, b, c}));
1648 }
1649 case Builtin::BI__builtin_elementwise_fshr: {
1650 mlir::Location loc = getLoc(e->getExprLoc());
1651 mlir::Value a = emitScalarExpr(e->getArg(0));
1652 mlir::Value b = emitScalarExpr(e->getArg(1));
1653 mlir::Value c = emitScalarExpr(e->getArg(2));
1654 return RValue::get(builder.emitIntrinsicCallOp(loc, "fshr", a.getType(),
1655 mlir::ValueRange{a, b, c}));
1656 }
1657 case Builtin::BI__builtin_elementwise_add_sat:
1658 case Builtin::BI__builtin_elementwise_sub_sat:
1659 case Builtin::BI__builtin_elementwise_max:
1660 case Builtin::BI__builtin_elementwise_min:
1661 case Builtin::BI__builtin_elementwise_maxnum:
1662 case Builtin::BI__builtin_elementwise_minnum:
1663 case Builtin::BI__builtin_elementwise_maximum:
1664 case Builtin::BI__builtin_elementwise_minimum:
1665 case Builtin::BI__builtin_elementwise_maximumnum:
1666 case Builtin::BI__builtin_elementwise_minimumnum:
1667 case Builtin::BI__builtin_reduce_max:
1668 case Builtin::BI__builtin_reduce_min:
1669 case Builtin::BI__builtin_reduce_add:
1670 case Builtin::BI__builtin_reduce_mul:
1671 case Builtin::BI__builtin_reduce_xor:
1672 case Builtin::BI__builtin_reduce_or:
1673 case Builtin::BI__builtin_reduce_and:
1674 case Builtin::BI__builtin_reduce_assoc_fadd:
1675 case Builtin::BI__builtin_reduce_in_order_fadd:
1676 case Builtin::BI__builtin_reduce_maximum:
1677 case Builtin::BI__builtin_reduce_minimum:
1678 case Builtin::BI__builtin_matrix_transpose:
1679 case Builtin::BI__builtin_matrix_column_major_load:
1680 case Builtin::BI__builtin_matrix_column_major_store:
1681 case Builtin::BI__builtin_masked_load:
1682 case Builtin::BI__builtin_masked_expand_load:
1683 case Builtin::BI__builtin_masked_gather:
1684 case Builtin::BI__builtin_masked_store:
1685 case Builtin::BI__builtin_masked_compress_store:
1686 case Builtin::BI__builtin_masked_scatter:
1687 return errorBuiltinNYI(*this, e, builtinID);
1688 case Builtin::BI__builtin_isinf_sign: {
1689 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(*this, e);
1690 mlir::Location loc = getLoc(e->getBeginLoc());
1691 mlir::Value arg = emitScalarExpr(e->getArg(0));
1692 mlir::Value isInf =
1693 builder.createIsFPClass(loc, arg, cir::FPClassTest::Infinity);
1694 mlir::Value isNeg = emitSignBit(loc, *this, arg);
1695 mlir::Type intTy = convertType(e->getType());
1696 cir::ConstantOp zero = builder.getNullValue(intTy, loc);
1697 cir::ConstantOp one = builder.getConstant(loc, cir::IntAttr::get(intTy, 1));
1698 cir::ConstantOp negativeOne =
1699 builder.getConstant(loc, cir::IntAttr::get(intTy, -1));
1700 mlir::Value signResult = builder.createSelect(loc, isNeg, negativeOne, one);
1701 mlir::Value result = builder.createSelect(loc, isInf, signResult, zero);
1702 return RValue::get(result);
1703 }
1704 case Builtin::BI__builtin_flt_rounds: {
1705 mlir::Location loc = getLoc(e->getExprLoc());
1706 mlir::Type resultType = convertType(e->getType());
1707 mlir::Value result =
1708 builder.emitIntrinsicCallOp(loc, "get.rounding", resultType);
1709 if (result.getType() != resultType)
1710 result =
1711 builder.createCast(loc, cir::CastKind::integral, result, resultType);
1712 return RValue::get(result);
1713 }
1714 case Builtin::BI__builtin_set_flt_rounds: {
1715 mlir::Location loc = getLoc(e->getExprLoc());
1716 mlir::Value v = emitScalarExpr(e->getArg(0));
1717 builder.emitIntrinsicCallOp(loc, "set.rounding", builder.getVoidTy(),
1718 mlir::ValueRange{v});
1719 return RValue::get(nullptr);
1720 }
1721 case Builtin::BI__builtin_fpclassify: {
1722 CIRGenFunction::CIRGenFPOptionsRAII fPOptsRAII(*this, e);
1723 mlir::Location loc = getLoc(e->getBeginLoc());
1724 mlir::Value value = emitScalarExpr(e->getArg(5));
1725 mlir::Type resultTy = convertType(e->getType());
1726 // if isZero then
1727 // result = FP_ZERO
1728 // elseif isNan then
1729 // result = FP_NAN
1730 // elseif isInfinity then
1731 // result = FP_INFINITE
1732 // elseif isNormal then
1733 // result = FP_NORMAL
1734 // else
1735 // result = FP_SUBNORMAL
1736 auto isZero =
1737 cir::IsFPClassOp::create(builder, loc, value, cir::FPClassTest::Zero);
1738 mlir::Value result =
1739 cir::TernaryOp::create(
1740 builder, loc, isZero,
1741 /*thenBuilder=*/
1742 [&](mlir::OpBuilder &opBuilder, mlir::Location location) {
1743 mlir::Value zeroLiteral = emitScalarExpr(e->getArg(4));
1744 cir::YieldOp::create(opBuilder, location, zeroLiteral);
1745 },
1746 /*elseBuilder=*/
1747 [&](mlir::OpBuilder &opBuilder, mlir::Location location) {
1748 auto isNan = cir::IsFPClassOp::create(opBuilder, location, value,
1749 cir::FPClassTest::Nan);
1750 mlir::Value nanResult =
1751 cir::TernaryOp::create(
1752 opBuilder, location, isNan,
1753 /*thenBuilder=*/
1754 [&](mlir::OpBuilder &opBuilder, mlir::Location location) {
1755 mlir::Value nanLiteral = emitScalarExpr(e->getArg(0));
1756 cir::YieldOp::create(opBuilder, location, nanLiteral);
1757 },
1758 /*elseBuilder=*/
1759 [&](mlir::OpBuilder &opBuilder, mlir::Location location) {
1760 auto isInfinity = cir::IsFPClassOp::create(
1761 opBuilder, location, value,
1762 cir::FPClassTest::Infinity);
1763 mlir::Value infResult =
1764 cir::TernaryOp::create(
1765 opBuilder, location, isInfinity,
1766 /*thenBuilder=*/
1767 [&](mlir::OpBuilder &opBuilder,
1768 mlir::Location location) {
1769 mlir::Value infinityLiteral =
1770 emitScalarExpr(e->getArg(1));
1771 cir::YieldOp::create(opBuilder, location,
1772 infinityLiteral);
1773 },
1774 /*elseBuilder=*/
1775 [&](mlir::OpBuilder &opBuilder,
1776 mlir::Location location) {
1777 auto isNormal = cir::IsFPClassOp::create(
1778 opBuilder, location, value,
1779 cir::FPClassTest::Normal);
1780 mlir::Value fpNormal =
1781 emitScalarExpr(e->getArg(2));
1782 mlir::Value fpSubnormal =
1783 emitScalarExpr(e->getArg(3));
1784 mlir::Value returnValue =
1785 cir::SelectOp::create(
1786 opBuilder, location, resultTy,
1787 isNormal, fpNormal, fpSubnormal);
1788 cir::YieldOp::create(opBuilder, location,
1789 returnValue);
1790 })
1791 .getResult();
1792 cir::YieldOp::create(opBuilder, location, infResult);
1793 })
1794 .getResult();
1795 cir::YieldOp::create(opBuilder, location, nanResult);
1796 })
1797 .getResult();
1798 return RValue::get(result);
1799 }
1800 case Builtin::BIalloca:
1801 case Builtin::BI_alloca:
1802 case Builtin::BI__builtin_alloca_uninitialized:
1803 case Builtin::BI__builtin_alloca:
1804 return emitBuiltinAlloca(*this, e, builtinID);
1805 case Builtin::BI__builtin_alloca_with_align_uninitialized:
1806 case Builtin::BI__builtin_alloca_with_align:
1807 case Builtin::BI__builtin_infer_alloc_token:
1808 return errorBuiltinNYI(*this, e, builtinID);
1809 case Builtin::BIbzero:
1810 case Builtin::BI__builtin_bzero: {
1811 mlir::Location loc = getLoc(e->getSourceRange());
1812 Address destPtr = emitPointerWithAlignment(e->getArg(0));
1813 Address destPtrCast = destPtr.withElementType(builder, cgm.voidTy);
1814 mlir::Value size = emitScalarExpr(e->getArg(1));
1815 mlir::Value zero = builder.getNullValue(builder.getUInt8Ty(), loc);
1817 builder.createMemSet(loc, destPtrCast, zero, size);
1819 return RValue::getIgnored();
1820 }
1821 case Builtin::BIbcopy:
1822 case Builtin::BI__builtin_bcopy: {
1825 mlir::Value sizeVal = emitScalarExpr(e->getArg(2));
1827 e->getArg(0)->getExprLoc(), fd, 0);
1829 e->getArg(1)->getExprLoc(), fd, 0);
1830 builder.createMemMove(getLoc(e->getSourceRange()), dest.getPointer(),
1831 src.getPointer(), sizeVal);
1832 return RValue::get(nullptr);
1833 }
1834 case Builtin::BI__builtin_char_memchr:
1835 case Builtin::BI__builtin_memchr: {
1836 Address srcPtr = emitPointerWithAlignment(e->getArg(0));
1837 mlir::Value src =
1838 builder.createBitcast(srcPtr.getPointer(), builder.getVoidPtrTy());
1839 mlir::Value pattern = emitScalarExpr(e->getArg(1));
1840 mlir::Value len = emitScalarExpr(e->getArg(2));
1841 mlir::Value res = cir::MemChrOp::create(builder, getLoc(e->getExprLoc()),
1842 src, pattern, len);
1843 return RValue::get(res);
1844 }
1845 case Builtin::BImemcpy:
1846 case Builtin::BI__builtin_memcpy:
1847 case Builtin::BImempcpy:
1848 case Builtin::BI__builtin_mempcpy:
1849 case Builtin::BI__builtin_memcpy_inline:
1850 case Builtin::BI__builtin___memcpy_chk:
1851 case Builtin::BI__builtin_objc_memmove_collectable:
1852 case Builtin::BI__builtin___memmove_chk:
1853 case Builtin::BI__builtin_trivially_relocate:
1854 case Builtin::BImemmove:
1855 case Builtin::BI__builtin_memmove:
1856 case Builtin::BImemset:
1857 case Builtin::BI__builtin_memset:
1858 case Builtin::BI__builtin_memset_inline:
1859 case Builtin::BI__builtin___memset_chk:
1860 case Builtin::BI__builtin_wmemchr:
1861 case Builtin::BI__builtin_wmemcmp:
1862 break; // Handled as library calls below.
1863 case Builtin::BI__builtin_dwarf_cfa:
1864 return errorBuiltinNYI(*this, e, builtinID);
1865 case Builtin::BI__builtin_return_address: {
1866 llvm::APSInt level = e->getArg(0)->EvaluateKnownConstInt(getContext());
1867 return RValue::get(cir::ReturnAddrOp::create(
1868 builder, getLoc(e->getExprLoc()),
1869 builder.getConstAPInt(loc, builder.getUInt32Ty(), level)));
1870 }
1871 case Builtin::BI_ReturnAddress: {
1872 return RValue::get(cir::ReturnAddrOp::create(
1873 builder, getLoc(e->getExprLoc()),
1874 builder.getConstInt(loc, builder.getUInt32Ty(), 0)));
1875 }
1876 case Builtin::BI__builtin_frame_address: {
1877 llvm::APSInt level = e->getArg(0)->EvaluateKnownConstInt(getContext());
1878 mlir::Location loc = getLoc(e->getExprLoc());
1879 mlir::Value addr = cir::FrameAddrOp::create(
1880 builder, loc, allocaInt8PtrTy,
1881 builder.getConstAPInt(loc, builder.getUInt32Ty(), level));
1882 return RValue::get(
1883 builder.createCast(loc, cir::CastKind::bitcast, addr, voidPtrTy));
1884 }
1885 case Builtin::BI__builtin_extract_return_addr:
1886 case Builtin::BI__builtin_frob_return_addr:
1887 case Builtin::BI__builtin_dwarf_sp_column:
1888 case Builtin::BI__builtin_init_dwarf_reg_size_table:
1889 case Builtin::BI__builtin_eh_return:
1890 case Builtin::BI__builtin_unwind_init:
1891 case Builtin::BI__builtin_extend_pointer:
1892 return errorBuiltinNYI(*this, e, builtinID);
1893 case Builtin::BI__builtin_setjmp: {
1895 mlir::Location loc = getLoc(e->getExprLoc());
1896
1897 cir::PointerType voidPtrTy = builder.getVoidPtrTy();
1898 cir::PointerType ppTy = builder.getPointerTo(voidPtrTy);
1899 Address castBuf = buf.withElementType(builder, voidPtrTy);
1900
1902 if (getTarget().getTriple().isSystemZ()) {
1903 cgm.errorNYI(e->getExprLoc(), "setjmp on SystemZ");
1904 return {};
1905 }
1906
1907 mlir::Value frameAddress =
1908 cir::FrameAddrOp::create(builder, loc, voidPtrTy,
1909 mlir::ValueRange{builder.getUInt32(0, loc)})
1910 .getResult();
1911
1912 builder.createStore(loc, frameAddress, castBuf);
1913
1914 mlir::Value stacksave =
1915 cir::StackSaveOp::create(builder, loc, voidPtrTy).getResult();
1916 cir::PtrStrideOp stackSaveSlot = cir::PtrStrideOp::create(
1917 builder, loc, ppTy, castBuf.getPointer(), builder.getSInt32(2, loc));
1918 llvm::TypeSize voidPtrTySize =
1919 cgm.getDataLayout().getTypeAllocSize(voidPtrTy);
1920 CharUnits slotAlign = castBuf.getAlignment().alignmentAtOffset(
1921 CharUnits().fromQuantity(2 * voidPtrTySize));
1922 Address slotAddr = Address(stackSaveSlot, voidPtrTy, slotAlign);
1923 builder.createStore(loc, stacksave, slotAddr);
1924 auto op = cir::EhSetjmpOp::create(builder, loc, castBuf.getPointer());
1925 return RValue::get(op);
1926 }
1927 case Builtin::BI__builtin_longjmp: {
1928 mlir::Value buf = emitScalarExpr(e->getArg(0));
1929 mlir::Location loc = getLoc(e->getExprLoc());
1930
1931 cir::EhLongjmpOp::create(builder, loc, buf);
1932 cir::UnreachableOp::create(builder, loc);
1933 return RValue::get(nullptr);
1934 }
1935 case Builtin::BI__builtin_launder: {
1936 const Expr *arg = e->getArg(0);
1937 QualType argTy = arg->getType()->getPointeeType();
1938 mlir::Value ptr = emitScalarExpr(arg);
1939
1940 if (cgm.getCodeGenOpts().StrictVTablePointers &&
1941 argTy.requiresBuiltinLaunder(cgm.getASTContext())) {
1942 mlir::Location loc = getLoc(e->getExprLoc());
1943 ptr = cir::LaunderOp::create(builder, loc, ptr).getResult();
1944 }
1945 return RValue::get(ptr);
1946 }
1947 case Builtin::BI__sync_fetch_and_add:
1948 case Builtin::BI__sync_fetch_and_sub:
1949 case Builtin::BI__sync_fetch_and_or:
1950 case Builtin::BI__sync_fetch_and_and:
1951 case Builtin::BI__sync_fetch_and_xor:
1952 case Builtin::BI__sync_fetch_and_nand:
1953 case Builtin::BI__sync_add_and_fetch:
1954 case Builtin::BI__sync_sub_and_fetch:
1955 case Builtin::BI__sync_and_and_fetch:
1956 case Builtin::BI__sync_or_and_fetch:
1957 case Builtin::BI__sync_xor_and_fetch:
1958 case Builtin::BI__sync_nand_and_fetch:
1959 case Builtin::BI__sync_val_compare_and_swap:
1960 case Builtin::BI__sync_bool_compare_and_swap:
1961 case Builtin::BI__sync_lock_test_and_set:
1962 case Builtin::BI__sync_lock_release:
1963 case Builtin::BI__sync_swap:
1964 return errorBuiltinNYI(*this, e, builtinID);
1965 case Builtin::BI__sync_fetch_and_add_1:
1966 case Builtin::BI__sync_fetch_and_add_2:
1967 case Builtin::BI__sync_fetch_and_add_4:
1968 case Builtin::BI__sync_fetch_and_add_8:
1969 case Builtin::BI__sync_fetch_and_add_16:
1970 return emitBinaryAtomic(*this, cir::AtomicFetchKind::Add, e);
1971 case Builtin::BI__sync_fetch_and_sub_1:
1972 case Builtin::BI__sync_fetch_and_sub_2:
1973 case Builtin::BI__sync_fetch_and_sub_4:
1974 case Builtin::BI__sync_fetch_and_sub_8:
1975 case Builtin::BI__sync_fetch_and_sub_16:
1976 return emitBinaryAtomic(*this, cir::AtomicFetchKind::Sub, e);
1977 case Builtin::BI__sync_fetch_and_or_1:
1978 case Builtin::BI__sync_fetch_and_or_2:
1979 case Builtin::BI__sync_fetch_and_or_4:
1980 case Builtin::BI__sync_fetch_and_or_8:
1981 case Builtin::BI__sync_fetch_and_or_16:
1982 return emitBinaryAtomic(*this, cir::AtomicFetchKind::Or, e);
1983 case Builtin::BI__sync_fetch_and_and_1:
1984 case Builtin::BI__sync_fetch_and_and_2:
1985 case Builtin::BI__sync_fetch_and_and_4:
1986 case Builtin::BI__sync_fetch_and_and_8:
1987 case Builtin::BI__sync_fetch_and_and_16:
1988 return emitBinaryAtomic(*this, cir::AtomicFetchKind::And, e);
1989 case Builtin::BI__sync_fetch_and_xor_1:
1990 case Builtin::BI__sync_fetch_and_xor_2:
1991 case Builtin::BI__sync_fetch_and_xor_4:
1992 case Builtin::BI__sync_fetch_and_xor_8:
1993 case Builtin::BI__sync_fetch_and_xor_16:
1994 return emitBinaryAtomic(*this, cir::AtomicFetchKind::Xor, e);
1995 case Builtin::BI__sync_fetch_and_nand_1:
1996 case Builtin::BI__sync_fetch_and_nand_2:
1997 case Builtin::BI__sync_fetch_and_nand_4:
1998 case Builtin::BI__sync_fetch_and_nand_8:
1999 case Builtin::BI__sync_fetch_and_nand_16:
2000 return emitBinaryAtomic(*this, cir::AtomicFetchKind::Nand, e);
2001 case Builtin::BI__sync_fetch_and_min:
2002 case Builtin::BI__sync_fetch_and_max:
2003 case Builtin::BI__sync_fetch_and_umin:
2004 case Builtin::BI__sync_fetch_and_umax:
2005 return errorBuiltinNYI(*this, e, builtinID);
2006 return getUndefRValue(e->getType());
2007 case Builtin::BI__sync_add_and_fetch_1:
2008 case Builtin::BI__sync_add_and_fetch_2:
2009 case Builtin::BI__sync_add_and_fetch_4:
2010 case Builtin::BI__sync_add_and_fetch_8:
2011 case Builtin::BI__sync_add_and_fetch_16:
2012 return emitBinaryAtomicPost<cir::AddOp>(*this, cir::AtomicFetchKind::Add,
2013 e);
2014 case Builtin::BI__sync_sub_and_fetch_1:
2015 case Builtin::BI__sync_sub_and_fetch_2:
2016 case Builtin::BI__sync_sub_and_fetch_4:
2017 case Builtin::BI__sync_sub_and_fetch_8:
2018 case Builtin::BI__sync_sub_and_fetch_16:
2019 return emitBinaryAtomicPost<cir::SubOp>(*this, cir::AtomicFetchKind::Sub,
2020 e);
2021 case Builtin::BI__sync_and_and_fetch_1:
2022 case Builtin::BI__sync_and_and_fetch_2:
2023 case Builtin::BI__sync_and_and_fetch_4:
2024 case Builtin::BI__sync_and_and_fetch_8:
2025 case Builtin::BI__sync_and_and_fetch_16:
2026 return emitBinaryAtomicPost<cir::AndOp>(*this, cir::AtomicFetchKind::And,
2027 e);
2028 case Builtin::BI__sync_or_and_fetch_1:
2029 case Builtin::BI__sync_or_and_fetch_2:
2030 case Builtin::BI__sync_or_and_fetch_4:
2031 case Builtin::BI__sync_or_and_fetch_8:
2032 case Builtin::BI__sync_or_and_fetch_16:
2033 return emitBinaryAtomicPost<cir::OrOp>(*this, cir::AtomicFetchKind::Or, e);
2034 case Builtin::BI__sync_xor_and_fetch_1:
2035 case Builtin::BI__sync_xor_and_fetch_2:
2036 case Builtin::BI__sync_xor_and_fetch_4:
2037 case Builtin::BI__sync_xor_and_fetch_8:
2038 case Builtin::BI__sync_xor_and_fetch_16:
2039 return emitBinaryAtomicPost<cir::XorOp>(*this, cir::AtomicFetchKind::Xor,
2040 e);
2041 case Builtin::BI__sync_nand_and_fetch_1:
2042 case Builtin::BI__sync_nand_and_fetch_2:
2043 case Builtin::BI__sync_nand_and_fetch_4:
2044 case Builtin::BI__sync_nand_and_fetch_8:
2045 case Builtin::BI__sync_nand_and_fetch_16:
2046 return emitBinaryAtomicPost<cir::AndOp>(*this, cir::AtomicFetchKind::Nand,
2047 e, /*invert=*/true);
2048 case Builtin::BI__sync_val_compare_and_swap_1:
2049 case Builtin::BI__sync_val_compare_and_swap_2:
2050 case Builtin::BI__sync_val_compare_and_swap_4:
2051 case Builtin::BI__sync_val_compare_and_swap_8:
2052 case Builtin::BI__sync_val_compare_and_swap_16:
2053 case Builtin::BI__sync_bool_compare_and_swap_1:
2054 case Builtin::BI__sync_bool_compare_and_swap_2:
2055 case Builtin::BI__sync_bool_compare_and_swap_4:
2056 case Builtin::BI__sync_bool_compare_and_swap_8:
2057 case Builtin::BI__sync_bool_compare_and_swap_16:
2058 case Builtin::BI__sync_swap_1:
2059 case Builtin::BI__sync_swap_2:
2060 case Builtin::BI__sync_swap_4:
2061 case Builtin::BI__sync_swap_8:
2062 case Builtin::BI__sync_swap_16:
2063 case Builtin::BI__sync_lock_test_and_set_1:
2064 case Builtin::BI__sync_lock_test_and_set_2:
2065 case Builtin::BI__sync_lock_test_and_set_4:
2066 case Builtin::BI__sync_lock_test_and_set_8:
2067 case Builtin::BI__sync_lock_test_and_set_16:
2068 case Builtin::BI__sync_lock_release_1:
2069 case Builtin::BI__sync_lock_release_2:
2070 case Builtin::BI__sync_lock_release_4:
2071 case Builtin::BI__sync_lock_release_8:
2072 case Builtin::BI__sync_lock_release_16:
2073 case Builtin::BI__sync_synchronize:
2074 case Builtin::BI__builtin_nontemporal_load:
2075 case Builtin::BI__builtin_nontemporal_store:
2076 case Builtin::BI__c11_atomic_is_lock_free:
2077 case Builtin::BI__atomic_is_lock_free:
2078 case Builtin::BI__atomic_test_and_set:
2079 case Builtin::BI__atomic_clear:
2080 return errorBuiltinNYI(*this, e, builtinID);
2081 case Builtin::BI__atomic_thread_fence:
2082 case Builtin::BI__c11_atomic_thread_fence: {
2083 emitAtomicFenceOp(*this, e, cir::SyncScopeKind::System);
2084 return RValue::get(nullptr);
2085 }
2086 case Builtin::BI__atomic_signal_fence:
2087 case Builtin::BI__c11_atomic_signal_fence: {
2088 emitAtomicFenceOp(*this, e, cir::SyncScopeKind::SingleThread);
2089 return RValue::get(nullptr);
2090 }
2091 case Builtin::BI__scoped_atomic_thread_fence:
2092 return errorBuiltinNYI(*this, e, builtinID);
2093 case Builtin::BI__builtin_signbit:
2094 case Builtin::BI__builtin_signbitf:
2095 case Builtin::BI__builtin_signbitl: {
2096 CIRGenFunction::CIRGenFPOptionsRAII fPOptsRAII(*this, e);
2097 mlir::Location loc = getLoc(e->getBeginLoc());
2098 mlir::Value value = emitScalarExpr(e->getArg(0));
2099 mlir::Operation *signBitOp = cir::SignBitOp::create(builder, loc, value);
2100 mlir::Value result = builder.createBoolToInt(signBitOp->getResult(0),
2101 convertType(e->getType()));
2102 return RValue::get(result);
2103 }
2104 case Builtin::BI__warn_memset_zero_len:
2105 case Builtin::BI__annotation:
2106 case Builtin::BI__builtin_annotation:
2107 case Builtin::BI__builtin_addcb:
2108 case Builtin::BI__builtin_addcs:
2109 case Builtin::BI__builtin_addc:
2110 case Builtin::BI__builtin_addcl:
2111 case Builtin::BI__builtin_addcll:
2112 case Builtin::BI__builtin_subcb:
2113 case Builtin::BI__builtin_subcs:
2114 case Builtin::BI__builtin_subc:
2115 case Builtin::BI__builtin_subcl:
2116 case Builtin::BI__builtin_subcll:
2117 return errorBuiltinNYI(*this, e, builtinID);
2118
2119 case Builtin::BI__builtin_add_overflow:
2120 case Builtin::BI__builtin_sub_overflow:
2121 case Builtin::BI__builtin_mul_overflow: {
2122 const clang::Expr *leftArg = e->getArg(0);
2123 const clang::Expr *rightArg = e->getArg(1);
2124 const clang::Expr *resultArg = e->getArg(2);
2125
2126 clang::QualType resultQTy =
2127 resultArg->getType()->castAs<clang::PointerType>()->getPointeeType();
2128
2129 WidthAndSignedness leftInfo =
2130 getIntegerWidthAndSignedness(cgm.getASTContext(), leftArg->getType());
2131 WidthAndSignedness rightInfo =
2132 getIntegerWidthAndSignedness(cgm.getASTContext(), rightArg->getType());
2133 WidthAndSignedness resultInfo =
2134 getIntegerWidthAndSignedness(cgm.getASTContext(), resultQTy);
2135
2136 // Note we compute the encompassing type with the consideration to the
2137 // result type, so later in LLVM lowering we don't get redundant integral
2138 // extension casts.
2139 WidthAndSignedness encompassingInfo =
2140 EncompassingIntegerType({leftInfo, rightInfo, resultInfo});
2141
2142 auto encompassingCIRTy = cir::IntType::get(
2143 &getMLIRContext(), encompassingInfo.width, encompassingInfo.isSigned);
2144 auto resultCIRTy = mlir::cast<cir::IntType>(cgm.convertType(resultQTy));
2145
2146 mlir::Value x = emitScalarExpr(leftArg);
2147 mlir::Value y = emitScalarExpr(rightArg);
2148 Address resultPtr = emitPointerWithAlignment(resultArg);
2149
2150 // Extend each operand to the encompassing type, if necessary.
2151 if (x.getType() != encompassingCIRTy)
2152 x = builder.createCast(cir::CastKind::integral, x, encompassingCIRTy);
2153 if (y.getType() != encompassingCIRTy)
2154 y = builder.createCast(cir::CastKind::integral, y, encompassingCIRTy);
2155
2156 // Perform the operation on the extended values.
2157 mlir::Location loc = getLoc(e->getSourceRange());
2158 mlir::Value result, overflow;
2159 switch (builtinID) {
2160 default:
2161 llvm_unreachable("Unknown overflow builtin id.");
2162 case Builtin::BI__builtin_add_overflow:
2163 std::tie(result, overflow) =
2164 emitOverflowOp<cir::AddOverflowOp>(builder, loc, resultCIRTy, x, y);
2165 break;
2166 case Builtin::BI__builtin_sub_overflow:
2167 std::tie(result, overflow) =
2168 emitOverflowOp<cir::SubOverflowOp>(builder, loc, resultCIRTy, x, y);
2169 break;
2170 case Builtin::BI__builtin_mul_overflow:
2171 std::tie(result, overflow) =
2172 emitOverflowOp<cir::MulOverflowOp>(builder, loc, resultCIRTy, x, y);
2173 break;
2174 }
2175
2176 // Here is a slight difference from the original clang CodeGen:
2177 // - In the original clang CodeGen, the checked arithmetic result is
2178 // first computed as a value of the encompassing type, and then it is
2179 // truncated to the actual result type with a second overflow checking.
2180 // - In CIRGen, the checked arithmetic operation directly produce the
2181 // checked arithmetic result in its expected type.
2182 //
2183 // So we don't need a truncation and a second overflow checking here.
2184
2185 // Finally, store the result using the pointer.
2186 bool isVolatile =
2187 resultArg->getType()->getPointeeType().isVolatileQualified();
2188 builder.createStore(loc, result, resultPtr, isVolatile);
2189
2190 return RValue::get(overflow);
2191 }
2192
2193 case Builtin::BI__builtin_uadd_overflow:
2194 case Builtin::BI__builtin_uaddl_overflow:
2195 case Builtin::BI__builtin_uaddll_overflow:
2196 case Builtin::BI__builtin_usub_overflow:
2197 case Builtin::BI__builtin_usubl_overflow:
2198 case Builtin::BI__builtin_usubll_overflow:
2199 case Builtin::BI__builtin_umul_overflow:
2200 case Builtin::BI__builtin_umull_overflow:
2201 case Builtin::BI__builtin_umulll_overflow:
2202 case Builtin::BI__builtin_sadd_overflow:
2203 case Builtin::BI__builtin_saddl_overflow:
2204 case Builtin::BI__builtin_saddll_overflow:
2205 case Builtin::BI__builtin_ssub_overflow:
2206 case Builtin::BI__builtin_ssubl_overflow:
2207 case Builtin::BI__builtin_ssubll_overflow:
2208 case Builtin::BI__builtin_smul_overflow:
2209 case Builtin::BI__builtin_smull_overflow:
2210 case Builtin::BI__builtin_smulll_overflow: {
2211 // Scalarize our inputs.
2212 mlir::Value x = emitScalarExpr(e->getArg(0));
2213 mlir::Value y = emitScalarExpr(e->getArg(1));
2214
2215 const clang::Expr *resultArg = e->getArg(2);
2216 Address resultPtr = emitPointerWithAlignment(resultArg);
2217
2218 clang::QualType resultQTy =
2219 resultArg->getType()->castAs<clang::PointerType>()->getPointeeType();
2220 auto resultCIRTy = mlir::cast<cir::IntType>(cgm.convertType(resultQTy));
2221
2222 // Create the appropriate overflow-checked arithmetic operation.
2223 mlir::Location loc = getLoc(e->getSourceRange());
2224 mlir::Value result, overflow;
2225 switch (builtinID) {
2226 default:
2227 llvm_unreachable("Unknown overflow builtin id.");
2228 case Builtin::BI__builtin_uadd_overflow:
2229 case Builtin::BI__builtin_uaddl_overflow:
2230 case Builtin::BI__builtin_uaddll_overflow:
2231 case Builtin::BI__builtin_sadd_overflow:
2232 case Builtin::BI__builtin_saddl_overflow:
2233 case Builtin::BI__builtin_saddll_overflow:
2234 std::tie(result, overflow) =
2235 emitOverflowOp<cir::AddOverflowOp>(builder, loc, resultCIRTy, x, y);
2236 break;
2237 case Builtin::BI__builtin_usub_overflow:
2238 case Builtin::BI__builtin_usubl_overflow:
2239 case Builtin::BI__builtin_usubll_overflow:
2240 case Builtin::BI__builtin_ssub_overflow:
2241 case Builtin::BI__builtin_ssubl_overflow:
2242 case Builtin::BI__builtin_ssubll_overflow:
2243 std::tie(result, overflow) =
2244 emitOverflowOp<cir::SubOverflowOp>(builder, loc, resultCIRTy, x, y);
2245 break;
2246 case Builtin::BI__builtin_umul_overflow:
2247 case Builtin::BI__builtin_umull_overflow:
2248 case Builtin::BI__builtin_umulll_overflow:
2249 case Builtin::BI__builtin_smul_overflow:
2250 case Builtin::BI__builtin_smull_overflow:
2251 case Builtin::BI__builtin_smulll_overflow:
2252 std::tie(result, overflow) =
2253 emitOverflowOp<cir::MulOverflowOp>(builder, loc, resultCIRTy, x, y);
2254 break;
2255 }
2256
2257 bool isVolatile =
2258 resultArg->getType()->getPointeeType().isVolatileQualified();
2259 builder.createStore(loc, emitToMemory(result, resultQTy), resultPtr,
2260 isVolatile);
2261
2262 return RValue::get(overflow);
2263 }
2264
2265 case Builtin::BIaddressof:
2266 case Builtin::BI__addressof:
2267 case Builtin::BI__builtin_addressof:
2268 return RValue::get(emitLValue(e->getArg(0)).getPointer());
2269 case Builtin::BI__builtin_function_start:
2270 return errorBuiltinNYI(*this, e, builtinID);
2271 case Builtin::BI__builtin_operator_new:
2273 e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_New);
2274 case Builtin::BI__builtin_operator_delete:
2276 e->getCallee()->getType()->castAs<FunctionProtoType>(), e, OO_Delete);
2277 return RValue::get(nullptr);
2278 case Builtin::BI__builtin_is_aligned:
2279 case Builtin::BI__builtin_align_up:
2280 case Builtin::BI__builtin_align_down:
2281 case Builtin::BI__noop:
2282 case Builtin::BI__builtin_call_with_static_chain:
2283 case Builtin::BI_InterlockedExchange8:
2284 case Builtin::BI_InterlockedExchange16:
2285 case Builtin::BI_InterlockedExchange:
2286 case Builtin::BI_InterlockedExchangePointer:
2287 case Builtin::BI_InterlockedCompareExchangePointer:
2288 case Builtin::BI_InterlockedCompareExchangePointer_nf:
2289 case Builtin::BI_InterlockedCompareExchange8:
2290 case Builtin::BI_InterlockedCompareExchange16:
2291 case Builtin::BI_InterlockedCompareExchange:
2292 case Builtin::BI_InterlockedCompareExchange64:
2293 case Builtin::BI_InterlockedIncrement16:
2294 case Builtin::BI_InterlockedIncrement:
2295 case Builtin::BI_InterlockedDecrement16:
2296 case Builtin::BI_InterlockedDecrement:
2297 case Builtin::BI_InterlockedAnd8:
2298 case Builtin::BI_InterlockedAnd16:
2299 case Builtin::BI_InterlockedAnd:
2300 case Builtin::BI_InterlockedExchangeAdd8:
2301 case Builtin::BI_InterlockedExchangeAdd16:
2302 case Builtin::BI_InterlockedExchangeAdd:
2303 case Builtin::BI_InterlockedExchangeSub8:
2304 case Builtin::BI_InterlockedExchangeSub16:
2305 case Builtin::BI_InterlockedExchangeSub:
2306 case Builtin::BI_InterlockedOr8:
2307 case Builtin::BI_InterlockedOr16:
2308 case Builtin::BI_InterlockedOr:
2309 case Builtin::BI_InterlockedXor8:
2310 case Builtin::BI_InterlockedXor16:
2311 case Builtin::BI_InterlockedXor:
2312 case Builtin::BI_bittest64:
2313 case Builtin::BI_bittest:
2314 case Builtin::BI_bittestandcomplement64:
2315 case Builtin::BI_bittestandcomplement:
2316 case Builtin::BI_bittestandreset64:
2317 case Builtin::BI_bittestandreset:
2318 case Builtin::BI_bittestandset64:
2319 case Builtin::BI_bittestandset:
2320 case Builtin::BI_interlockedbittestandreset:
2321 case Builtin::BI_interlockedbittestandreset64:
2322 case Builtin::BI_interlockedbittestandreset64_acq:
2323 case Builtin::BI_interlockedbittestandreset64_rel:
2324 case Builtin::BI_interlockedbittestandreset64_nf:
2325 case Builtin::BI_interlockedbittestandset64:
2326 case Builtin::BI_interlockedbittestandset64_acq:
2327 case Builtin::BI_interlockedbittestandset64_rel:
2328 case Builtin::BI_interlockedbittestandset64_nf:
2329 case Builtin::BI_interlockedbittestandset:
2330 case Builtin::BI_interlockedbittestandset_acq:
2331 case Builtin::BI_interlockedbittestandset_rel:
2332 case Builtin::BI_interlockedbittestandset_nf:
2333 case Builtin::BI_interlockedbittestandreset_acq:
2334 case Builtin::BI_interlockedbittestandreset_rel:
2335 case Builtin::BI_interlockedbittestandreset_nf:
2336 case Builtin::BI__iso_volatile_load8:
2337 case Builtin::BI__iso_volatile_load16:
2338 case Builtin::BI__iso_volatile_load32:
2339 case Builtin::BI__iso_volatile_load64:
2340 case Builtin::BI__iso_volatile_store8:
2341 case Builtin::BI__iso_volatile_store16:
2342 case Builtin::BI__iso_volatile_store32:
2343 case Builtin::BI__iso_volatile_store64:
2344 case Builtin::BI__builtin_ptrauth_sign_constant:
2345 case Builtin::BI__builtin_ptrauth_auth:
2346 case Builtin::BI__builtin_ptrauth_auth_and_resign:
2347 case Builtin::BI__builtin_ptrauth_blend_discriminator:
2348 case Builtin::BI__builtin_ptrauth_sign_generic_data:
2349 case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
2350 case Builtin::BI__builtin_ptrauth_strip:
2351 case Builtin::BI__builtin_get_vtable_pointer:
2352 case Builtin::BI__exception_code:
2353 case Builtin::BI_exception_code:
2354 case Builtin::BI__exception_info:
2355 case Builtin::BI_exception_info:
2356 case Builtin::BI__abnormal_termination:
2357 case Builtin::BI_abnormal_termination:
2358 return errorBuiltinNYI(*this, e, builtinID);
2359 case Builtin::BI_setjmpex:
2360 case Builtin::BI_setjmp:
2361 if (getTarget().getTriple().isOSMSVCRT()) {
2362 cgm.errorNYI(e->getSourceRange(), "setjmp/setjmpex on MSVCRT");
2363 return getUndefRValue(e->getType());
2364 }
2365 // Else break and this will be handled as a library call.
2366 break;
2367 case Builtin::BImove:
2368 case Builtin::BImove_if_noexcept:
2369 case Builtin::BIforward:
2370 case Builtin::BIforward_like:
2371 case Builtin::BIas_const:
2372 return RValue::get(emitLValue(e->getArg(0)).getPointer());
2373 case Builtin::BI__GetExceptionInfo:
2374 case Builtin::BI__fastfail:
2375 case Builtin::BIread_pipe:
2376 case Builtin::BIwrite_pipe:
2377 case Builtin::BIreserve_read_pipe:
2378 case Builtin::BIreserve_write_pipe:
2379 case Builtin::BIwork_group_reserve_read_pipe:
2380 case Builtin::BIwork_group_reserve_write_pipe:
2381 case Builtin::BIsub_group_reserve_read_pipe:
2382 case Builtin::BIsub_group_reserve_write_pipe:
2383 case Builtin::BIcommit_read_pipe:
2384 case Builtin::BIcommit_write_pipe:
2385 case Builtin::BIwork_group_commit_read_pipe:
2386 case Builtin::BIwork_group_commit_write_pipe:
2387 case Builtin::BIsub_group_commit_read_pipe:
2388 case Builtin::BIsub_group_commit_write_pipe:
2389 case Builtin::BIget_pipe_num_packets:
2390 case Builtin::BIget_pipe_max_packets:
2391 case Builtin::BIto_global:
2392 case Builtin::BIto_local:
2393 case Builtin::BIto_private:
2394 case Builtin::BIenqueue_kernel:
2395 case Builtin::BIget_kernel_work_group_size:
2396 case Builtin::BIget_kernel_preferred_work_group_size_multiple:
2397 case Builtin::BIget_kernel_max_sub_group_size_for_ndrange:
2398 case Builtin::BIget_kernel_sub_group_count_for_ndrange:
2399 case Builtin::BI__builtin_store_half:
2400 case Builtin::BI__builtin_store_halff:
2401 case Builtin::BI__builtin_load_half:
2402 case Builtin::BI__builtin_load_halff:
2403 return errorBuiltinNYI(*this, e, builtinID);
2404 case Builtin::BI__builtin_printf:
2405 case Builtin::BIprintf:
2406 if (getTarget().getTriple().isNVPTX() ||
2407 getTarget().getTriple().isAMDGCN() ||
2408 (getTarget().getTriple().isSPIRV() &&
2409 getTarget().getTriple().getVendor() == llvm::Triple::AMD)) {
2410 if (getTarget().getTriple().isNVPTX())
2412 if ((getTarget().getTriple().isAMDGCN() ||
2413 getTarget().getTriple().isSPIRV()) &&
2414 getLangOpts().HIP)
2415 return errorBuiltinNYI(*this, e, builtinID);
2416 }
2417 break;
2418 case Builtin::BI__builtin_canonicalize:
2419 case Builtin::BI__builtin_canonicalizef:
2420 case Builtin::BI__builtin_canonicalizef16:
2421 case Builtin::BI__builtin_canonicalizel:
2422 case Builtin::BI__builtin_thread_pointer:
2423 case Builtin::BI__builtin_os_log_format:
2424 case Builtin::BI__xray_customevent:
2425 case Builtin::BI__xray_typedevent:
2426 case Builtin::BI__builtin_ms_va_start:
2427 case Builtin::BI__builtin_ms_va_end:
2428 case Builtin::BI__builtin_ms_va_copy:
2429 case Builtin::BI__builtin_get_device_side_mangled_name:
2430 return errorBuiltinNYI(*this, e, builtinID);
2431 }
2432
2433 // If this is an alias for a lib function (e.g. __builtin_sin), emit
2434 // the call using the normal call path, but using the unmangled
2435 // version of the function name.
2436 if (!shouldEmitBuiltinAsIR(builtinID, getContext().BuiltinInfo, *this) &&
2437 getContext().BuiltinInfo.isLibFunction(builtinID))
2438 return emitLibraryCall(*this, fd, e,
2439 cgm.getBuiltinLibFunction(fd, builtinID));
2440
2441 // If this is a predefined lib function (e.g. malloc), emit the call
2442 // using exactly the normal call path.
2443 if (getContext().BuiltinInfo.isPredefinedLibFunction(builtinID))
2444 return emitLibraryCall(*this, fd, e,
2445 emitScalarExpr(e->getCallee()).getDefiningOp());
2446
2447 // See if we have a target specific intrinsic.
2448 std::string name = getContext().BuiltinInfo.getName(builtinID);
2449 Intrinsic::ID intrinsicID = Intrinsic::not_intrinsic;
2450 StringRef prefix =
2451 llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch());
2452 if (!prefix.empty()) {
2453 intrinsicID = Intrinsic::getIntrinsicForClangBuiltin(prefix, name);
2454 // NOTE we don't need to perform a compatibility flag check here since the
2455 // intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
2456 // MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
2457 if (intrinsicID == Intrinsic::not_intrinsic)
2458 intrinsicID = Intrinsic::getIntrinsicForMSBuiltin(prefix, name);
2459 }
2460
2461 if (intrinsicID != Intrinsic::not_intrinsic) {
2462 unsigned iceArguments = 0;
2464 getContext().GetBuiltinType(builtinID, error, &iceArguments);
2465 assert(error == ASTContext::GE_None && "Should not codegen an error");
2466
2467 StringRef name = Intrinsic::getName(intrinsicID);
2468 // cir::LLVMIntrinsicCallOp expects intrinsic name to not have prefix
2469 // "llvm." For example, `llvm.nvvm.barrier0` should be passed as
2470 // `nvvm.barrier0`.
2471 assert(name.starts_with("llvm.") && "expected llvm. prefix");
2472 name = name.drop_front(/*strlen("llvm.")=*/5);
2473
2474 cir::FuncType intrinsicType =
2475 getIntrinsicType(*this, &getMLIRContext(), intrinsicID);
2476
2478 const FunctionDecl *fd = e->getDirectCallee();
2479 for (unsigned i = 0; i < e->getNumArgs(); i++) {
2480 mlir::Value argValue =
2481 emitScalarOrConstFoldImmArg(iceArguments, i, e->getArg(i));
2482 // If the intrinsic arg type is different from the builtin arg type
2483 // we need to do a bit cast.
2484 mlir::Type argType = argValue.getType();
2485 mlir::Type expectedTy = intrinsicType.getInput(i);
2486
2487 // Correct integer signedness based on AST parameter type
2488 mlir::Type correctedExpectedTy = expectedTy;
2489 if (fd && i < fd->getNumParams()) {
2490 correctedExpectedTy = correctIntegerSignedness(
2491 expectedTy, fd->getParamDecl(i)->getType(), &getMLIRContext());
2492 }
2493
2494 if (mlir::isa<cir::PointerType>(expectedTy)) {
2495 bool argIsPointer = mlir::isa<cir::PointerType>(argType);
2496 bool argIsVectorOfPointer = false;
2497 if (auto vecTy = dyn_cast<mlir::VectorType>(argType))
2498 argIsVectorOfPointer =
2499 mlir::isa<cir::PointerType>(vecTy.getElementType());
2500
2501 if (!argIsPointer && !argIsVectorOfPointer) {
2502 cgm.errorNYI(
2503 e->getSourceRange(),
2504 "intrinsic expects a pointer type (NYI for non-pointer)");
2505 return getUndefRValue(e->getType());
2506 }
2507
2508 // Pointer handling (address-space cast / bitcast fallback).
2509 if (argType != expectedTy)
2510 argValue = getCorrectedPtr(argValue, expectedTy, builder);
2511 } else {
2512 // Non-pointer expected type: if needed, bitcast to the corrected
2513 // expected type to match signedness/representation.
2514 if (argType != correctedExpectedTy)
2515 argValue = builder.createBitcast(argValue, correctedExpectedTy);
2516 }
2517
2518 args.push_back(argValue);
2519 }
2520
2521 // Correct return type signedness based on AST return type before creating
2522 // the call, avoiding unnecessary casts in the IR.
2523 mlir::Type correctedReturnType = intrinsicType.getReturnType();
2524 if (fd) {
2525 correctedReturnType =
2526 correctIntegerSignedness(intrinsicType.getReturnType(),
2527 fd->getReturnType(), &getMLIRContext());
2528 }
2529
2530 cir::LLVMIntrinsicCallOp intrinsicCall = cir::LLVMIntrinsicCallOp::create(
2531 builder, getLoc(e->getExprLoc()), builder.getStringAttr(name),
2532 correctedReturnType, args);
2533
2534 mlir::Value intrinsicRes = intrinsicCall.getResult();
2535
2536 if (isa<cir::VoidType>(correctedReturnType))
2537 return RValue::get(nullptr);
2538
2539 return RValue::get(intrinsicRes);
2540 }
2541
2542 // Some target-specific builtins can have aggregate return values, e.g.
2543 // __builtin_arm_mve_vld2q_u32. So if the result is an aggregate, force
2544 // returnValue to be non-null, so that the target-specific emission code can
2545 // always just emit into it.
2547 if (evalKind == cir::TEK_Aggregate && returnValue.isNull()) {
2548 cgm.errorNYI(e->getSourceRange(), "aggregate return value from builtin");
2549 return getUndefRValue(e->getType());
2550 }
2551
2552 // Now see if we can emit a target-specific builtin.
2553 // FIXME: This is a temporary mechanism (double-optional semantics) that will
2554 // go away once everything is implemented:
2555 // 1. return `mlir::Value{}` for cases where we have issued the diagnostic.
2556 // 2. return `std::nullopt` in cases where we didn't issue a diagnostic
2557 // but also didn't handle the builtin.
2558 if (std::optional<mlir::Value> rst =
2559 emitTargetBuiltinExpr(builtinID, e, returnValue)) {
2560 mlir::Value v = rst.value();
2561 // CIR dialect operations may have no results, no values will be returned
2562 // even if it executes successfully.
2563 if (!v)
2564 return RValue::get(nullptr);
2565
2566 switch (evalKind) {
2567 case cir::TEK_Scalar:
2568 if (mlir::isa<cir::VoidType>(v.getType()))
2569 return RValue::get(nullptr);
2570 return RValue::get(v);
2571 case cir::TEK_Aggregate:
2572 cgm.errorNYI(e->getSourceRange(), "aggregate return value from builtin");
2573 return getUndefRValue(e->getType());
2574 case cir::TEK_Complex:
2575 llvm_unreachable("No current target builtin returns complex");
2576 }
2577 llvm_unreachable("Bad evaluation kind in EmitBuiltinExpr");
2578 }
2579
2580 cgm.errorNYI(e->getSourceRange(),
2581 std::string("unimplemented builtin call: ") +
2582 getContext().BuiltinInfo.getName(builtinID));
2583 return getUndefRValue(e->getType());
2584}
2585
2586static std::optional<mlir::Value>
2588 const CallExpr *e, ReturnValueSlot &returnValue,
2589 llvm::Triple::ArchType arch) {
2590 // When compiling in HipStdPar mode we have to be conservative in rejecting
2591 // target specific features in the FE, and defer the possible error to the
2592 // AcceleratorCodeSelection pass, wherein iff an unsupported target builtin is
2593 // referenced by an accelerator executable function, we emit an error.
2594 // Returning nullptr here leads to the builtin being handled in
2595 // EmitStdParUnsupportedBuiltin.
2596 if (cgf->getLangOpts().HIPStdPar && cgf->getLangOpts().CUDAIsDevice &&
2597 arch != cgf->getTarget().getTriple().getArch())
2598 return std::nullopt;
2599
2600 switch (arch) {
2601 case llvm::Triple::arm:
2602 case llvm::Triple::armeb:
2603 case llvm::Triple::thumb:
2604 case llvm::Triple::thumbeb:
2605 // These are actually NYI, but that will be reported by emitBuiltinExpr.
2606 // At this point, we don't even know that the builtin is target-specific.
2607 return std::nullopt;
2608 case llvm::Triple::aarch64:
2609 case llvm::Triple::aarch64_32:
2610 case llvm::Triple::aarch64_be:
2611 return cgf->emitAArch64BuiltinExpr(builtinID, e, returnValue, arch);
2612 case llvm::Triple::bpfeb:
2613 case llvm::Triple::bpfel:
2614 // These are actually NYI, but that will be reported by emitBuiltinExpr.
2615 // At this point, we don't even know that the builtin is target-specific.
2616 return std::nullopt;
2617
2618 case llvm::Triple::x86:
2619 case llvm::Triple::x86_64:
2620 return cgf->emitX86BuiltinExpr(builtinID, e);
2621
2622 case llvm::Triple::ppc:
2623 case llvm::Triple::ppcle:
2624 case llvm::Triple::ppc64:
2625 case llvm::Triple::ppc64le:
2626 case llvm::Triple::r600:
2627 // These are actually NYI, but that will be reported by emitBuiltinExpr.
2628 // At this point, we don't even know that the builtin is target-specific.
2629 return std::nullopt;
2630 case llvm::Triple::amdgcn:
2631 return cgf->emitAMDGPUBuiltinExpr(builtinID, e);
2632 case llvm::Triple::systemz:
2633 return std::nullopt;
2634 case llvm::Triple::nvptx:
2635 case llvm::Triple::nvptx64:
2636 return cgf->emitNVPTXBuiltinExpr(builtinID, e);
2637 case llvm::Triple::wasm32:
2638 case llvm::Triple::wasm64:
2639 case llvm::Triple::hexagon:
2640 // These are actually NYI, but that will be reported by emitBuiltinExpr.
2641 // At this point, we don't even know that the builtin is target-specific.
2642 return std::nullopt;
2643 case llvm::Triple::riscv32:
2644 case llvm::Triple::riscv64:
2645 return cgf->emitRISCVBuiltinExpr(builtinID, e);
2646 default:
2647 return std::nullopt;
2648 }
2649}
2650
2651std::optional<mlir::Value>
2654 if (getContext().BuiltinInfo.isAuxBuiltinID(builtinID)) {
2655 assert(getContext().getAuxTargetInfo() && "Missing aux target info");
2657 this, getContext().BuiltinInfo.getAuxBuiltinID(builtinID), e,
2658 returnValue, getContext().getAuxTargetInfo()->getTriple().getArch());
2659 }
2660
2661 return emitTargetArchBuiltinExpr(this, builtinID, e, returnValue,
2662 getTarget().getTriple().getArch());
2663}
2664
2666 const unsigned iceArguments, const unsigned idx, const Expr *argExpr) {
2667 mlir::Value arg = {};
2668 if ((iceArguments & (1 << idx)) == 0) {
2669 arg = emitScalarExpr(argExpr);
2670 } else {
2671 // If this is required to be a constant, constant fold it so that we
2672 // know that the generated intrinsic gets a ConstantInt.
2673 const std::optional<llvm::APSInt> result =
2675 assert(result && "Expected argument to be a constant");
2676 arg = builder.getConstInt(getLoc(argExpr->getSourceRange()), *result);
2677 }
2678 return arg;
2679}
2680
2681/// Given a builtin id for a function like "__builtin_fabsf", return a Function*
2682/// for "fabsf".
2684 unsigned builtinID) {
2685 assert(astContext.BuiltinInfo.isLibFunction(builtinID));
2686
2687 // Get the name, skip over the __builtin_ prefix (if necessary). We may have
2688 // to build this up so provide a small stack buffer to handle the vast
2689 // majority of names.
2691
2693 name = astContext.BuiltinInfo.getName(builtinID).substr(10);
2694
2695 GlobalDecl d(fd);
2696 mlir::Type type = convertType(fd->getType());
2697 return getOrCreateCIRFunction(name, type, d, /*forVTable=*/false);
2698}
2699
2701 mlir::Value argValue = evaluateExprAsBool(e);
2702 if (!sanOpts.has(SanitizerKind::Builtin))
2703 return argValue;
2704
2706 cgm.errorNYI(e->getSourceRange(),
2707 "emitCheckedArgForAssume: sanitizers are NYI");
2708 return {};
2709}
2710
2711void CIRGenFunction::emitVAStart(mlir::Value vaList) {
2712 // LLVM codegen casts to *i8, no real gain on doing this for CIRGen this
2713 // early, defer to LLVM lowering.
2714 cir::VAStartOp::create(builder, vaList.getLoc(), vaList);
2715}
2716
2717void CIRGenFunction::emitVAEnd(mlir::Value vaList) {
2718 cir::VAEndOp::create(builder, vaList.getLoc(), vaList);
2719}
2720
2721// FIXME(cir): This completely abstracts away the ABI with a generic CIR Op. By
2722// default this lowers to llvm.va_arg which is incomplete and not ABI-compliant
2723// on most targets so cir.va_arg will need some ABI handling in LoweringPrepare
2725 assert(!cir::MissingFeatures::msabi());
2726 assert(!cir::MissingFeatures::vlas());
2727 mlir::Location loc = cgm.getLoc(ve->getExprLoc());
2728 mlir::Type type = convertType(ve->getType());
2729 mlir::Value vaList = emitVAListRef(ve->getSubExpr()).getPointer();
2730 return cir::VAArgOp::create(builder, loc, type, vaList);
2731}
2732
2733mlir::Value CIRGenFunction::emitBuiltinObjectSize(const Expr *e, unsigned type,
2734 cir::IntType resType,
2735 mlir::Value emittedE,
2736 bool isDynamic) {
2737 // If this is a pass_object_size parameter, load the implicit size arg.
2738 //
2739 // BOS type compatibility: a pass_object_size annotation with one type can
2740 // satisfy a __builtin_object_size query with a different type when the
2741 // annotated type is a safe approximation. Type 0 (max, whole object) is
2742 // an overestimate for type 1 (max, closest surrounding subobject), and
2743 // type 3 (min, closest surrounding subobject) is an underestimate for
2744 // type 2 (min, whole object).
2745 enum BOSType {
2746 MaxWholeObject = 0,
2747 MaxSubobject = 1,
2748 MinWholeObject = 2,
2749 MinSubobject = 3,
2750 };
2751 if (auto *dre = dyn_cast<DeclRefExpr>(e->IgnoreParenImpCasts())) {
2752 auto *param = dyn_cast<ParmVarDecl>(dre->getDecl());
2753 auto *objSizeAttr = dre->getDecl()->getAttr<PassObjectSizeAttr>();
2754 if (param && objSizeAttr) {
2755 auto from = objSizeAttr->getType();
2756 bool compatible = from == static_cast<int>(type) ||
2757 (from == MaxWholeObject && type == MaxSubobject) ||
2758 (from == MinSubobject && type == MinWholeObject);
2759 if (compatible) {
2760 const ImplicitParamDecl *sizeDecl = sizeArguments.lookup(param);
2761 assert(sizeDecl && "expected pass_object_size implicit param");
2762
2763 DeclMapTy::iterator declIter = localDeclMap.find(sizeDecl);
2764 assert(declIter != localDeclMap.end());
2765 Address addr = declIter->second;
2766
2767 return emitLoadOfScalar(addr, /*volatile=*/false,
2768 getContext().getSizeType(), e->getBeginLoc(),
2770 }
2771 }
2772 }
2773
2774 // LLVM can't handle type=3 appropriately, and __builtin_object_size shouldn't
2775 // evaluate e for side-effects. In either case, just like original LLVM
2776 // lowering, we shouldn't lower to `cir.objsize` but to a constant instead.
2777 if (type == 3 || (!emittedE && e->HasSideEffects(getContext())))
2778 return builder.getConstInt(getLoc(e->getSourceRange()), resType,
2779 (type & 2) ? 0 : -1);
2780
2781 mlir::Value ptr = emittedE ? emittedE : emitScalarExpr(e);
2782 assert(mlir::isa<cir::PointerType>(ptr.getType()) &&
2783 "Non-pointer passed to __builtin_object_size?");
2784
2786
2787 // Extract the min/max mode from type. CIR only supports type 0
2788 // (max, whole object) and type 2 (min, whole object), not type 1 or 3
2789 // (closest subobject variants).
2790 const bool min = ((type & 2) != 0);
2791 // For GCC compatibility, __builtin_object_size treats NULL as unknown size.
2792 auto op =
2793 cir::ObjSizeOp::create(builder, getLoc(e->getSourceRange()), resType, ptr,
2794 min, /*nullUnknown=*/true, isDynamic);
2795 return op.getResult();
2796}
2797
2799 const Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE,
2800 bool isDynamic) {
2801 if (std::optional<uint64_t> objectSize =
2803 return builder.getConstInt(getLoc(e->getSourceRange()), resType,
2804 *objectSize);
2805 return emitBuiltinObjectSize(e, type, resType, emittedE, isDynamic);
2806}
static StringRef bytes(const std::vector< T, Allocator > &v)
Defines enum values for all the target-independent builtin functions.
static mlir::Value emitSignBit(mlir::Location loc, CIRGenFunction &cgf, mlir::Value val)
static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static mlir::Value createBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, mlir::Value arg, Args... args)
static mlir::Type decodeFixedType(CIRGenFunction &cgf, ArrayRef< llvm::Intrinsic::IITDescriptor > &infos, mlir::MLIRContext *context)
static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static RValue emitBinaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static RValue emitBinaryAtomicPost(CIRGenFunction &cgf, cir::AtomicFetchKind atomicOpkind, const CallExpr *e, bool invert=false)
static std::optional< 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 emitBinaryAtomic(CIRGenFunction &cgf, cir::AtomicFetchKind atomicOpkind, const CallExpr *e)
static mlir::Value emitToInt(CIRGenFunction &cgf, mlir::Value v, QualType t, cir::IntType intType)
Emit the conversions required to turn the given value into an integer of the given size.
static mlir::Value getCorrectedPtr(mlir::Value argValue, mlir::Type expectedTy, CIRGenBuilderTy &builder)
static std::pair< mlir::Value, mlir::Value > emitOverflowOp(CIRGenBuilderTy &builder, mlir::Location loc, cir::IntType resultTy, mlir::Value lhs, mlir::Value rhs)
Create a checked overflow arithmetic op and return its result and overflow flag.
static bool shouldEmitBuiltinAsIR(unsigned builtinID, const Builtin::Context &bi, const CIRGenFunction &cgf)
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 void emitAtomicFenceOp(CIRGenFunction &cgf, const CallExpr *expr, cir::SyncScopeKind syncScope)
static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e, Args... args)
static Address checkAtomicAlignment(CIRGenFunction &cgf, const CallExpr *e)
static bool shouldCIREmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
static RValue emitBuiltinBitOpWithFallback(CIRGenFunction &cgf, const CallExpr *e)
Emit a clz/ctz bit op with optional fallback for __builtin_c[lt]zg.
static cir::FuncType getIntrinsicType(CIRGenFunction &cgf, mlir::MLIRContext *context, llvm::Intrinsic::ID id)
static mlir::Value makeBinaryAtomicValue(CIRGenFunction &cgf, cir::AtomicFetchKind kind, const CallExpr *expr, mlir::Type *originalArgType=nullptr, mlir::Value *emittedArgValue=nullptr, cir::MemOrder ordering=cir::MemOrder::SequentiallyConsistent)
Utility to insert an atomic instruction based on Intrinsic::ID and the expression node.
static struct WidthAndSignedness EncompassingIntegerType(ArrayRef< struct WidthAndSignedness > types)
static RValue emitBuiltinAlloca(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
static mlir::Type correctIntegerSignedness(mlir::Type iitType, QualType astType, mlir::MLIRContext *context)
Helper function to correct integer signedness for intrinsic arguments and return type.
static RValue emitUnaryMaybeConstrainedFPToIntBuiltin(CIRGenFunction &cgf, const CallExpr &e)
static RValue errorBuiltinNYI(CIRGenFunction &cgf, const CallExpr *e, unsigned builtinID)
static mlir::Value emitFromInt(CIRGenFunction &cgf, mlir::Value v, QualType t, mlir::Type resultType)
static StringRef getTriple(const Command &Job)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines an enumeration for C++ overloaded operators.
static QualType getPointeeType(const MemRegion *R)
__DEVICE__ int min(int __a, int __b)
__device__ __2f16 b
__device__ __2f16 float c
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src, mlir::Type newTy)
mlir::Value createAlloca(mlir::Location loc, cir::PointerType addrType, mlir::Type type, llvm::StringRef name, mlir::IntegerAttr alignment, mlir::Value dynAllocSize)
llvm::TypeSize getTypeSizeInBits(mlir::Type ty) const
APSInt & getInt()
Definition APValue.h:508
bool isFloat() const
Definition APValue.h:486
bool isInt() const
Definition APValue.h:485
APFloat & getFloat()
Definition APValue.h:522
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
unsigned getIntWidth(QualType T) const
CanQualType VoidPtrTy
Builtin::Context & BuiltinInfo
Definition ASTContext.h:807
TypeInfo getTypeInfo(const Type *T) const
Get the size and alignment of the specified complete type in bits.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs=nullptr) const
Return the type for the specified builtin.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:924
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
@ GE_None
No error.
uint64_t getCharWidth() const
Return the size of the character type, in bits.
Holds information about both target-independent and target-specific builtins, allowing easy queries b...
Definition Builtins.h:236
bool shouldGenerateFPMathIntrinsic(unsigned BuiltinID, llvm::Triple Trip, std::optional< bool > ErrnoOverwritten, bool MathErrnoEnabled, bool HasOptNoneAttr, bool IsOptimizationEnabled) const
Determine whether we can generate LLVM intrinsics for the given builtin ID, based on whether it has s...
Definition Builtins.cpp:228
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:310
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:96
mlir::Type getElementType() const
Definition Address.h:123
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
Definition Address.h:136
Address withAlignment(clang::CharUnits newAlignment) const
Return address with different alignment, but same pointer and element type.
Definition Address.h:87
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:110
cir::IntType getSIntNTy(int n)
cir::PointerType getUInt8PtrTy()
cir::IntType getUIntNTy(int n)
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:92
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
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
const clang::Decl * curFuncDecl
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
mlir::Value emitNVPTXDevicePrintfCallExpr(const CallExpr *expr)
Emit a device-side printf call for NVPTX targets.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
cir::CallOp emitCoroFreeBuiltin(const CallExpr *e)
mlir::Value evaluateOrEmitBuiltinObjectSize(const clang::Expr *e, unsigned type, cir::IntType resType, mlir::Value emittedE, bool isDynamic)
std::optional< mlir::Value > emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *expr)
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....
std::optional< mlir::Value > emitTargetBuiltinExpr(unsigned builtinID, const clang::CallExpr *e, ReturnValueSlot &returnValue)
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.
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
RValue getUndefRValue(clang::QualType ty)
Get an appropriate 'undef' rvalue for the given type.
Address returnValue
The temporary alloca to hold the return value.
std::optional< mlir::Value > emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr)
RValue emitCall(const CIRGenFunctionInfo &funcInfo, const CIRGenCallee &callee, ReturnValueSlot returnValue, const CallArgList &args, cir::CIRCallOpInterface *callOp, mlir::Location loc)
std::optional< mlir::Value > emitAMDGPUBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an AMDGPU builtin function.
std::optional< mlir::Value > emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, ReturnValueSlot returnValue, llvm::Triple::ArchType arch)
void emitAtomicExprWithMemOrder(const Expr *memOrder, bool isStore, bool isLoad, bool isFence, llvm::function_ref< void(cir::MemOrder)> emitAtomicOp)
llvm::SmallDenseMap< const ParmVarDecl *, const ImplicitParamDecl * > sizeArguments
If a ParmVarDecl had the pass_object_size attribute, this will contain a mapping from said ParmVarDec...
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()
void emitVAStart(mlir::Value vaList)
Emits the start of a CIR variable-argument operation (cir.va_start)
void emitNonNullArgCheck(RValue rv, QualType argType, SourceLocation argLoc, AbstractCallee ac, unsigned paramNum)
Create a check for a function parameter that may potentially be declared as non-null.
mlir::MLIRContext & getMLIRContext()
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
DeclMapTy localDeclMap
This keeps track of the CIR allocas or globals for local C declarations.
std::optional< mlir::Value > emitNVPTXBuiltinExpr(unsigned builtinID, const CallExpr *expr)
Emit a call to an NVPTX builtin function.
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)
mlir::Value emitFromMemory(mlir::Value value, clang::QualType ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
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.
clang::ASTContext & getASTContext() const
mlir::Type convertType(clang::QualType type)
clang::DiagnosticsEngine & getDiags() const
cir::FuncOp getBuiltinLibFunction(const FunctionDecl *fd, unsigned builtinID)
Given a builtin id for a function like "__builtin_fabsf", return a Function* for "fabsf".
const llvm::Triple & getTriple() const
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
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::NamedAttrList extraAttrs={})
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Value getPointer() const
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
bool isIgnored() const
Definition CIRGenValue.h:52
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:260
virtual bool supportsLibCall() const
Returns true if the target supports math library calls.
Definition TargetInfo.h:54
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3150
bool hasStoredFPFeatures() const
Definition Expr.h:3105
SourceLocation getBeginLoc() const
Definition Expr.h:3280
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3129
Expr * getCallee()
Definition Expr.h:3093
FPOptionsOverride getFPFeatures() const
Definition Expr.h:3245
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3137
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
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:585
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:233
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
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.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3097
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:3695
std::optional< uint64_t > tryEvaluateObjectSize(const ASTContext &Ctx, unsigned Type) const
If the current Expr is a pointer, this will try to statically determine the number of bytes available...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:282
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
LangOptions::FPExceptionModeKind getExceptionMode() const
Represents a function declaration or definition.
Definition Decl.h:2018
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2815
QualType getReturnType() const
Definition Decl.h:2863
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5369
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
@ FPE_Ignore
Assume that floating-point exceptions are masked.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3390
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8529
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8571
bool requiresBuiltinLaunder(const ASTContext &Context) const
Returns true if this type requires laundering by checking if it is a dynamic class type,...
Definition Type.cpp:5591
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
Exposes information about the current target.
Definition TargetInfo.h:227
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
virtual bool isCLZForZeroUndef() const
The __builtin_clz* and __builtin_ctz* built-in functions are specified to have undefined results for ...
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:748
bool isBlockPointerType() const
Definition TypeBase.h:8702
bool isPointerType() const
Definition TypeBase.h:8682
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9342
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9170
bool isObjCObjectPointerType() const
Definition TypeBase.h:8861
bool isFloatingType() const
Definition Type.cpp:2389
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition Type.cpp:2332
Represents a call to the builtin function __builtin_va_arg.
Definition Expr.h:4960
const Expr * getSubExpr() const
Definition Expr.h:4976
QualType getType() const
Definition Decl.h:723
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
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 addressSpace()
static bool asmLabelAttr()
static bool msvcBuiltins()
static bool builtinCallF128()
static bool isPPC_FP128Ty()
static bool emitCheckedInBoundsGEP()
static bool fpConstraints()
static bool countedBySize()
static bool fastMathFlags()
static bool builtinBitCountExpr()
static bool builtinCall()
static bool generateDebugInfo()
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
cir::PointerType voidPtrTy
void* in address space 0
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:642
#define conj(__x)
Definition tgmath.h:1303