21#include "mlir/IR/Location.h"
22#include "mlir/IR/Value.h"
44 bool isDivRemOp()
const {
45 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
46 opcode == BO_RemAssign;
50 bool mayHaveIntegerOverflow()
const {
52 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
53 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
65 bool isFixedPointOp()
const {
68 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
69 QualType lhstype = binOp->getLHS()->getType();
70 QualType rhstype = binOp->getRHS()->getType();
73 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
74 return unop->getSubExpr()->getType()->isFixedPointType();
79class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
81 CIRGenBuilderTy &builder;
85 bool ignoreResultAssign;
88 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
89 bool ignoreResultAssign =
false)
90 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
95 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
97 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
101 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
102 return cgf.cgm.emitNullConstant(ty, loc);
105 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
106 return builder.createFloatingCast(result, cgf.convertType(promotionType));
109 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
110 return builder.createFloatingCast(result, cgf.convertType(exprType));
113 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
115 mlir::Value maybePromoteBoolResult(mlir::Value value,
116 mlir::Type dstTy)
const {
117 if (mlir::isa<cir::IntType>(dstTy))
118 return builder.createBoolToInt(value, dstTy);
119 if (mlir::isa<cir::BoolType>(dstTy))
121 llvm_unreachable(
"Can only promote integer or boolean types");
128 mlir::Value Visit(Expr *e) {
129 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
132 mlir::Value VisitStmt(Stmt *
s) {
133 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
136 mlir::Value VisitExpr(Expr *e) {
137 cgf.getCIRGenModule().errorNYI(
142 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
146 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
148 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
153 mlir::Value emitLoadOfLValue(
const Expr *e) {
154 LValue lv = cgf.emitLValue(e);
156 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
159 mlir::Value VisitCoawaitExpr(CoawaitExpr *
s) {
160 return cgf.emitCoawaitExpr(*s).getValue();
163 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
164 return cgf.emitLoadOfLValue(lv, loc).getValue();
168 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
169 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
170 return cgf.emitScalarConstant(constant, e);
172 return emitLoadOfLValue(e);
175 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
177 auto blockInfoAttr = cir::BlockAddrInfoAttr::get(
179 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->
getSourceRange()),
184 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
186 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
190 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
192 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
193 "expect floating-point type");
194 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
198 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
199 mlir::Type ty = cgf.convertType(e->
getType());
200 auto init = cir::IntAttr::get(ty, e->
getValue());
201 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()), init);
204 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
208 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
215 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
219 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
221 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
223 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
227 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
230 mlir::Value VisitCastExpr(
CastExpr *e);
231 mlir::Value VisitCallExpr(
const CallExpr *e);
233 mlir::Value VisitStmtExpr(StmtExpr *e) {
234 CIRGenFunction::StmtExprEvaluation eval(cgf);
242 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
244 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
248 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
249 ignoreResultAssign =
false;
255 const mlir::Value vecValue = Visit(e->
getBase());
256 const mlir::Value indexValue = Visit(e->
getIdx());
257 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
260 return emitLoadOfLValue(e);
263 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
266 mlir::Value inputVec = Visit(e->
getExpr(0));
267 mlir::Value indexVec = Visit(e->
getExpr(1));
268 return cir::VecShuffleDynamicOp::create(
269 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
272 mlir::Value vec1 = Visit(e->
getExpr(0));
273 mlir::Value vec2 = Visit(e->
getExpr(1));
278 SmallVector<mlir::Attribute, 8> indices;
281 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
287 return cir::VecShuffleOp::create(cgf.builder,
289 cgf.convertType(e->
getType()), vec1, vec2,
290 cgf.builder.getArrayAttr(indices));
293 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
296 return emitScalarConversion(Visit(e->
getSrcExpr()),
301 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
303 mlir::Value VisitMemberExpr(MemberExpr *e);
305 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
306 return emitLoadOfLValue(e);
309 mlir::Value VisitInitListExpr(InitListExpr *e);
311 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
312 return VisitCastExpr(e);
315 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
316 return cgf.cgm.emitNullConstant(e->
getType(),
321 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
324 return cgf.getBuilder().createPtrToBoolCast(v);
327 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
328 cir::BoolType boolTy = builder.getBoolTy();
329 return cir::CastOp::create(builder, loc, boolTy,
330 cir::CastKind::float_to_bool, src);
333 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
339 cir::BoolType boolTy = builder.getBoolTy();
340 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
346 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
347 mlir::Location loc) {
348 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
351 return emitFloatToBoolConversion(src, loc);
353 if (llvm::isa<MemberPointerType>(srcType)) {
354 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
355 return builder.getFalse(loc);
359 return emitIntToBoolConversion(src, loc);
361 assert(::mlir::isa<cir::PointerType>(src.getType()));
362 return emitPointerToBoolConversion(src, srcType);
367 struct ScalarConversionOpts {
368 bool treatBooleanAsSigned;
369 bool emitImplicitIntegerTruncationChecks;
370 bool emitImplicitIntegerSignChangeChecks;
372 ScalarConversionOpts()
373 : treatBooleanAsSigned(
false),
374 emitImplicitIntegerTruncationChecks(
false),
375 emitImplicitIntegerSignChangeChecks(
false) {}
377 ScalarConversionOpts(clang::SanitizerSet sanOpts)
378 : treatBooleanAsSigned(
false),
379 emitImplicitIntegerTruncationChecks(
380 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
381 emitImplicitIntegerSignChangeChecks(
382 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
389 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
390 QualType dstType, mlir::Type srcTy,
391 mlir::Type dstTy, ScalarConversionOpts opts) {
393 "Internal error: matrix types not handled by this function.");
394 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
395 mlir::isa<mlir::IntegerType>(dstTy)) &&
396 "Obsolete code. Don't use mlir::IntegerType with CIR.");
398 mlir::Type fullDstTy = dstTy;
399 if (mlir::isa<cir::VectorType>(srcTy) &&
400 mlir::isa<cir::VectorType>(dstTy)) {
402 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
403 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
406 std::optional<cir::CastKind> castKind;
408 if (mlir::isa<cir::BoolType>(srcTy)) {
409 if (opts.treatBooleanAsSigned)
410 cgf.getCIRGenModule().errorNYI(
"signed bool");
411 if (cgf.getBuilder().isInt(dstTy))
412 castKind = cir::CastKind::bool_to_int;
413 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
414 castKind = cir::CastKind::bool_to_float;
416 llvm_unreachable(
"Internal error: Cast to unexpected type");
417 }
else if (cgf.getBuilder().isInt(srcTy)) {
418 if (cgf.getBuilder().isInt(dstTy))
419 castKind = cir::CastKind::integral;
420 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
421 castKind = cir::CastKind::int_to_float;
423 llvm_unreachable(
"Internal error: Cast to unexpected type");
424 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
425 if (cgf.getBuilder().isInt(dstTy)) {
429 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
430 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
432 castKind = cir::CastKind::float_to_int;
433 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
435 return builder.createFloatingCast(src, fullDstTy);
437 llvm_unreachable(
"Internal error: Cast to unexpected type");
440 llvm_unreachable(
"Internal error: Cast from unexpected type");
443 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
444 return cir::CastOp::create(builder, src.getLoc(), fullDstTy, *castKind,
449 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
453 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
458 "variably modified types in varargs");
461 return cgf.emitVAArg(ve);
464 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
468 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
470 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
473 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
475 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
477 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
479 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
481 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
483 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
485 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
487 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
489 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
490 cir::UnaryOpKind kind,
bool isPre) {
491 if (cgf.getLangOpts().OpenMP)
499 if (
type->getAs<AtomicType>()) {
503 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
506 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
519 if (kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
520 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
521 }
else if (
type->isIntegerType()) {
522 QualType promotedType;
523 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
524 if (cgf.getContext().isPromotableIntegerType(
type)) {
525 promotedType = cgf.getContext().getPromotedIntegerType(
type);
526 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
527 canPerformLossyDemotionCheck =
true;
528 canPerformLossyDemotionCheck &=
529 cgf.getContext().getCanonicalType(
type) !=
530 cgf.getContext().getCanonicalType(promotedType);
531 canPerformLossyDemotionCheck &=
538 (!canPerformLossyDemotionCheck ||
539 type->isSignedIntegerOrEnumerationType() ||
541 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
542 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
543 "The following check expects that if we do promotion to different "
544 "underlying canonical type, at least one of the types (either "
545 "base or promoted) will be signed, or the bitwidths will match.");
550 value = emitIncDecConsiderOverflowBehavior(e, value, kind);
552 cir::UnaryOpKind
kind =
553 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
555 value = emitUnaryOp(e, kind, input,
false);
557 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
558 QualType
type = ptr->getPointeeType();
559 if (cgf.getContext().getAsVariableArrayType(
type)) {
561 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
563 }
else if (
type->isFunctionType()) {
566 "Pointer arithmetic on function pointer");
571 CIRGenBuilderTy &builder = cgf.getBuilder();
572 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
573 mlir::Value amt = builder.getSInt32(amount, loc);
575 value = builder.createPtrStride(loc, value, amt);
577 }
else if (
type->isVectorType()) {
580 }
else if (
type->isRealFloatingType()) {
583 if (
type->isHalfType() &&
584 !cgf.getContext().getLangOpts().NativeHalfType) {
589 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
592 assert(kind == cir::UnaryOpKind::Inc ||
593 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
594 value = emitUnaryOp(e, kind, value);
596 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
599 }
else if (
type->isFixedPointType()) {
600 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
603 assert(
type->castAs<ObjCObjectPointerType>());
604 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
608 CIRGenFunction::SourceLocRAIIObject sourceloc{
613 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
615 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
619 return isPre ? value : input;
622 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
624 cir::UnaryOpKind kind) {
625 assert(kind == cir::UnaryOpKind::Inc ||
626 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
627 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
628 case LangOptions::SOB_Defined:
629 return emitUnaryOp(e, kind, inVal,
false);
630 case LangOptions::SOB_Undefined:
632 return emitUnaryOp(e, kind, inVal,
true);
633 case LangOptions::SOB_Trapping:
635 return emitUnaryOp(e, kind, inVal,
true);
636 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
639 llvm_unreachable(
"Unexpected signed overflow behavior kind");
642 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
643 if (llvm::isa<MemberPointerType>(e->
getType())) {
644 cgf.cgm.errorNYI(e->
getSourceRange(),
"Address of member pointer");
645 return builder.getNullPtr(cgf.convertType(e->
getType()),
649 return cgf.emitLValue(e->
getSubExpr()).getPointer();
652 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
655 return emitLoadOfLValue(e);
658 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
661 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
662 if (result && !promotionType.
isNull())
663 return emitUnPromotedValue(result, e->
getType());
667 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
670 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
671 if (result && !promotionType.
isNull())
672 return emitUnPromotedValue(result, e->
getType());
676 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
677 cir::UnaryOpKind kind,
678 QualType promotionType) {
679 ignoreResultAssign =
false;
681 if (!promotionType.
isNull())
682 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
691 return emitUnaryOp(e, kind, operand, nsw);
694 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind kind,
695 mlir::Value input,
bool nsw =
false) {
696 return cir::UnaryOp::create(builder,
698 input.getType(), kind, input, nsw);
701 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
702 ignoreResultAssign =
false;
704 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
707 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
709 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
710 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
711 mlir::Value VisitRealImag(
const UnaryOperator *e,
712 QualType promotionType = QualType());
714 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
718 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
719 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
722 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
723 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
727 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
729 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
730 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
731 return cgf.emitCXXNewExpr(e);
733 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
734 cgf.emitCXXDeleteExpr(e);
738 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
739 cgf.emitCXXThrowExpr(e);
748 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
750 ScalarConversionOpts opts = ScalarConversionOpts()) {
760 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
766 if (srcType == dstType) {
767 if (opts.emitImplicitIntegerSignChangeChecks)
768 cgf.getCIRGenModule().errorNYI(loc,
769 "implicit integer sign change checks");
776 mlir::Type mlirSrcType = src.getType();
781 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
783 mlir::Type mlirDstType = cgf.convertType(dstType);
786 !cgf.getContext().getLangOpts().NativeHalfType) {
788 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
789 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
790 cgf.getCIRGenModule().errorNYI(loc,
791 "cast via llvm.convert.from.fp16");
796 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
797 cgf.getCIRGenModule().errorNYI(loc,
798 "cast via llvm.convert.from.fp16");
801 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
803 srcType = cgf.getContext().FloatTy;
804 mlirSrcType = cgf.floatTy;
810 if (mlirSrcType == mlirDstType) {
811 if (opts.emitImplicitIntegerSignChangeChecks)
812 cgf.getCIRGenModule().errorNYI(loc,
813 "implicit integer sign change checks");
820 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
821 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
822 return builder.getNullPtr(dstPT, src.getLoc());
828 return builder.createPtrToInt(src, mlirDstType);
835 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
837 "Splatted expr doesn't match with vector element type?");
839 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
844 cgf.getCIRGenModule().errorNYI(loc,
845 "matrix type to matrix type conversion");
849 "Internal error: conversion between matrix type and scalar type");
852 mlir::Value res =
nullptr;
853 mlir::Type resTy = mlirDstType;
855 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
857 if (mlirDstType != resTy) {
858 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
859 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
863 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
867 if (opts.emitImplicitIntegerTruncationChecks)
868 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
870 if (opts.emitImplicitIntegerSignChangeChecks)
871 cgf.getCIRGenModule().errorNYI(loc,
872 "implicit integer sign change checks");
877 BinOpInfo emitBinOps(
const BinaryOperator *e,
878 QualType promotionType = QualType()) {
879 ignoreResultAssign =
false;
881 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
882 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
883 if (!promotionType.
isNull())
884 result.fullType = promotionType;
886 result.fullType = e->
getType();
887 result.compType = result.fullType;
888 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
889 result.compType = vecType->getElementType();
899 mlir::Value emitMul(
const BinOpInfo &ops);
900 mlir::Value emitDiv(
const BinOpInfo &ops);
901 mlir::Value emitRem(
const BinOpInfo &ops);
902 mlir::Value emitAdd(
const BinOpInfo &ops);
903 mlir::Value emitSub(
const BinOpInfo &ops);
904 mlir::Value emitShl(
const BinOpInfo &ops);
905 mlir::Value emitShr(
const BinOpInfo &ops);
906 mlir::Value emitAnd(
const BinOpInfo &ops);
907 mlir::Value emitXor(
const BinOpInfo &ops);
908 mlir::Value emitOr(
const BinOpInfo &ops);
910 LValue emitCompoundAssignLValue(
911 const CompoundAssignOperator *e,
912 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
913 mlir::Value &result);
915 emitCompoundAssign(
const CompoundAssignOperator *e,
916 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
920 QualType getPromotionType(QualType ty) {
921 const clang::ASTContext &ctx = cgf.getContext();
922 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
923 QualType elementTy = complexTy->getElementType();
929 if (
auto *vt = ty->
getAs<VectorType>()) {
930 unsigned numElements = vt->getNumElements();
933 return cgf.getContext().FloatTy;
940#define HANDLEBINOP(OP) \
941 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
942 QualType promotionTy = getPromotionType(e->getType()); \
943 auto result = emit##OP(emitBinOps(e, promotionTy)); \
944 if (result && !promotionTy.isNull()) \
945 result = emitUnPromotedValue(result, e->getType()); \
948 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
949 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
965 ignoreResultAssign =
false;
971 auto clangCmpToCIRCmp =
975 return cir::CmpOpKind::lt;
977 return cir::CmpOpKind::gt;
979 return cir::CmpOpKind::le;
981 return cir::CmpOpKind::ge;
983 return cir::CmpOpKind::eq;
985 return cir::CmpOpKind::ne;
987 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
991 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
999 BinOpInfo boInfo = emitBinOps(e);
1000 mlir::Value lhs = boInfo.lhs;
1001 mlir::Value rhs = boInfo.rhs;
1011 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1013 boInfo.lhs, boInfo.rhs);
1015 }
else if (boInfo.isFixedPointOp()) {
1018 result = builder.
getBool(
false, loc);
1022 mlir::isa<cir::PointerType>(lhs.getType()) &&
1023 mlir::isa<cir::PointerType>(rhs.getType())) {
1024 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1027 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1034 BinOpInfo boInfo = emitBinOps(e);
1035 result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);
1043#define VISITCOMP(CODE) \
1044 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1054 const bool ignore = std::exchange(ignoreResultAssign,
false);
1069 rhs = Visit(e->
getRHS());
1079 if (lhs.isBitField()) {
1099 if (!lhs.isVolatile())
1103 return emitLoadOfLValue(lhs, e->
getExprLoc());
1106 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1107 cgf.emitIgnoredExpr(e->
getLHS());
1109 return Visit(e->
getRHS());
1112 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1114 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1115 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1116 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1117 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1118 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1120 mlir::Value lhs = Visit(e->
getLHS());
1121 mlir::Value rhs = Visit(e->
getRHS());
1123 auto cmpOpKind = cir::CmpOpKind::ne;
1124 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1125 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1126 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1127 return builder.createIntCast(vecOr, vecTy);
1131 mlir::Type resTy = cgf.convertType(e->
getType());
1132 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1134 CIRGenFunction::ConditionalEvaluation eval(cgf);
1136 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1137 auto resOp = cir::TernaryOp::create(
1138 builder, loc, lhsCondV,
1139 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1140 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1141 b.getInsertionBlock()};
1142 cgf.curLexScope->setAsTernary();
1143 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1145 cir::YieldOp::create(
b, loc, res);
1148 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1149 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1150 b.getInsertionBlock()};
1152 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1153 cir::YieldOp::create(
b, loc, res.getRes());
1155 return maybePromoteBoolResult(resOp.getResult(), resTy);
1158 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1160 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1161 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1162 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1163 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1164 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1166 mlir::Value lhs = Visit(e->
getLHS());
1167 mlir::Value rhs = Visit(e->
getRHS());
1169 auto cmpOpKind = cir::CmpOpKind::ne;
1170 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1171 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1172 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1173 return builder.createIntCast(vecOr, vecTy);
1177 mlir::Type resTy = cgf.convertType(e->
getType());
1178 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1180 CIRGenFunction::ConditionalEvaluation eval(cgf);
1182 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1183 auto resOp = cir::TernaryOp::create(
1184 builder, loc, lhsCondV,
1185 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1186 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1187 b.getInsertionBlock()};
1189 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1190 cir::YieldOp::create(
b, loc, res.getRes());
1193 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1194 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1195 b.getInsertionBlock()};
1197 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1199 cir::YieldOp::create(
b, loc, res);
1202 return maybePromoteBoolResult(resOp.getResult(), resTy);
1205 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1206 return cgf.emitAtomicExpr(e).getValue();
1210LValue ScalarExprEmitter::emitCompoundAssignLValue(
1212 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1213 mlir::Value &result) {
1224 if (promotionTypeCR.
isNull())
1228 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1230 if (!promotionTypeRHS.
isNull())
1233 opInfo.rhs = Visit(e->
getRHS());
1235 opInfo.fullType = promotionTypeCR;
1236 opInfo.compType = opInfo.fullType;
1237 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1238 opInfo.compType = vecType->getElementType();
1247 if (lhsTy->
getAs<AtomicType>()) {
1248 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1252 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1254 CIRGenFunction::SourceLocRAIIObject sourceloc{
1257 if (!promotionTypeLHS.
isNull())
1258 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1260 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1264 result = (this->*func)(opInfo);
1268 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1269 ScalarConversionOpts(cgf.
sanOpts));
1275 if (lhsLV.isBitField())
1286mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1290 cir::CastKind castOpKind;
1292 case CK_FloatingComplexToReal:
1293 castOpKind = cir::CastKind::float_complex_to_real;
1295 case CK_IntegralComplexToReal:
1296 castOpKind = cir::CastKind::int_complex_to_real;
1298 case CK_FloatingComplexToBoolean:
1299 castOpKind = cir::CastKind::float_complex_to_bool;
1301 case CK_IntegralComplexToBoolean:
1302 castOpKind = cir::CastKind::int_complex_to_bool;
1305 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1311mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1312 QualType promotionType) {
1314 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1315 switch (bo->getOpcode()) {
1316#define HANDLE_BINOP(OP) \
1318 return emit##OP(emitBinOps(bo, promotionType));
1327 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1328 switch (uo->getOpcode()) {
1331 return VisitRealImag(uo, promotionType);
1333 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1335 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1340 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1342 if (!promotionType.
isNull())
1343 return emitPromotedValue(result, promotionType);
1344 return emitUnPromotedValue(result, e->
getType());
1349mlir::Value ScalarExprEmitter::emitCompoundAssign(
1350 const CompoundAssignOperator *e,
1351 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1353 bool ignore = std::exchange(ignoreResultAssign,
false);
1355 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1366 if (!lhs.isVolatile())
1370 return emitLoadOfLValue(lhs, e->
getExprLoc());
1373mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1375 mlir::OpBuilder &builder = cgf.builder;
1377 auto scope = cir::ScopeOp::create(
1380 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1381 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1382 builder.getInsertionBlock()};
1383 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1384 if (scopeYieldVal) {
1388 cir::YieldOp::create(builder, loc, scopeYieldVal);
1389 yieldTy = scopeYieldVal.getType();
1393 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1403#define COMPOUND_OP(Op) \
1404 case BO_##Op##Assign: \
1405 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1442 llvm_unreachable(
"Not valid compound assignment operators");
1444 llvm_unreachable(
"Unhandled compound assignment operator");
1449 bool ignoreResultAssign) {
1451 "Invalid scalar expression to emit");
1454 .Visit(
const_cast<Expr *
>(e));
1459 if (!promotionType.
isNull())
1474static std::optional<QualType>
1478 return std::nullopt;
1483 return std::nullopt;
1496 const BinOpInfo &op) {
1498 "Expected a unary or binary operator");
1502 if (!op.mayHaveIntegerOverflow())
1506 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1507 return !uo->canOverflow();
1512 std::optional<QualType> optionalLHSTy =
1517 std::optional<QualType> optionalRHSTy =
1527 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1534 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1535 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1540 const BinOpInfo &op,
1541 bool isSubtraction) {
1546 mlir::Value pointer = op.lhs;
1547 Expr *pointerOperand =
expr->getLHS();
1548 mlir::Value
index = op.rhs;
1549 Expr *indexOperand =
expr->getRHS();
1555 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1556 std::swap(pointer,
index);
1557 std::swap(pointerOperand, indexOperand);
1559 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1560 "Need a pointer operand");
1561 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1596 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1607 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1612 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1614 pointer.getType(), pointer,
index);
1617mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1618 const mlir::Location loc = cgf.
getLoc(ops.loc);
1620 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1621 case LangOptions::SOB_Defined:
1622 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1623 return builder.createMul(loc, ops.lhs, ops.rhs);
1625 case LangOptions::SOB_Undefined:
1626 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1627 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1629 case LangOptions::SOB_Trapping:
1631 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1641 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1643 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1645 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1647 return builder.createFMul(loc, ops.lhs, ops.rhs);
1650 if (ops.isFixedPointOp()) {
1656 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1657 cgf.
convertType(ops.fullType), cir::BinOpKind::Mul,
1660mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1661 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1662 cgf.
convertType(ops.fullType), cir::BinOpKind::Div,
1665mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1666 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1667 cgf.
convertType(ops.fullType), cir::BinOpKind::Rem,
1671mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1672 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1673 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1676 const mlir::Location loc = cgf.
getLoc(ops.loc);
1678 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1679 case LangOptions::SOB_Defined:
1680 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1681 return builder.createAdd(loc, ops.lhs, ops.rhs);
1683 case LangOptions::SOB_Undefined:
1684 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1685 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1687 case LangOptions::SOB_Trapping:
1689 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1700 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1702 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1704 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1706 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1709 if (ops.isFixedPointOp()) {
1715 return cir::BinOp::create(builder, loc, cgf.
convertType(ops.fullType),
1716 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1719mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1720 const mlir::Location loc = cgf.
getLoc(ops.loc);
1722 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1724 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1725 case LangOptions::SOB_Defined: {
1726 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1727 return builder.createSub(loc, ops.lhs, ops.rhs);
1730 case LangOptions::SOB_Undefined:
1731 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1732 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1734 case LangOptions::SOB_Trapping:
1736 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1748 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1750 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1752 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1754 return builder.createFSub(loc, ops.lhs, ops.rhs);
1757 if (ops.isFixedPointOp()) {
1763 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1765 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1770 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1782 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1786mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1788 if (ops.isFixedPointOp()) {
1798 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
1802 bool sanitizeUnsignedBase =
1803 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
1805 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1806 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
1811 else if ((sanitizeBase || sanitizeExponent) &&
1812 mlir::isa<cir::IntType>(ops.lhs.getType()))
1815 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
1818mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
1820 if (ops.isFixedPointOp()) {
1833 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
1834 mlir::isa<cir::IntType>(ops.lhs.getType()))
1839 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
1842mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
1843 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1844 cgf.
convertType(ops.fullType), cir::BinOpKind::And,
1847mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
1848 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1849 cgf.
convertType(ops.fullType), cir::BinOpKind::Xor,
1852mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
1853 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1854 cgf.
convertType(ops.fullType), cir::BinOpKind::Or,
1862mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
1864 QualType destTy = ce->
getType();
1869 ignoreResultAssign =
false;
1872 case clang::CK_Dependent:
1873 llvm_unreachable(
"dependent cast kind in CIR gen!");
1874 case clang::CK_BuiltinFnToFnPtr:
1875 llvm_unreachable(
"builtin functions are handled elsewhere");
1877 case CK_CPointerToObjCPointerCast:
1878 case CK_BlockPointerToObjCPointerCast:
1879 case CK_AnyPointerToBlockPointerCast:
1881 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
1886 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
1888 "sanitizer support");
1892 "strict vtable pointers");
1918 case CK_AddressSpaceConversion: {
1919 Expr::EvalResult result;
1936 cir::TargetAddressSpaceAttr subExprAS;
1941 "non-target address space conversion");
1945 cgf, Visit(subExpr), subExprAS, convertType(destTy));
1948 case CK_AtomicToNonAtomic: {
1954 case CK_NonAtomicToAtomic:
1955 case CK_UserDefinedConversion:
1956 return Visit(
const_cast<Expr *
>(subExpr));
1958 auto v = Visit(
const_cast<Expr *
>(subExpr));
1964 if (t != v.getType())
1969 case CK_IntegralToPointer: {
1971 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
1978 mlir::Value middleVal = builder.createCast(
1980 : cir::CastKind::integral,
1985 "IntegralToPointer: strict vtable pointers");
1989 return builder.createIntToPtr(middleVal, destCIRTy);
1992 case CK_BaseToDerived: {
1994 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2006 case CK_UncheckedDerivedToBase:
2007 case CK_DerivedToBase: {
2018 case CK_ArrayToPointerDecay:
2021 case CK_NullToPointer: {
2031 case CK_LValueToRValue:
2033 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2034 return Visit(
const_cast<Expr *
>(subExpr));
2036 case CK_IntegralCast: {
2037 ScalarConversionOpts opts;
2038 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2039 if (!ice->isPartOfExplicitCast())
2040 opts = ScalarConversionOpts(cgf.
sanOpts);
2042 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2046 case CK_FloatingComplexToReal:
2047 case CK_IntegralComplexToReal:
2048 case CK_FloatingComplexToBoolean:
2049 case CK_IntegralComplexToBoolean: {
2055 case CK_FloatingRealToComplex:
2056 case CK_FloatingComplexCast:
2057 case CK_IntegralRealToComplex:
2058 case CK_IntegralComplexCast:
2059 case CK_IntegralComplexToFloatingComplex:
2060 case CK_FloatingComplexToIntegralComplex:
2061 llvm_unreachable(
"scalar cast to non-scalar value");
2063 case CK_PointerToIntegral: {
2064 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2067 "strict vtable pointers");
2068 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
2074 case CK_IntegralToFloating:
2075 case CK_FloatingToIntegral:
2076 case CK_FloatingCast:
2077 case CK_FixedPointToFloating:
2078 case CK_FloatingToFixedPoint: {
2079 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
2081 "fixed point casts");
2085 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2089 case CK_IntegralToBoolean:
2090 return emitIntToBoolConversion(Visit(subExpr),
2093 case CK_PointerToBoolean:
2094 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2095 case CK_FloatingToBoolean:
2096 return emitFloatToBoolConversion(Visit(subExpr),
2098 case CK_MemberPointerToBoolean: {
2099 mlir::Value memPtr = Visit(subExpr);
2101 cir::CastKind::member_ptr_to_bool, memPtr,
2105 case CK_VectorSplat: {
2107 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2108 return cir::VecSplatOp::create(builder,
2112 case CK_FunctionToPointerDecay:
2122mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2124 return emitLoadOfLValue(e);
2131mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2136 Expr::EvalResult result;
2138 llvm::APSInt value = result.
Val.
getInt();
2142 return emitLoadOfLValue(e);
2145mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2146 const unsigned numInitElements = e->
getNumInits();
2148 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2149 assert((ignore ==
false ||
2151 "init list ignored");
2159 const auto vectorType =
2162 SmallVector<mlir::Value, 16> elements;
2163 for (Expr *init : e->
inits()) {
2164 elements.push_back(Visit(init));
2168 if (numInitElements < vectorType.getSize()) {
2171 std::fill_n(std::back_inserter(elements),
2172 vectorType.getSize() - numInitElements, zeroValue);
2175 return cir::VecCreateOp::create(cgf.
getBuilder(),
2181 if (numInitElements == 0)
2192 "Invalid scalar expression to emit");
2194 .emitScalarConversion(src, srcTy, dstTy, loc);
2202 "Invalid complex -> scalar conversion");
2207 ? cir::CastKind::float_complex_to_bool
2208 : cir::CastKind::int_complex_to_bool;
2213 ? cir::CastKind::float_complex_to_real
2214 : cir::CastKind::int_complex_to_real;
2220mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2227 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2229 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2230 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2238 boolVal = builder.createNot(boolVal);
2244mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2249 llvm::APSInt value = evalResult.
Val.
getInt();
2255 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2259mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2261 mlir::Value result = VisitRealImag(e, promotionTy);
2262 if (result && !promotionTy.
isNull())
2263 result = emitUnPromotedValue(result, e->
getType());
2267mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2269 mlir::Value result = VisitRealImag(e, promotionTy);
2270 if (result && !promotionTy.
isNull())
2271 result = emitUnPromotedValue(result, e->
getType());
2275mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2276 QualType promotionTy) {
2277 assert(e->
getOpcode() == clang::UO_Real ||
2279 "Invalid UnaryOp kind for ComplexType Real or Imag");
2296 ? builder.createComplexReal(loc, complex)
2297 : builder.createComplexImag(loc, complex);
2301 mlir::Value operand = promotionTy.
isNull()
2303 : cgf.emitPromotedScalarExpr(op, promotionTy);
2304 return builder.createComplexReal(loc, operand);
2309 mlir::Value operand;
2312 operand = cir::LoadOp::create(builder, loc, operand);
2313 }
else if (!promotionTy.
isNull()) {
2318 return builder.createComplexImag(loc, operand);
2323mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2324 const UnaryExprOrTypeTraitExpr *e) {
2328 kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
2331 "sizeof operator for VariableArrayType",
2333 return builder.getConstant(
2335 llvm::APSInt(llvm::APInt(64, 1),
true)));
2337 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2339 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2341 return builder.getConstant(
2343 llvm::APSInt(llvm::APInt(64, 1),
true)));
2346 return builder.getConstant(
2368mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2369 const AbstractConditionalOperator *e) {
2372 ignoreResultAssign =
false;
2375 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2377 Expr *condExpr = e->
getCond();
2385 Expr *live = lhsExpr, *dead = rhsExpr;
2387 std::swap(live, dead);
2393 mlir::Value result = Visit(live);
2400 loc, cir::PoisonAttr::get(builder.getContext(),
2408 QualType condType = condExpr->
getType();
2421 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2425 mlir::Value condValue = Visit(condExpr);
2426 mlir::Value lhsValue = Visit(lhsExpr);
2427 mlir::Value rhsValue = Visit(rhsExpr);
2428 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2437 bool lhsIsVoid =
false;
2441 mlir::Value lhs = Visit(lhsExpr);
2447 mlir::Value rhs = Visit(rhsExpr);
2449 assert(!rhs &&
"lhs and rhs types must match");
2457 CIRGenFunction::ConditionalEvaluation eval(cgf);
2458 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2459 mlir::Type yieldTy{};
2461 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2462 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2466 eval.beginEvaluation();
2467 mlir::Value branch = Visit(
expr);
2468 eval.endEvaluation();
2471 yieldTy = branch.getType();
2472 cir::YieldOp::create(
b, loc, branch);
2476 insertPoints.push_back(
b.saveInsertionPoint());
2480 mlir::Value result = cir::TernaryOp::create(
2481 builder, loc, condV,
2483 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2484 emitBranch(
b, loc, lhsExpr);
2487 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2488 emitBranch(
b, loc, rhsExpr);
2492 if (!insertPoints.empty()) {
2498 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2499 mlir::OpBuilder::InsertionGuard guard(builder);
2500 builder.restoreInsertionPoint(toInsert);
2503 if (mlir::isa<cir::VoidType>(yieldTy)) {
2504 cir::YieldOp::create(builder, loc);
2507 cir::YieldOp::create(builder, loc, op0);
2517 cir::UnaryOpKind kind,
2520 .emitScalarPrePostIncDec(e, lv, kind, isPre);
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
__device__ __2f16 float __ockl_bool s
cir::ConstantOp getBool(bool state, mlir::Location loc)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(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 createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
bool isNullPointer() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
LabelDecl * getLabel() const
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
BinaryOperatorKind Opcode
mlir::Value getPointer() const
mlir::Value createNeg(mlir::Value value)
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
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
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
friend class ::ScalarExprEmitter
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::MLIRContext & getMLIRContext()
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
LexicalScope * curLexScope
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr, mlir::Type destTy, bool isNonNull=false) const
Perform address space cast of an expression of pointer type.
Expr * getExpr()
Get the initialization expression that will be used.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
static const char * getCastKindName(CastKind CK)
unsigned getValue() const
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
This represents one expression.
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,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
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...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
A pointer to member type per C++ 8.3.3 - Pointers to members.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
SourceLocation getExprLoc() const LLVM_READONLY
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getCanonicalType() const
bool UseExcessPrecision(const ASTContext &Ctx)
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
Expr * getReplacement() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isConstantMatrixType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isExtVectorType() const
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
SourceLocation getExprLoc() const
Expr * getSubExpr() const
static bool isIncrementOp(Opcode Op)
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool isTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
U cast(CodeGen::Address addr)
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool fixedPointType()
static bool vecTernaryOp()
static bool cgFPOptionsRAII()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool HasSideEffects
Whether the evaluated expression has side effects.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.