23#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
24#include "mlir/IR/Location.h"
25#include "mlir/IR/Value.h"
47 bool isDivRemOp()
const {
48 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
49 opcode == BO_RemAssign;
53 bool mayHaveIntegerOverflow()
const {
55 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
56 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
68 bool isFixedPointOp()
const {
71 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
72 QualType lhstype = binOp->getLHS()->getType();
73 QualType rhstype = binOp->getRHS()->getType();
76 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
77 return unop->getSubExpr()->getType()->isFixedPointType();
82class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
84 CIRGenBuilderTy &builder;
88 bool ignoreResultAssign;
91 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
92 bool ignoreResultAssign =
false)
93 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
98 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
100 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
104 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
105 return cgf.cgm.emitNullConstant(ty, loc);
108 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
109 return builder.createFloatingCast(result, cgf.convertType(promotionType));
112 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
113 return builder.createFloatingCast(result, cgf.convertType(exprType));
116 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
118 mlir::Value maybePromoteBoolResult(mlir::Value value,
119 mlir::Type dstTy)
const {
120 if (mlir::isa<cir::IntType>(dstTy))
121 return builder.createBoolToInt(value, dstTy);
122 if (mlir::isa<cir::BoolType>(dstTy))
124 llvm_unreachable(
"Can only promote integer or boolean types");
131 mlir::Value Visit(Expr *e) {
132 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
135 mlir::Value VisitStmt(Stmt *s) {
136 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
139 mlir::Value VisitExpr(Expr *e) {
140 cgf.getCIRGenModule().errorNYI(
145 mlir::Value VisitConstantExpr(ConstantExpr *e) {
151 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
154 "ScalarExprEmitter: constant expr GL Value");
159 mlir::cast<mlir::TypedAttr>(result));
162 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
166 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
170 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
172 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
177 mlir::Value emitLoadOfLValue(
const Expr *e) {
178 LValue lv = cgf.emitLValue(e);
180 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
183 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
184 return cgf.emitCoawaitExpr(*s).getValue();
187 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
188 return cgf.emitCoyieldExpr(*e).getValue();
191 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
192 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
196 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
197 return cgf.emitLoadOfLValue(lv, loc).getValue();
201 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
202 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
203 return cgf.emitScalarConstant(constant, e);
205 return emitLoadOfLValue(e);
208 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
210 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
214 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->
getSourceRange()),
219 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
221 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
225 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
227 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
231 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
233 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
234 "expect floating-point type");
235 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
239 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
240 mlir::Type ty = cgf.convertType(e->
getType());
243 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
244 llvm::APInt apValue(intTy.getWidth(), e->
getValue(),
246 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
247 cir::IntAttr::get(ty, apValue));
250 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
254 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
261 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
265 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
267 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
268 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
271 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
272 return cgf.emitPseudoObjectRValue(e).getValue();
274 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
276 "ScalarExprEmitter: sycl unique stable name");
279 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
281 auto it = e->
begin();
282 llvm::APInt value = (*it)->getValue();
283 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
286 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
288 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
292 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
295 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
296 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
299 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
300 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
303 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
304 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
307 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
308 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
311 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
312 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
315 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
317 "ScalarExprEmitter: objc availability check");
321 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
323 "ScalarExprEmitter: matrix subscript");
327 mlir::Value VisitCastExpr(
CastExpr *e);
328 mlir::Value VisitCallExpr(
const CallExpr *e);
330 mlir::Value VisitStmtExpr(StmtExpr *e) {
331 CIRGenFunction::StmtExprEvaluation eval(cgf);
339 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
341 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
345 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
346 ignoreResultAssign =
false;
352 const mlir::Value vecValue = Visit(e->
getBase());
353 const mlir::Value indexValue = Visit(e->
getIdx());
354 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
357 return emitLoadOfLValue(e);
360 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
363 mlir::Value inputVec = Visit(e->
getExpr(0));
364 mlir::Value indexVec = Visit(e->
getExpr(1));
365 return cir::VecShuffleDynamicOp::create(
366 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
369 mlir::Value vec1 = Visit(e->
getExpr(0));
370 mlir::Value vec2 = Visit(e->
getExpr(1));
375 SmallVector<mlir::Attribute, 8> indices;
378 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
384 return cir::VecShuffleOp::create(cgf.builder,
386 cgf.convertType(e->
getType()), vec1, vec2,
387 cgf.builder.getArrayAttr(indices));
390 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
393 return emitScalarConversion(Visit(e->
getSrcExpr()),
398 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
400 mlir::Value VisitMatrixElementExpr(Expr *e) {
401 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
405 mlir::Value VisitMemberExpr(MemberExpr *e);
407 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
408 return emitLoadOfLValue(e);
411 mlir::Value VisitInitListExpr(InitListExpr *e);
413 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
414 assert(cgf.getArrayInitIndex() &&
415 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
416 return cgf.getArrayInitIndex();
419 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
423 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
424 return VisitCastExpr(e);
427 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
428 return cgf.cgm.emitNullConstant(e->
getType(),
433 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
436 return cgf.getBuilder().createPtrToBoolCast(v);
439 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
440 cir::BoolType boolTy = builder.getBoolTy();
441 return cir::CastOp::create(builder, loc, boolTy,
442 cir::CastKind::float_to_bool, src);
445 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
449 if (mlir::isa<cir::BoolType>(srcVal.getType()))
457 cir::BoolType boolTy = builder.getBoolTy();
458 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
464 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
465 mlir::Location loc) {
466 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
469 return emitFloatToBoolConversion(src, loc);
471 if (llvm::isa<MemberPointerType>(srcType)) {
472 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
473 return builder.getFalse(loc);
477 return emitIntToBoolConversion(src, loc);
479 assert(::mlir::isa<cir::PointerType>(src.getType()));
480 return emitPointerToBoolConversion(src, srcType);
485 struct ScalarConversionOpts {
486 bool treatBooleanAsSigned;
487 bool emitImplicitIntegerTruncationChecks;
488 bool emitImplicitIntegerSignChangeChecks;
490 ScalarConversionOpts()
491 : treatBooleanAsSigned(
false),
492 emitImplicitIntegerTruncationChecks(
false),
493 emitImplicitIntegerSignChangeChecks(
false) {}
495 ScalarConversionOpts(clang::SanitizerSet sanOpts)
496 : treatBooleanAsSigned(
false),
497 emitImplicitIntegerTruncationChecks(
498 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
499 emitImplicitIntegerSignChangeChecks(
500 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
507 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
508 QualType dstType, mlir::Type srcTy,
509 mlir::Type dstTy, ScalarConversionOpts opts) {
511 "Internal error: matrix types not handled by this function.");
512 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
513 mlir::isa<mlir::IntegerType>(dstTy)) &&
514 "Obsolete code. Don't use mlir::IntegerType with CIR.");
516 mlir::Type fullDstTy = dstTy;
517 if (mlir::isa<cir::VectorType>(srcTy) &&
518 mlir::isa<cir::VectorType>(dstTy)) {
520 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
521 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
524 std::optional<cir::CastKind> castKind;
528 cir::FenvAttr fenvAttr;
530 if (mlir::isa<cir::BoolType>(srcTy)) {
531 if (opts.treatBooleanAsSigned)
532 cgf.getCIRGenModule().errorNYI(
"signed bool");
533 if (cgf.getBuilder().isInt(dstTy)) {
534 castKind = cir::CastKind::bool_to_int;
535 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
536 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
537 castKind = cir::CastKind::bool_to_float;
539 llvm_unreachable(
"Internal error: Cast to unexpected type");
541 }
else if (cgf.getBuilder().isInt(srcTy)) {
542 if (cgf.getBuilder().isInt(dstTy)) {
543 castKind = cir::CastKind::integral;
544 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
545 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
546 castKind = cir::CastKind::int_to_float;
547 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
548 castKind = cir::CastKind::int_to_bool;
550 llvm_unreachable(
"Internal error: Cast to unexpected type");
552 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
553 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
554 if (cgf.getBuilder().isInt(dstTy)) {
558 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
559 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
560 castKind = cir::CastKind::float_to_int;
561 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
563 return builder.createFloatingCast(src, fullDstTy);
564 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
565 castKind = cir::CastKind::float_to_bool;
567 llvm_unreachable(
"Internal error: Cast to unexpected type");
570 llvm_unreachable(
"Internal error: Cast from unexpected type");
573 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
574 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
579 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
583 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
588 "variably modified types in varargs");
591 return cgf.emitVAArg(ve);
594 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
598 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
600 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
603 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
605 return emitScalarPrePostIncDec(e, lv);
607 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
608 return VisitUnaryPrePostIncDec(e);
610 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
611 return VisitUnaryPrePostIncDec(e);
613 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
614 return VisitUnaryPrePostIncDec(e);
616 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
617 return VisitUnaryPrePostIncDec(e);
620 mlir::Value emitFixedPointIncDec(
const UnaryOperator *e, mlir::Value value,
622 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
623 if (cgf.getLangOpts().OpenMP)
631 if (
type->getAs<AtomicType>()) {
635 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
638 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
652 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
653 }
else if (
type->isIntegerType()) {
654 QualType promotedType;
655 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
656 if (cgf.getContext().isPromotableIntegerType(
type)) {
657 promotedType = cgf.getContext().getPromotedIntegerType(
type);
658 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
659 canPerformLossyDemotionCheck =
true;
660 canPerformLossyDemotionCheck &=
661 cgf.getContext().getCanonicalType(
type) !=
662 cgf.getContext().getCanonicalType(promotedType);
663 canPerformLossyDemotionCheck &=
670 (!canPerformLossyDemotionCheck ||
671 type->isSignedIntegerOrEnumerationType() ||
673 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
674 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
675 "The following check expects that if we do promotion to different "
676 "underlying canonical type, at least one of the types (either "
677 "base or promoted) will be signed, or the bitwidths will match.");
682 value = emitIncDecConsiderOverflowBehavior(e, value);
685 value = emitIncOrDec(e, input,
false);
687 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
688 QualType
type = ptr->getPointeeType();
689 if (
const VariableArrayType *vla =
690 cgf.getContext().getAsVariableArrayType(
type)) {
692 mlir::Value numElts = cgf.getVLASize(vla).numElts;
694 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
696 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
701 mlir::Value amt = builder.getSInt32(amount, loc);
703 value = builder.createPtrStride(loc, value, amt);
705 }
else if (
type->isVectorType()) {
706 if (
type->hasIntegerRepresentation()) {
707 value = emitIncOrDec(e, input,
false);
709 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec vector of float");
712 }
else if (
type->isRealFloatingType()) {
713 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
715 if (
type->isHalfType() &&
716 !cgf.getContext().getLangOpts().NativeHalfType) {
721 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
723 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
724 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
725 mlir::Value amount = builder.getConstFP(
726 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
727 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
728 : builder.createFSub(loc, value, amount);
730 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
733 }
else if (
type->isFixedPointType()) {
734 value = emitFixedPointIncDec(e, value,
type);
736 assert(
type->castAs<ObjCObjectPointerType>());
737 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
741 CIRGenFunction::SourceLocRAIIObject sourceloc{
746 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
748 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
752 return e->
isPrefix() ? value : input;
755 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
757 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
758 case LangOptions::SOB_Defined:
759 return emitIncOrDec(e, inVal,
false);
760 case LangOptions::SOB_Undefined:
762 return emitIncOrDec(e, inVal,
true);
763 case LangOptions::SOB_Trapping:
765 return emitIncOrDec(e, inVal,
true);
766 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
769 llvm_unreachable(
"Unexpected signed overflow behavior kind");
772 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
773 if (llvm::isa<MemberPointerType>(e->
getType()))
774 return cgf.cgm.emitMemberPointerConstant(e);
776 return cgf.emitLValue(e->
getSubExpr()).getPointer();
779 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
782 return emitLoadOfLValue(e);
785 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
787 mlir::Value result = VisitUnaryPlus(e, promotionType);
788 if (result && !promotionType.
isNull())
789 return emitUnPromotedValue(result, e->
getType());
793 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
794 ignoreResultAssign =
false;
795 if (!promotionType.
isNull())
796 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
800 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
802 mlir::Value result = VisitUnaryMinus(e, promotionType);
803 if (result && !promotionType.
isNull())
804 return emitUnPromotedValue(result, e->
getType());
808 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
809 ignoreResultAssign =
false;
811 if (!promotionType.
isNull())
812 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
818 if (cir::isFPOrVectorOfFPType(operand.getType()))
819 return builder.createOrFold<cir::FNegOp>(loc, operand);
825 cgf.getLangOpts().getSignedOverflowBehavior() !=
826 LangOptions::SOB_Defined;
828 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
831 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
835 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
836 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
839 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
840 ignoreResultAssign =
false;
842 return builder.createOrFold<cir::NotOp>(
846 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
848 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
849 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
850 mlir::Value VisitRealImag(
const UnaryOperator *e,
851 QualType promotionType = QualType());
853 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
858 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
859 return emitLoadOfLValue(e);
861 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
862 ASTContext &ctx = cgf.getContext();
865 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
867 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
868 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
871 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
872 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
875 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
876 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
880 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
882 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
883 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
884 return cgf.emitCXXNewExpr(e);
886 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
887 cgf.emitCXXDeleteExpr(e);
890 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
896 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
901 "Expected int type for TypeTraitExpr");
902 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
909 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
915 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
917 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
920 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
923 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
925 "ScalarExprEmitter: cxx pseudo destructor");
928 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
929 cgf.emitCXXThrowExpr(e);
933 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
937 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
938 QualType dstTy, mlir::Location loc);
945 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
947 ScalarConversionOpts opts = ScalarConversionOpts()) {
955 cir::BoolType boolTy = builder.getBoolTy();
956 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
957 cir::CastKind::int_to_bool, src);
962 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
964 llvm_unreachable(
"Unhandled scalar conversion from a fixed point type to "
970 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
973 llvm_unreachable(
"Unhandled scalar conversion to a fixed point type from "
979 if (srcType == dstType) {
980 if (opts.emitImplicitIntegerSignChangeChecks)
981 cgf.getCIRGenModule().errorNYI(loc,
982 "implicit integer sign change checks");
989 mlir::Type mlirSrcType = src.getType();
994 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
996 mlir::Type mlirDstType = cgf.convertType(dstType);
999 !cgf.getContext().getLangOpts().NativeHalfType) {
1001 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1005 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1007 srcType = cgf.getContext().FloatTy;
1008 mlirSrcType = cgf.floatTy;
1014 if (mlirSrcType == mlirDstType) {
1015 if (opts.emitImplicitIntegerSignChangeChecks)
1016 cgf.getCIRGenModule().errorNYI(loc,
1017 "implicit integer sign change checks");
1024 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1025 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1026 return builder.getNullPtr(dstPT, src.getLoc());
1032 return builder.createPtrToInt(src, mlirDstType);
1039 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1041 "Splatted expr doesn't match with vector element type?");
1043 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1048 cgf.getCIRGenModule().errorNYI(loc,
1049 "matrix type to matrix type conversion");
1053 "Internal error: conversion between matrix type and scalar type");
1056 mlir::Value res =
nullptr;
1057 mlir::Type resTy = mlirDstType;
1059 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1061 if (mlirDstType != resTy) {
1062 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1066 if (opts.emitImplicitIntegerTruncationChecks)
1067 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1069 if (opts.emitImplicitIntegerSignChangeChecks)
1070 cgf.getCIRGenModule().errorNYI(loc,
1071 "implicit integer sign change checks");
1076 BinOpInfo emitBinOps(
const BinaryOperator *e,
1077 QualType promotionType = QualType()) {
1078 ignoreResultAssign =
false;
1080 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1081 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1082 if (!promotionType.
isNull())
1083 result.fullType = promotionType;
1085 result.fullType = e->
getType();
1086 result.compType = result.fullType;
1087 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1088 result.compType = vecType->getElementType();
1096 mlir::Value emitMul(
const BinOpInfo &ops);
1097 mlir::Value emitDiv(
const BinOpInfo &ops);
1098 mlir::Value emitRem(
const BinOpInfo &ops);
1099 mlir::Value emitAdd(
const BinOpInfo &ops);
1100 mlir::Value emitSub(
const BinOpInfo &ops);
1101 mlir::Value emitShl(
const BinOpInfo &ops);
1102 mlir::Value emitShr(
const BinOpInfo &ops);
1103 mlir::Value emitAnd(
const BinOpInfo &ops);
1104 mlir::Value emitXor(
const BinOpInfo &ops);
1105 mlir::Value emitOr(
const BinOpInfo &ops);
1107 mlir::Value emitFixedPointBinOp(
const BinOpInfo &ops);
1109 LValue emitCompoundAssignLValue(
1110 const CompoundAssignOperator *e,
1111 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1112 mlir::Value &result);
1114 emitCompoundAssign(
const CompoundAssignOperator *e,
1115 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1119 QualType getPromotionType(QualType ty) {
1120 const clang::ASTContext &ctx = cgf.getContext();
1121 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1122 QualType elementTy = complexTy->getElementType();
1128 if (
auto *vt = ty->
getAs<VectorType>()) {
1129 unsigned numElements = vt->getNumElements();
1132 return cgf.getContext().FloatTy;
1139#define HANDLEBINOP(OP) \
1140 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1141 QualType promotionTy = getPromotionType(e->getType()); \
1142 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1143 if (result && !promotionTy.isNull()) \
1144 result = emitUnPromotedValue(result, e->getType()); \
1147 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1148 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1166 return cir::CmpOpKind::lt;
1168 return cir::CmpOpKind::gt;
1170 return cir::CmpOpKind::le;
1172 return cir::CmpOpKind::ge;
1174 return cir::CmpOpKind::eq;
1176 return cir::CmpOpKind::ne;
1178 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1182 mlir::Value emitCmp(
const BinaryOperator *e) {
1183 ignoreResultAssign =
false;
1184 const mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1190 if (lhsTy->
getAs<MemberPointerType>()) {
1193 mlir::Value lhs = cgf.emitScalarExpr(e->
getLHS());
1194 mlir::Value rhs = cgf.emitScalarExpr(e->
getRHS());
1195 result = builder.createCompare(loc,
kind, lhs, rhs);
1197 BinOpInfo boInfo = emitBinOps(e);
1198 mlir::Value lhs = boInfo.lhs;
1199 mlir::Value rhs = boInfo.rhs;
1205 cgf.cgm.errorNYI(loc,
"AltiVec comparison");
1209 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1210 cgf.convertType(boInfo.fullType),
kind,
1211 boInfo.lhs, boInfo.rhs);
1213 }
else if (boInfo.isFixedPointOp()) {
1214 result = emitFixedPointBinOp(boInfo);
1217 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1218 mlir::isa<cir::PointerType>(lhs.getType()) &&
1219 mlir::isa<cir::PointerType>(rhs.getType())) {
1220 cgf.cgm.errorNYI(loc,
"strict vtable pointer comparisons");
1222 result = builder.createCompare(loc,
kind, lhs, rhs);
1226 "Complex Comparison: can only be an equality comparison");
1230 lhs = cgf.emitComplexExpr(e->
getLHS());
1232 mlir::Value lhsReal = Visit(e->
getLHS());
1233 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1234 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1239 rhs = cgf.emitComplexExpr(e->
getRHS());
1241 mlir::Value rhsReal = Visit(e->
getRHS());
1242 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1243 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1246 result = builder.createCompare(loc,
kind, lhs, rhs);
1249 return emitScalarConversion(result, cgf.getContext().BoolTy, e->
getType(),
1254#define VISITCOMP(CODE) \
1255 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1265 const bool ignore = std::exchange(ignoreResultAssign,
false);
1280 rhs = Visit(e->
getRHS());
1290 if (lhs.isBitField()) {
1312 if (!lhs.isVolatile())
1316 return emitLoadOfLValue(lhs, e->
getExprLoc());
1319 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1320 cgf.emitIgnoredExpr(e->
getLHS());
1322 return Visit(e->
getRHS());
1325 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1327 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1329 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1331 mlir::Value lhs = Visit(e->
getLHS());
1332 mlir::Value rhs = Visit(e->
getRHS());
1334 auto cmpOpKind = cir::CmpOpKind::ne;
1335 mlir::Type resTy = cgf.convertType(e->
getType());
1336 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1337 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1338 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1339 return builder.createIntCast(vecOr, resTy);
1343 mlir::Type resTy = cgf.convertType(e->
getType());
1344 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1346 CIRGenFunction::ConditionalEvaluation eval(cgf);
1348 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1349 auto resOp = cir::TernaryOp::create(
1350 builder, loc, lhsCondV,
1351 [&](mlir::OpBuilder &b, mlir::Location loc) {
1352 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1353 b.getInsertionBlock()};
1354 cgf.curLexScope->setAsTernary();
1355 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1357 cir::YieldOp::create(b, loc, res);
1360 [&](mlir::OpBuilder &b, mlir::Location loc) {
1361 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1362 b.getInsertionBlock()};
1364 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1365 cir::YieldOp::create(b, loc, res.getRes());
1367 return maybePromoteBoolResult(resOp.getResult(), resTy);
1370 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1372 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1374 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1376 mlir::Value lhs = Visit(e->
getLHS());
1377 mlir::Value rhs = Visit(e->
getRHS());
1379 auto cmpOpKind = cir::CmpOpKind::ne;
1380 mlir::Type resTy = cgf.convertType(e->
getType());
1381 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1382 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1383 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1384 return builder.createIntCast(vecOr, resTy);
1388 mlir::Type resTy = cgf.convertType(e->
getType());
1389 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1391 CIRGenFunction::ConditionalEvaluation eval(cgf);
1393 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1394 auto resOp = cir::TernaryOp::create(
1395 builder, loc, lhsCondV,
1396 [&](mlir::OpBuilder &b, mlir::Location loc) {
1397 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1398 b.getInsertionBlock()};
1400 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1401 cir::YieldOp::create(b, loc, res.getRes());
1404 [&](mlir::OpBuilder &b, mlir::Location loc) {
1405 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1406 b.getInsertionBlock()};
1408 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1410 cir::YieldOp::create(b, loc, res);
1413 return maybePromoteBoolResult(resOp.getResult(), resTy);
1416 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1417 return emitLoadOfLValue(e);
1420 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1421 return emitLoadOfLValue(e);
1425 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1426 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1430 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1434 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1436 "ScalarExprEmitter: objc string literal");
1439 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1440 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1443 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1445 "ScalarExprEmitter: objc array literal");
1448 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1450 "ScalarExprEmitter: objc dictionary literal");
1454 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1455 mlir::Value src,
unsigned numElementsDst) {
1456 static constexpr int64_t mask[] = {0, 1, 2, -1};
1457 return builder.createVecShuffle(
1458 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1480 mlir::Type srcTy = src.getType();
1484 return builder.createBitcast(src, dstTy);
1489 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1497 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1501 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1508 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1512 return builder.createIntToPtr(src, dstTy);
1515 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1516 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1517 mlir::Type srcTy = src.getType();
1518 mlir::Type dstTy = cgf.convertType(e->
getType());
1530 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1536 if (numElementsSrc == 3 && numElementsDst != 3) {
1538 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1539 "numElemsDst != 3");
1546 if (numElementsSrc != 3 && numElementsDst == 3) {
1547 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1549 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1551 src = convertVec3AndVec4(builder, loc, src, 3);
1558 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1559 return cgf.emitAtomicExpr(e).getValue();
1563LValue ScalarExprEmitter::emitCompoundAssignLValue(
1565 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1566 mlir::Value &result) {
1577 if (promotionTypeCR.
isNull())
1581 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1583 if (!promotionTypeRHS.
isNull())
1586 opInfo.rhs = Visit(e->
getRHS());
1588 opInfo.fullType = promotionTypeCR;
1589 opInfo.compType = opInfo.fullType;
1590 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1591 opInfo.compType = vecType->getElementType();
1600 if (lhsTy->
getAs<AtomicType>()) {
1601 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1605 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1607 CIRGenFunction::SourceLocRAIIObject sourceloc{
1610 if (!promotionTypeLHS.
isNull())
1611 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1613 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1617 result = (this->*func)(opInfo);
1621 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1622 ScalarConversionOpts(cgf.
sanOpts));
1628 if (lhsLV.isBitField())
1639mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1643 cir::CastKind castOpKind;
1645 case CK_FloatingComplexToReal:
1646 castOpKind = cir::CastKind::float_complex_to_real;
1648 case CK_IntegralComplexToReal:
1649 castOpKind = cir::CastKind::int_complex_to_real;
1651 case CK_FloatingComplexToBoolean:
1652 castOpKind = cir::CastKind::float_complex_to_bool;
1654 case CK_IntegralComplexToBoolean:
1655 castOpKind = cir::CastKind::int_complex_to_bool;
1658 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1664mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1665 QualType promotionType) {
1667 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1668 switch (bo->getOpcode()) {
1669#define HANDLE_BINOP(OP) \
1671 return emit##OP(emitBinOps(bo, promotionType));
1680 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1681 switch (uo->getOpcode()) {
1684 return VisitRealImag(uo, promotionType);
1686 return VisitUnaryMinus(uo, promotionType);
1688 return VisitUnaryPlus(uo, promotionType);
1693 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1695 if (!promotionType.
isNull())
1696 return emitPromotedValue(result, promotionType);
1697 return emitUnPromotedValue(result, e->
getType());
1702mlir::Value ScalarExprEmitter::emitCompoundAssign(
1703 const CompoundAssignOperator *e,
1704 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1706 bool ignore = std::exchange(ignoreResultAssign,
false);
1708 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1719 if (!lhs.isVolatile())
1723 return emitLoadOfLValue(lhs, e->
getExprLoc());
1726mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1727 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1742#define COMPOUND_OP(Op) \
1743 case BO_##Op##Assign: \
1744 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1781 llvm_unreachable(
"Not valid compound assignment operators");
1783 llvm_unreachable(
"Unhandled compound assignment operator");
1788 bool ignoreResultAssign) {
1790 "Invalid scalar expression to emit");
1793 .Visit(
const_cast<Expr *
>(e));
1798 if (!promotionType.
isNull())
1813static std::optional<QualType>
1817 return std::nullopt;
1822 return std::nullopt;
1835 const BinOpInfo &op) {
1837 "Expected a unary or binary operator");
1841 if (!op.mayHaveIntegerOverflow())
1845 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1846 return !uo->canOverflow();
1851 std::optional<QualType> optionalLHSTy =
1856 std::optional<QualType> optionalRHSTy =
1866 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1873 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1874 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1879 const BinOpInfo &op,
1880 bool isSubtraction) {
1885 mlir::Value pointer = op.lhs;
1886 Expr *pointerOperand =
expr->getLHS();
1887 mlir::Value
index = op.rhs;
1888 Expr *indexOperand =
expr->getRHS();
1894 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1895 std::swap(pointer,
index);
1896 std::swap(pointerOperand, indexOperand);
1898 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1899 "Need a pointer operand");
1900 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1935 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1945 numElements.getType());
1956 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1961 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1963 pointer.getType(), pointer,
index);
1967 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1968 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1978 bool negMul,
bool negAdd) {
1979 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
1980 mlir::Value mulOp0 = mulOp.getLhs();
1981 mlir::Value mulOp1 = mulOp.getRhs();
1989 mlir::Value fmuladd =
1990 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
1991 addend, mulOp.getFenvAttr());
2004 bool isSub =
false) {
2005 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2006 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2007 "Only fadd/fsub can be the root of an fmuladd.");
2016 mlir::Value lhs = op.lhs;
2017 mlir::Value rhs = op.rhs;
2021 bool negLHS =
false;
2022 if (
auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2023 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2024 lhs = lhsNeg.getInput();
2029 bool negRHS =
false;
2030 if (
auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2031 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2032 rhs = rhsNeg.getInput();
2040 if (
auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2041 if (lhsMul.getResult().use_empty() || negLHS) {
2044 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2045 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2048 if (
auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2049 if (rhsMul.getResult().use_empty() || negRHS) {
2052 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2053 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS,
false);
2060mlir::Value ScalarExprEmitter::emitFixedPointIncDec(
const UnaryOperator *e,
2079 if (
type->isSignedFixedPointType()) {
2086 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(
info.loc));
2089 fpbuilder.createIntegerToFixed(
info.rhs,
true, dstSema);
2090 return emitFixedPointBinOp(info);
2093mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2096 mlir::Location loc) {
2099 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2103 result = fpBuilder.createFloatingToFixed(
2107 result = fpBuilder.createFixedToFloating(
2111 llvm::FixedPointSemantics srcFPSema =
2113 llvm::FixedPointSemantics dstFPSema =
2117 result = fpBuilder.createFixedToInteger(
2118 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2121 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2124 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2130mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
2131 const mlir::Location loc = cgf.
getLoc(ops.loc);
2134 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2135 case LangOptions::SOB_Defined:
2136 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2137 return builder.
createMul(loc, ops.lhs, ops.rhs);
2139 case LangOptions::SOB_Undefined:
2140 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2143 case LangOptions::SOB_Trapping:
2155 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2157 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2159 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2160 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2161 return builder.
createFMul(loc, ops.lhs, ops.rhs);
2164 if (ops.isFixedPointOp())
2165 return emitFixedPointBinOp(ops);
2167 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2170mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2171 const mlir::Location loc = cgf.
getLoc(ops.loc);
2172 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2173 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2174 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2177 if (ops.isFixedPointOp())
2178 return emitFixedPointBinOp(ops);
2180 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2183mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2184 const mlir::Location loc = cgf.
getLoc(ops.loc);
2185 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2186 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2187 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2189 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2193mlir::Value ScalarExprEmitter::emitFixedPointBinOp(
const BinOpInfo &ops) {
2198 QualType resultTy = ops.compType;
2199 QualType lhsTy, rhsTy;
2200 if (
const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2201 rhsTy = binOp->getRHS()->getType();
2202 if (
const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2207 lhsTy = cao->getComputationLHSType();
2208 resultTy = cao->getComputationResultType();
2210 lhsTy = binOp->getLHS()->getType();
2212 }
else if (
const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2213 lhsTy = unOp->getSubExpr()->getType();
2214 rhsTy = unOp->getSubExpr()->getType();
2217 mlir::Value lhs = ops.lhs;
2218 mlir::Value rhs = ops.rhs;
2223 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2227 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(ops.loc));
2228 switch (ops.opcode) {
2231 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2235 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2239 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2243 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2247 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2251 result = fpbuilder.createShr(lhs, rhs);
2259 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2260 clangCmpToCIRCmp(ops.opcode));
2264 llvm_unreachable(
"Found unimplemented fixed point binary operation");
2278 "Found unsupported binary operation for fixed point types.");
2284 return fpbuilder.createFixedToFixed(
2285 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2288mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2289 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2290 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2294 const mlir::Location loc = cgf.
getLoc(ops.loc);
2297 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2298 case LangOptions::SOB_Defined:
2299 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2300 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2302 case LangOptions::SOB_Undefined:
2303 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2306 case LangOptions::SOB_Trapping:
2319 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2321 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2323 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2324 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2328 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2331 if (ops.isFixedPointOp())
2332 return emitFixedPointBinOp(ops);
2334 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2337mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2338 const mlir::Location loc = cgf.
getLoc(ops.loc);
2340 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2343 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2344 case LangOptions::SOB_Defined: {
2345 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2346 return builder.
createSub(loc, ops.lhs, ops.rhs);
2349 case LangOptions::SOB_Undefined:
2350 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2353 case LangOptions::SOB_Trapping:
2367 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2369 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2371 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2372 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2374 if (mlir::Value fmuladd =
2377 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2380 if (ops.isFixedPointOp())
2381 return emitFixedPointBinOp(ops);
2383 return builder.
createSub(loc, ops.lhs, ops.rhs);
2388 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2400 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2404mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2406 if (ops.isFixedPointOp())
2407 return emitFixedPointBinOp(ops);
2413 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2417 bool sanitizeUnsignedBase =
2418 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2420 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2421 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2426 else if ((sanitizeBase || sanitizeExponent) &&
2427 mlir::isa<cir::IntType>(ops.lhs.getType()))
2433mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2435 if (ops.isFixedPointOp())
2436 return emitFixedPointBinOp(ops);
2445 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2446 mlir::isa<cir::IntType>(ops.lhs.getType()))
2454mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2455 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2457mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2458 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2460mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2461 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2468mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2470 QualType destTy = ce->
getType();
2472 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2476 ignoreResultAssign =
false;
2479 case clang::CK_Dependent:
2480 llvm_unreachable(
"dependent cast kind in CIR gen!");
2481 case clang::CK_BuiltinFnToFnPtr:
2482 llvm_unreachable(
"builtin functions are handled elsewhere");
2483 case CK_LValueBitCast:
2484 case CK_LValueToRValueBitCast: {
2486 Address sourceAddr = sourceLVal.getAddress();
2492 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2495 case CK_CPointerToObjCPointerCast:
2496 case CK_BlockPointerToObjCPointerCast:
2497 case CK_AnyPointerToBlockPointerCast:
2499 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2504 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2506 "sanitizer support");
2510 "strict vtable pointers");
2536 case CK_AddressSpaceConversion: {
2537 Expr::EvalResult result;
2551 case CK_AtomicToNonAtomic:
2552 case CK_NonAtomicToAtomic:
2553 case CK_UserDefinedConversion:
2554 return Visit(
const_cast<Expr *
>(subExpr));
2558 case CK_IntegralToPointer: {
2560 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2569 : cir::CastKind::integral,
2574 "IntegralToPointer: strict vtable pointers");
2581 case CK_BaseToDerived: {
2583 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2595 case CK_UncheckedDerivedToBase:
2596 case CK_DerivedToBase: {
2607 case CK_ArrayToPointerDecay:
2610 case CK_NullToPointer: {
2620 case CK_NullToMemberPointer: {
2626 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2632 case CK_ReinterpretMemberPointer: {
2633 mlir::Value src = Visit(subExpr);
2637 case CK_BaseToDerivedMemberPointer:
2638 case CK_DerivedToBaseMemberPointer: {
2639 mlir::Value src = Visit(subExpr);
2643 QualType derivedTy =
2644 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2645 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2646 NestedNameSpecifier qualifier = mpType->getQualifier();
2647 assert(qualifier &&
"member pointer without class qualifier");
2648 const Type *qualifierType = qualifier.getAsType();
2649 assert(qualifierType &&
"member pointer qualifier is not a type");
2656 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2659 if (
kind == CK_BaseToDerivedMemberPointer)
2660 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2662 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2665 if (
kind == CK_BaseToDerivedMemberPointer)
2666 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2668 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2672 case CK_LValueToRValue:
2674 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2675 return Visit(
const_cast<Expr *
>(subExpr));
2677 case CK_IntegralCast: {
2678 ScalarConversionOpts opts;
2679 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2680 if (!ice->isPartOfExplicitCast())
2681 opts = ScalarConversionOpts(cgf.
sanOpts);
2683 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2687 case CK_FloatingComplexToReal:
2688 case CK_IntegralComplexToReal:
2689 case CK_FloatingComplexToBoolean:
2690 case CK_IntegralComplexToBoolean: {
2696 case CK_FloatingRealToComplex:
2697 case CK_FloatingComplexCast:
2698 case CK_IntegralRealToComplex:
2699 case CK_IntegralComplexCast:
2700 case CK_IntegralComplexToFloatingComplex:
2701 case CK_FloatingComplexToIntegralComplex:
2702 llvm_unreachable(
"scalar cast to non-scalar value");
2704 case CK_PointerToIntegral: {
2705 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2708 "strict vtable pointers");
2715 case CK_FixedPointCast:
2716 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2719 case CK_FixedPointToBoolean:
2721 "Expected src type to be fixed point type");
2722 assert(destTy->
isBooleanType() &&
"Expected dest type to be boolean type");
2723 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2726 case CK_FixedPointToIntegral:
2728 "Expected src type to be fixed point type");
2729 assert(destTy->
isIntegerType() &&
"Expected dest type to be an integer");
2730 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2733 case CK_IntegralToFixedPoint:
2735 "Expected src type to be an integer");
2737 "Expected dest type to be fixed point type");
2738 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2741 case CK_IntegralToFloating:
2742 case CK_FloatingToIntegral:
2743 case CK_FloatingCast:
2744 case CK_FixedPointToFloating:
2745 case CK_FloatingToFixedPoint: {
2746 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2747 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2751 case CK_IntegralToBoolean:
2752 return emitIntToBoolConversion(Visit(subExpr),
2755 case CK_PointerToBoolean:
2756 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2757 case CK_FloatingToBoolean:
2758 return emitFloatToBoolConversion(Visit(subExpr),
2760 case CK_MemberPointerToBoolean: {
2761 mlir::Value memPtr = Visit(subExpr);
2763 cir::CastKind::member_ptr_to_bool, memPtr,
2767 case CK_VectorSplat: {
2769 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2770 return cir::VecSplatOp::create(builder,
2774 case CK_FunctionToPointerDecay:
2784mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2786 return emitLoadOfLValue(e);
2793mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2798 Expr::EvalResult result;
2800 llvm::APSInt value = result.
Val.
getInt();
2810 return builder.
getBool(value.getBoolValue(), loc);
2813 return emitLoadOfLValue(e);
2816mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2817 const unsigned numInitElements = e->
getNumInits();
2819 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2820 assert((ignore ==
false ||
2822 "init list ignored");
2830 const auto vectorType =
2833 SmallVector<mlir::Value, 16> elements;
2834 for (Expr *init : e->
inits()) {
2835 elements.push_back(Visit(init));
2839 if (numInitElements < vectorType.getSize()) {
2842 std::fill_n(std::back_inserter(elements),
2843 vectorType.getSize() - numInitElements, zeroValue);
2846 return cir::VecCreateOp::create(cgf.
getBuilder(),
2852 if (numInitElements == 0)
2863 "Invalid scalar expression to emit");
2865 .emitScalarConversion(src, srcTy, dstTy, loc);
2873 "Invalid complex -> scalar conversion");
2878 ? cir::CastKind::float_complex_to_bool
2879 : cir::CastKind::int_complex_to_bool;
2884 ? cir::CastKind::float_complex_to_real
2885 : cir::CastKind::int_complex_to_real;
2891mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2898 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2899 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2913mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2918 llvm::APSInt value = evalResult.
Val.
getInt();
2924 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2928mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2930 mlir::Value result = VisitRealImag(e, promotionTy);
2931 if (result && !promotionTy.
isNull())
2932 result = emitUnPromotedValue(result, e->
getType());
2936mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2938 mlir::Value result = VisitRealImag(e, promotionTy);
2939 if (result && !promotionTy.
isNull())
2940 result = emitUnPromotedValue(result, e->
getType());
2944mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2945 QualType promotionTy) {
2948 "Invalid UnaryOp kind for ComplexType Real or Imag");
2970 mlir::Value operand = promotionTy.
isNull()
2972 : cgf.emitPromotedScalarExpr(op, promotionTy);
2978 mlir::Value operand;
2981 operand = cir::LoadOp::create(builder, loc, operand);
2982 }
else if (!promotionTy.
isNull()) {
2992mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2993 const UnaryExprOrTypeTraitExpr *e) {
2997 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2998 if (
const VariableArrayType *vat =
3003 bool evaluateExtent =
true;
3004 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3006 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
3009 if (evaluateExtent) {
3020 if (
kind == UETT_CountOf)
3025 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
3026 mlir::Value numElts = vlaSize.
numElts;
3030 if (!eltSize.
isOne()) {
3032 mlir::Value eltSizeValue =
3035 return builder.
createMul(loc, eltSizeValue, numElts,
3042 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
3049 }
else if (e->
getKind() == UETT_VectorElements) {
3051 if (vecTy.getIsScalable()) {
3054 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3061 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getSize()));
3088mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3089 const AbstractConditionalOperator *e) {
3092 ignoreResultAssign =
false;
3095 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3097 Expr *condExpr = e->
getCond();
3105 Expr *live = lhsExpr, *dead = rhsExpr;
3107 std::swap(live, dead);
3113 mlir::Value result = Visit(live);
3120 loc, cir::PoisonAttr::get(builder.getContext(),
3128 QualType condType = condExpr->
getType();
3137 mlir::Value lhsValue = Visit(lhsExpr);
3138 mlir::Value rhsValue = Visit(rhsExpr);
3140 mlir::Type vecTy = convertType(condType);
3141 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
3142 auto testMSB = cir::VecCmpOp::create(
3143 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3145 mlir::Value tmp2 = builder.
createNot(tmp);
3148 mlir::Value rhsTmp = rhsValue;
3149 mlir::Value lhsTmp = lhsValue;
3150 bool wasCast =
false;
3152 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
3158 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
3159 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
3160 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
3169 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
3173 mlir::Value condValue = Visit(condExpr);
3174 mlir::Value lhsValue = Visit(lhsExpr);
3175 mlir::Value rhsValue = Visit(rhsExpr);
3176 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3185 bool lhsIsVoid =
false;
3189 mlir::Value lhs = Visit(lhsExpr);
3195 mlir::Value rhs = Visit(rhsExpr);
3197 assert(!rhs &&
"lhs and rhs types must match");
3205 CIRGenFunction::ConditionalEvaluation eval(cgf);
3207 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
3208 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3215 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3217 eval.beginEvaluation();
3218 branch = Visit(
expr);
3219 eval.endEvaluation();
3220 branchCleanups.forceCleanup({&branch});
3224 cir::YieldOp::create(b, loc, branch);
3227 cir::TernaryOp ternary = cir::TernaryOp::create(
3228 builder, loc, condV,
3230 [&](mlir::OpBuilder &b, mlir::Location loc) {
3231 emitBranch(b, loc, lhsExpr);
3234 [&](mlir::OpBuilder &b, mlir::Location loc) {
3235 emitBranch(b, loc, rhsExpr);
3240 for (mlir::Region *region :
3241 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3242 mlir::Block &lastBlock = region->back();
3243 if (lastBlock.empty() ||
3244 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3245 mlir::OpBuilder::InsertionGuard guard(builder);
3246 builder.setInsertionPointToEnd(&lastBlock);
3247 cir::YieldOp::create(builder, loc);
3251 return ternary.getResult();
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
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 mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op, CIRGenBuilderTy &builder, bool isSub=false)
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 mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp, mlir::Value addend, CIRGenBuilderTy &builder, bool negMul, bool negAdd)
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.
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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 createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, 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)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
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.
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const
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.
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.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
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
uint64_t getValue() const
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
bool isShiftAssignOp() 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
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
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...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
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).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
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::Type convertTypeForMem(QualType t)
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::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
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)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
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.
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 ...
bool changesVolatileQualification() const
Return.
static const char * getCastKindName(CastKind CK)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isOne() const
isOne - Test whether the quantity equals one.
unsigned getValue() const
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
ChildElementIter< false > begin()
size_t getDataElementCount() const
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...
bool allowFPContractWithinStatement() const
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
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() const
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
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.
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.
bool isSatisfied() const
Whether or not the requires clause is satisfied.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
unsigned getPackLength() const
Retrieve the length of the parameter pack.
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
SourceLocation getLocation() const
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 getBoolValue() const
const APValue & getAPValue() const
bool isStoredAsBoolean() 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,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantMatrixType() 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 isExtVectorBoolType() 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 isMemberFunctionPointerType() 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.
bool isArgumentType() const
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)
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a C array with a specified size that is not an integer-constant-expression.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
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.
@ Address
A pointer to a ValueDecl.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Type
The name was classified as a type.
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 vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool fastMathFlags()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
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.