22#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
23#include "mlir/IR/Location.h"
24#include "mlir/IR/Value.h"
46 bool isDivRemOp()
const {
47 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
48 opcode == BO_RemAssign;
52 bool mayHaveIntegerOverflow()
const {
54 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
55 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
67 bool isFixedPointOp()
const {
70 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
71 QualType lhstype = binOp->getLHS()->getType();
72 QualType rhstype = binOp->getRHS()->getType();
75 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
76 return unop->getSubExpr()->getType()->isFixedPointType();
81class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
83 CIRGenBuilderTy &builder;
87 bool ignoreResultAssign;
90 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
91 bool ignoreResultAssign =
false)
92 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
97 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
99 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
103 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
104 return cgf.cgm.emitNullConstant(ty, loc);
107 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
108 return builder.createFloatingCast(result, cgf.convertType(promotionType));
111 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
112 return builder.createFloatingCast(result, cgf.convertType(exprType));
115 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
117 mlir::Value maybePromoteBoolResult(mlir::Value value,
118 mlir::Type dstTy)
const {
119 if (mlir::isa<cir::IntType>(dstTy))
120 return builder.createBoolToInt(value, dstTy);
121 if (mlir::isa<cir::BoolType>(dstTy))
123 llvm_unreachable(
"Can only promote integer or boolean types");
130 mlir::Value Visit(Expr *e) {
131 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
134 mlir::Value VisitStmt(Stmt *s) {
135 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
138 mlir::Value VisitExpr(Expr *e) {
139 cgf.getCIRGenModule().errorNYI(
144 mlir::Value VisitConstantExpr(ConstantExpr *e) {
150 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
153 "ScalarExprEmitter: constant expr GL Value");
158 mlir::cast<mlir::TypedAttr>(result));
161 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
165 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
169 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
171 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
176 mlir::Value emitLoadOfLValue(
const Expr *e) {
177 LValue lv = cgf.emitLValue(e);
179 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
182 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
183 return cgf.emitCoawaitExpr(*s).getValue();
186 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
187 return cgf.emitCoyieldExpr(*e).getValue();
190 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
191 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
195 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
196 return cgf.emitLoadOfLValue(lv, loc).getValue();
200 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
201 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
202 return cgf.emitScalarConstant(constant, e);
204 return emitLoadOfLValue(e);
207 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
209 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
211 cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
214 cgf.indirectGotoTargets.push_back(blockInfoAttr);
215 return blockAddressOp;
218 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
220 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
224 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
226 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
230 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
232 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
233 "expect floating-point type");
234 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
238 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
239 mlir::Type ty = cgf.convertType(e->
getType());
242 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
243 llvm::APInt apValue(intTy.getWidth(), e->
getValue(),
245 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
246 cir::IntAttr::get(ty, apValue));
249 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
253 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
260 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
264 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
266 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
267 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
270 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
271 return cgf.emitPseudoObjectRValue(e).getValue();
273 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
275 "ScalarExprEmitter: sycl unique stable name");
278 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
280 auto it = e->
begin();
281 llvm::APInt value = (*it)->getValue();
282 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
285 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
287 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
291 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
294 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
295 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
298 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
299 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
302 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
303 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
306 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
307 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
310 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
311 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
314 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
316 "ScalarExprEmitter: objc availability check");
320 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
322 "ScalarExprEmitter: matrix subscript");
326 mlir::Value VisitCastExpr(
CastExpr *e);
327 mlir::Value VisitCallExpr(
const CallExpr *e);
329 mlir::Value VisitStmtExpr(StmtExpr *e) {
330 CIRGenFunction::StmtExprEvaluation eval(cgf);
338 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
340 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
344 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
345 ignoreResultAssign =
false;
351 const mlir::Value vecValue = Visit(e->
getBase());
352 const mlir::Value indexValue = Visit(e->
getIdx());
353 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
356 return emitLoadOfLValue(e);
359 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
362 mlir::Value inputVec = Visit(e->
getExpr(0));
363 mlir::Value indexVec = Visit(e->
getExpr(1));
364 return cir::VecShuffleDynamicOp::create(
365 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
368 mlir::Value vec1 = Visit(e->
getExpr(0));
369 mlir::Value vec2 = Visit(e->
getExpr(1));
374 SmallVector<mlir::Attribute, 8> indices;
377 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
383 return cir::VecShuffleOp::create(cgf.builder,
385 cgf.convertType(e->
getType()), vec1, vec2,
386 cgf.builder.getArrayAttr(indices));
389 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
392 return emitScalarConversion(Visit(e->
getSrcExpr()),
397 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
399 mlir::Value VisitMatrixElementExpr(Expr *e) {
400 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
404 mlir::Value VisitMemberExpr(MemberExpr *e);
406 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
407 return emitLoadOfLValue(e);
410 mlir::Value VisitInitListExpr(InitListExpr *e);
412 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
413 assert(cgf.getArrayInitIndex() &&
414 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
415 return cgf.getArrayInitIndex();
418 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
422 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
423 return VisitCastExpr(e);
426 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
427 return cgf.cgm.emitNullConstant(e->
getType(),
432 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
435 return cgf.getBuilder().createPtrToBoolCast(v);
438 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
439 cir::BoolType boolTy = builder.getBoolTy();
440 return cir::CastOp::create(builder, loc, boolTy,
441 cir::CastKind::float_to_bool, src);
444 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
448 if (mlir::isa<cir::BoolType>(srcVal.getType()))
456 cir::BoolType boolTy = builder.getBoolTy();
457 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
463 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
464 mlir::Location loc) {
465 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
468 return emitFloatToBoolConversion(src, loc);
470 if (llvm::isa<MemberPointerType>(srcType)) {
471 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
472 return builder.getFalse(loc);
476 return emitIntToBoolConversion(src, loc);
478 assert(::mlir::isa<cir::PointerType>(src.getType()));
479 return emitPointerToBoolConversion(src, srcType);
484 struct ScalarConversionOpts {
485 bool treatBooleanAsSigned;
486 bool emitImplicitIntegerTruncationChecks;
487 bool emitImplicitIntegerSignChangeChecks;
489 ScalarConversionOpts()
490 : treatBooleanAsSigned(
false),
491 emitImplicitIntegerTruncationChecks(
false),
492 emitImplicitIntegerSignChangeChecks(
false) {}
494 ScalarConversionOpts(clang::SanitizerSet sanOpts)
495 : treatBooleanAsSigned(
false),
496 emitImplicitIntegerTruncationChecks(
497 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
498 emitImplicitIntegerSignChangeChecks(
499 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
506 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
507 QualType dstType, mlir::Type srcTy,
508 mlir::Type dstTy, ScalarConversionOpts opts) {
510 "Internal error: matrix types not handled by this function.");
511 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
512 mlir::isa<mlir::IntegerType>(dstTy)) &&
513 "Obsolete code. Don't use mlir::IntegerType with CIR.");
515 mlir::Type fullDstTy = dstTy;
516 if (mlir::isa<cir::VectorType>(srcTy) &&
517 mlir::isa<cir::VectorType>(dstTy)) {
519 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
520 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
523 std::optional<cir::CastKind> castKind;
525 if (mlir::isa<cir::BoolType>(srcTy)) {
526 if (opts.treatBooleanAsSigned)
527 cgf.getCIRGenModule().errorNYI(
"signed bool");
528 if (cgf.getBuilder().isInt(dstTy))
529 castKind = cir::CastKind::bool_to_int;
530 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
531 castKind = cir::CastKind::bool_to_float;
533 llvm_unreachable(
"Internal error: Cast to unexpected type");
534 }
else if (cgf.getBuilder().isInt(srcTy)) {
535 if (cgf.getBuilder().isInt(dstTy))
536 castKind = cir::CastKind::integral;
537 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
538 castKind = cir::CastKind::int_to_float;
539 else if (mlir::isa<cir::BoolType>(dstTy))
540 castKind = cir::CastKind::int_to_bool;
542 llvm_unreachable(
"Internal error: Cast to unexpected type");
543 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
544 if (cgf.getBuilder().isInt(dstTy)) {
548 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
549 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
551 castKind = cir::CastKind::float_to_int;
552 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
554 return builder.createFloatingCast(src, fullDstTy);
555 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
556 castKind = cir::CastKind::float_to_bool;
558 llvm_unreachable(
"Internal error: Cast to unexpected type");
561 llvm_unreachable(
"Internal error: Cast from unexpected type");
564 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
565 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
570 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
574 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
579 "variably modified types in varargs");
582 return cgf.emitVAArg(ve);
585 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
589 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
591 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
594 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
596 return emitScalarPrePostIncDec(e, lv);
598 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
599 return VisitUnaryPrePostIncDec(e);
601 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
602 return VisitUnaryPrePostIncDec(e);
604 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
605 return VisitUnaryPrePostIncDec(e);
607 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
608 return VisitUnaryPrePostIncDec(e);
610 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
611 if (cgf.getLangOpts().OpenMP)
619 if (
type->getAs<AtomicType>()) {
623 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
626 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
640 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
641 }
else if (
type->isIntegerType()) {
642 QualType promotedType;
643 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
644 if (cgf.getContext().isPromotableIntegerType(
type)) {
645 promotedType = cgf.getContext().getPromotedIntegerType(
type);
646 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
647 canPerformLossyDemotionCheck =
true;
648 canPerformLossyDemotionCheck &=
649 cgf.getContext().getCanonicalType(
type) !=
650 cgf.getContext().getCanonicalType(promotedType);
651 canPerformLossyDemotionCheck &=
658 (!canPerformLossyDemotionCheck ||
659 type->isSignedIntegerOrEnumerationType() ||
661 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
662 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
663 "The following check expects that if we do promotion to different "
664 "underlying canonical type, at least one of the types (either "
665 "base or promoted) will be signed, or the bitwidths will match.");
670 value = emitIncDecConsiderOverflowBehavior(e, value);
673 value = emitIncOrDec(e, input,
false);
675 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
676 QualType
type = ptr->getPointeeType();
677 if (
const VariableArrayType *vla =
678 cgf.getContext().getAsVariableArrayType(
type)) {
680 mlir::Value numElts = cgf.getVLASize(vla).numElts;
682 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
684 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
689 mlir::Value amt = builder.getSInt32(amount, loc);
691 value = builder.createPtrStride(loc, value, amt);
693 }
else if (
type->isVectorType()) {
694 if (
type->hasIntegerRepresentation()) {
695 value = emitIncOrDec(e, input,
false);
697 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec vector of float");
700 }
else if (
type->isRealFloatingType()) {
701 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
703 if (
type->isHalfType() &&
704 !cgf.getContext().getLangOpts().NativeHalfType) {
709 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
711 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
712 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
713 mlir::Value amount = builder.getConstFP(
714 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
715 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
716 : builder.createFSub(loc, value, amount);
718 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
721 }
else if (
type->isFixedPointType()) {
722 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
725 assert(
type->castAs<ObjCObjectPointerType>());
726 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
730 CIRGenFunction::SourceLocRAIIObject sourceloc{
735 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
737 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
741 return e->
isPrefix() ? value : input;
744 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
746 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
747 case LangOptions::SOB_Defined:
748 return emitIncOrDec(e, inVal,
false);
749 case LangOptions::SOB_Undefined:
751 return emitIncOrDec(e, inVal,
true);
752 case LangOptions::SOB_Trapping:
754 return emitIncOrDec(e, inVal,
true);
755 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
758 llvm_unreachable(
"Unexpected signed overflow behavior kind");
761 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
762 if (llvm::isa<MemberPointerType>(e->
getType()))
763 return cgf.cgm.emitMemberPointerConstant(e);
765 return cgf.emitLValue(e->
getSubExpr()).getPointer();
768 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
771 return emitLoadOfLValue(e);
774 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
776 mlir::Value result = VisitUnaryPlus(e, promotionType);
777 if (result && !promotionType.
isNull())
778 return emitUnPromotedValue(result, e->
getType());
782 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
783 ignoreResultAssign =
false;
784 if (!promotionType.
isNull())
785 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
789 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
791 mlir::Value result = VisitUnaryMinus(e, promotionType);
792 if (result && !promotionType.
isNull())
793 return emitUnPromotedValue(result, e->
getType());
797 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
798 ignoreResultAssign =
false;
800 if (!promotionType.
isNull())
801 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
807 if (cir::isFPOrVectorOfFPType(operand.getType()))
808 return builder.createOrFold<cir::FNegOp>(loc, operand);
814 cgf.getLangOpts().getSignedOverflowBehavior() !=
815 LangOptions::SOB_Defined;
817 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
820 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
824 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
825 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
828 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
829 ignoreResultAssign =
false;
831 return builder.createOrFold<cir::NotOp>(
835 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
837 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
838 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
839 mlir::Value VisitRealImag(
const UnaryOperator *e,
840 QualType promotionType = QualType());
842 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
847 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
849 "ScalarExprEmitter: materialize temporary");
852 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
853 ASTContext &ctx = cgf.getContext();
856 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
858 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
859 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
862 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
863 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
866 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
867 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
871 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
873 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
874 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
875 return cgf.emitCXXNewExpr(e);
877 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
878 cgf.emitCXXDeleteExpr(e);
881 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
887 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
892 "Expected int type for TypeTraitExpr");
893 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
899 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
905 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
907 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
910 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
913 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
915 "ScalarExprEmitter: cxx pseudo destructor");
918 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
919 cgf.emitCXXThrowExpr(e);
923 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
932 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
934 ScalarConversionOpts opts = ScalarConversionOpts()) {
944 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
950 if (srcType == dstType) {
951 if (opts.emitImplicitIntegerSignChangeChecks)
952 cgf.getCIRGenModule().errorNYI(loc,
953 "implicit integer sign change checks");
960 mlir::Type mlirSrcType = src.getType();
965 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
967 mlir::Type mlirDstType = cgf.convertType(dstType);
970 !cgf.getContext().getLangOpts().NativeHalfType) {
972 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
976 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
978 srcType = cgf.getContext().FloatTy;
979 mlirSrcType = cgf.floatTy;
985 if (mlirSrcType == mlirDstType) {
986 if (opts.emitImplicitIntegerSignChangeChecks)
987 cgf.getCIRGenModule().errorNYI(loc,
988 "implicit integer sign change checks");
995 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
996 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
997 return builder.getNullPtr(dstPT, src.getLoc());
1003 return builder.createPtrToInt(src, mlirDstType);
1010 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1012 "Splatted expr doesn't match with vector element type?");
1014 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1019 cgf.getCIRGenModule().errorNYI(loc,
1020 "matrix type to matrix type conversion");
1024 "Internal error: conversion between matrix type and scalar type");
1027 mlir::Value res =
nullptr;
1028 mlir::Type resTy = mlirDstType;
1030 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1032 if (mlirDstType != resTy) {
1033 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1037 if (opts.emitImplicitIntegerTruncationChecks)
1038 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1040 if (opts.emitImplicitIntegerSignChangeChecks)
1041 cgf.getCIRGenModule().errorNYI(loc,
1042 "implicit integer sign change checks");
1047 BinOpInfo emitBinOps(
const BinaryOperator *e,
1048 QualType promotionType = QualType()) {
1049 ignoreResultAssign =
false;
1051 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1052 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1053 if (!promotionType.
isNull())
1054 result.fullType = promotionType;
1056 result.fullType = e->
getType();
1057 result.compType = result.fullType;
1058 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1059 result.compType = vecType->getElementType();
1063 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1068 mlir::Value emitMul(
const BinOpInfo &ops);
1069 mlir::Value emitDiv(
const BinOpInfo &ops);
1070 mlir::Value emitRem(
const BinOpInfo &ops);
1071 mlir::Value emitAdd(
const BinOpInfo &ops);
1072 mlir::Value emitSub(
const BinOpInfo &ops);
1073 mlir::Value emitShl(
const BinOpInfo &ops);
1074 mlir::Value emitShr(
const BinOpInfo &ops);
1075 mlir::Value emitAnd(
const BinOpInfo &ops);
1076 mlir::Value emitXor(
const BinOpInfo &ops);
1077 mlir::Value emitOr(
const BinOpInfo &ops);
1079 LValue emitCompoundAssignLValue(
1080 const CompoundAssignOperator *e,
1081 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1082 mlir::Value &result);
1084 emitCompoundAssign(
const CompoundAssignOperator *e,
1085 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1089 QualType getPromotionType(QualType ty) {
1090 const clang::ASTContext &ctx = cgf.getContext();
1091 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1092 QualType elementTy = complexTy->getElementType();
1098 if (
auto *vt = ty->
getAs<VectorType>()) {
1099 unsigned numElements = vt->getNumElements();
1102 return cgf.getContext().FloatTy;
1109#define HANDLEBINOP(OP) \
1110 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1111 QualType promotionTy = getPromotionType(e->getType()); \
1112 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1113 if (result && !promotionTy.isNull()) \
1114 result = emitUnPromotedValue(result, e->getType()); \
1117 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1118 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1134 ignoreResultAssign =
false;
1140 auto clangCmpToCIRCmp =
1144 return cir::CmpOpKind::lt;
1146 return cir::CmpOpKind::gt;
1148 return cir::CmpOpKind::le;
1150 return cir::CmpOpKind::ge;
1152 return cir::CmpOpKind::eq;
1154 return cir::CmpOpKind::ne;
1156 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1168 BinOpInfo boInfo = emitBinOps(e);
1169 mlir::Value lhs = boInfo.lhs;
1170 mlir::Value rhs = boInfo.rhs;
1180 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1182 boInfo.lhs, boInfo.rhs);
1184 }
else if (boInfo.isFixedPointOp()) {
1187 result = builder.
getBool(
false, loc);
1191 mlir::isa<cir::PointerType>(lhs.getType()) &&
1192 mlir::isa<cir::PointerType>(rhs.getType())) {
1193 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1199 "Complex Comparison: can only be an equality comparison");
1205 mlir::Value lhsReal = Visit(e->
getLHS());
1206 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1214 mlir::Value rhsReal = Visit(e->
getRHS());
1215 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1227#define VISITCOMP(CODE) \
1228 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1238 const bool ignore = std::exchange(ignoreResultAssign,
false);
1253 rhs = Visit(e->
getRHS());
1263 if (lhs.isBitField()) {
1285 if (!lhs.isVolatile())
1289 return emitLoadOfLValue(lhs, e->
getExprLoc());
1292 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1293 cgf.emitIgnoredExpr(e->
getLHS());
1295 return Visit(e->
getRHS());
1298 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1300 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1302 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1304 mlir::Value lhs = Visit(e->
getLHS());
1305 mlir::Value rhs = Visit(e->
getRHS());
1307 auto cmpOpKind = cir::CmpOpKind::ne;
1308 mlir::Type resTy = cgf.convertType(e->
getType());
1309 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1310 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1311 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1312 return builder.createIntCast(vecOr, resTy);
1316 mlir::Type resTy = cgf.convertType(e->
getType());
1317 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1319 CIRGenFunction::ConditionalEvaluation eval(cgf);
1321 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1322 auto resOp = cir::TernaryOp::create(
1323 builder, loc, lhsCondV,
1324 [&](mlir::OpBuilder &b, mlir::Location loc) {
1325 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1326 b.getInsertionBlock()};
1327 cgf.curLexScope->setAsTernary();
1328 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1330 cir::YieldOp::create(b, loc, res);
1333 [&](mlir::OpBuilder &b, mlir::Location loc) {
1334 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1335 b.getInsertionBlock()};
1337 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1338 cir::YieldOp::create(b, loc, res.getRes());
1340 return maybePromoteBoolResult(resOp.getResult(), resTy);
1343 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1345 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1347 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1349 mlir::Value lhs = Visit(e->
getLHS());
1350 mlir::Value rhs = Visit(e->
getRHS());
1352 auto cmpOpKind = cir::CmpOpKind::ne;
1353 mlir::Type resTy = cgf.convertType(e->
getType());
1354 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1355 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1356 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1357 return builder.createIntCast(vecOr, resTy);
1361 mlir::Type resTy = cgf.convertType(e->
getType());
1362 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1364 CIRGenFunction::ConditionalEvaluation eval(cgf);
1366 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1367 auto resOp = cir::TernaryOp::create(
1368 builder, loc, lhsCondV,
1369 [&](mlir::OpBuilder &b, mlir::Location loc) {
1370 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1371 b.getInsertionBlock()};
1373 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1374 cir::YieldOp::create(b, loc, res.getRes());
1377 [&](mlir::OpBuilder &b, mlir::Location loc) {
1378 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1379 b.getInsertionBlock()};
1381 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1383 cir::YieldOp::create(b, loc, res);
1386 return maybePromoteBoolResult(resOp.getResult(), resTy);
1389 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1390 return emitLoadOfLValue(e);
1393 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1394 return emitLoadOfLValue(e);
1398 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1399 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1403 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1407 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1409 "ScalarExprEmitter: objc string literal");
1412 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1413 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1416 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1418 "ScalarExprEmitter: objc array literal");
1421 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1423 "ScalarExprEmitter: objc dictionary literal");
1427 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1428 mlir::Value src,
unsigned numElementsDst) {
1429 static constexpr int64_t mask[] = {0, 1, 2, -1};
1430 return builder.createVecShuffle(
1431 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1453 mlir::Type srcTy = src.getType();
1457 return builder.createBitcast(src, dstTy);
1462 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1470 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1474 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1481 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1485 return builder.createIntToPtr(src, dstTy);
1488 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1489 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1490 mlir::Type srcTy = src.getType();
1491 mlir::Type dstTy = cgf.convertType(e->
getType());
1503 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1509 if (numElementsSrc == 3 && numElementsDst != 3) {
1511 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1512 "numElemsDst != 3");
1519 if (numElementsSrc != 3 && numElementsDst == 3) {
1520 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1522 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1524 src = convertVec3AndVec4(builder, loc, src, 3);
1531 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1532 return cgf.emitAtomicExpr(e).getValue();
1536LValue ScalarExprEmitter::emitCompoundAssignLValue(
1538 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1539 mlir::Value &result) {
1550 if (promotionTypeCR.
isNull())
1554 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1556 if (!promotionTypeRHS.
isNull())
1559 opInfo.rhs = Visit(e->
getRHS());
1561 opInfo.fullType = promotionTypeCR;
1562 opInfo.compType = opInfo.fullType;
1563 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1564 opInfo.compType = vecType->getElementType();
1573 if (lhsTy->
getAs<AtomicType>()) {
1574 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1578 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1580 CIRGenFunction::SourceLocRAIIObject sourceloc{
1583 if (!promotionTypeLHS.
isNull())
1584 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1586 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1590 result = (this->*func)(opInfo);
1594 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1595 ScalarConversionOpts(cgf.
sanOpts));
1601 if (lhsLV.isBitField())
1612mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1616 cir::CastKind castOpKind;
1618 case CK_FloatingComplexToReal:
1619 castOpKind = cir::CastKind::float_complex_to_real;
1621 case CK_IntegralComplexToReal:
1622 castOpKind = cir::CastKind::int_complex_to_real;
1624 case CK_FloatingComplexToBoolean:
1625 castOpKind = cir::CastKind::float_complex_to_bool;
1627 case CK_IntegralComplexToBoolean:
1628 castOpKind = cir::CastKind::int_complex_to_bool;
1631 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1637mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1638 QualType promotionType) {
1640 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1641 switch (bo->getOpcode()) {
1642#define HANDLE_BINOP(OP) \
1644 return emit##OP(emitBinOps(bo, promotionType));
1653 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1654 switch (uo->getOpcode()) {
1657 return VisitRealImag(uo, promotionType);
1659 return VisitUnaryMinus(uo, promotionType);
1661 return VisitUnaryPlus(uo, promotionType);
1666 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1668 if (!promotionType.
isNull())
1669 return emitPromotedValue(result, promotionType);
1670 return emitUnPromotedValue(result, e->
getType());
1675mlir::Value ScalarExprEmitter::emitCompoundAssign(
1676 const CompoundAssignOperator *e,
1677 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1679 bool ignore = std::exchange(ignoreResultAssign,
false);
1681 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1692 if (!lhs.isVolatile())
1696 return emitLoadOfLValue(lhs, e->
getExprLoc());
1699mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1700 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1715#define COMPOUND_OP(Op) \
1716 case BO_##Op##Assign: \
1717 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1754 llvm_unreachable(
"Not valid compound assignment operators");
1756 llvm_unreachable(
"Unhandled compound assignment operator");
1761 bool ignoreResultAssign) {
1763 "Invalid scalar expression to emit");
1766 .Visit(
const_cast<Expr *
>(e));
1771 if (!promotionType.
isNull())
1786static std::optional<QualType>
1790 return std::nullopt;
1795 return std::nullopt;
1808 const BinOpInfo &op) {
1810 "Expected a unary or binary operator");
1814 if (!op.mayHaveIntegerOverflow())
1818 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1819 return !uo->canOverflow();
1824 std::optional<QualType> optionalLHSTy =
1829 std::optional<QualType> optionalRHSTy =
1839 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1846 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1847 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1852 const BinOpInfo &op,
1853 bool isSubtraction) {
1858 mlir::Value pointer = op.lhs;
1859 Expr *pointerOperand =
expr->getLHS();
1860 mlir::Value
index = op.rhs;
1861 Expr *indexOperand =
expr->getRHS();
1867 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1868 std::swap(pointer,
index);
1869 std::swap(pointerOperand, indexOperand);
1871 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1872 "Need a pointer operand");
1873 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1908 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1918 numElements.getType());
1929 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1934 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1936 pointer.getType(), pointer,
index);
1940 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1941 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1944mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1945 const mlir::Location loc = cgf.
getLoc(ops.loc);
1948 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1949 case LangOptions::SOB_Defined:
1950 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1951 return builder.
createMul(loc, ops.lhs, ops.rhs);
1953 case LangOptions::SOB_Undefined:
1954 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1957 case LangOptions::SOB_Trapping:
1969 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1971 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1973 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1974 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1975 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1978 if (ops.isFixedPointOp()) {
1984 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1987mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1988 const mlir::Location loc = cgf.
getLoc(ops.loc);
1989 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1990 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1991 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
1993 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
1996mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1997 const mlir::Location loc = cgf.
getLoc(ops.loc);
1998 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1999 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2000 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2002 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2006mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2007 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2008 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2012 const mlir::Location loc = cgf.
getLoc(ops.loc);
2015 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2016 case LangOptions::SOB_Defined:
2017 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2018 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2020 case LangOptions::SOB_Undefined:
2021 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2024 case LangOptions::SOB_Trapping:
2037 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2039 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2041 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2042 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2043 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2046 if (ops.isFixedPointOp()) {
2052 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2055mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2056 const mlir::Location loc = cgf.
getLoc(ops.loc);
2058 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2061 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2062 case LangOptions::SOB_Defined: {
2063 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2064 return builder.
createSub(loc, ops.lhs, ops.rhs);
2067 case LangOptions::SOB_Undefined:
2068 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2071 case LangOptions::SOB_Trapping:
2085 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2087 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2089 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2090 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2091 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2094 if (ops.isFixedPointOp()) {
2100 return builder.
createSub(loc, ops.lhs, ops.rhs);
2105 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2117 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2121mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2123 if (ops.isFixedPointOp()) {
2133 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2137 bool sanitizeUnsignedBase =
2138 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2140 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2141 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2146 else if ((sanitizeBase || sanitizeExponent) &&
2147 mlir::isa<cir::IntType>(ops.lhs.getType()))
2153mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2155 if (ops.isFixedPointOp()) {
2168 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2169 mlir::isa<cir::IntType>(ops.lhs.getType()))
2177mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2178 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2180mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2181 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2183mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2184 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2191mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2193 QualType destTy = ce->
getType();
2198 ignoreResultAssign =
false;
2201 case clang::CK_Dependent:
2202 llvm_unreachable(
"dependent cast kind in CIR gen!");
2203 case clang::CK_BuiltinFnToFnPtr:
2204 llvm_unreachable(
"builtin functions are handled elsewhere");
2205 case CK_LValueBitCast:
2206 case CK_LValueToRValueBitCast: {
2208 Address sourceAddr = sourceLVal.getAddress();
2214 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2217 case CK_CPointerToObjCPointerCast:
2218 case CK_BlockPointerToObjCPointerCast:
2219 case CK_AnyPointerToBlockPointerCast:
2221 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2226 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2228 "sanitizer support");
2232 "strict vtable pointers");
2258 case CK_AddressSpaceConversion: {
2259 Expr::EvalResult result;
2273 case CK_AtomicToNonAtomic:
2274 case CK_NonAtomicToAtomic:
2275 case CK_UserDefinedConversion:
2276 return Visit(
const_cast<Expr *
>(subExpr));
2280 case CK_IntegralToPointer: {
2282 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2291 : cir::CastKind::integral,
2296 "IntegralToPointer: strict vtable pointers");
2303 case CK_BaseToDerived: {
2305 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2317 case CK_UncheckedDerivedToBase:
2318 case CK_DerivedToBase: {
2329 case CK_ArrayToPointerDecay:
2332 case CK_NullToPointer: {
2342 case CK_NullToMemberPointer: {
2348 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2354 case CK_ReinterpretMemberPointer: {
2355 mlir::Value src = Visit(subExpr);
2359 case CK_BaseToDerivedMemberPointer:
2360 case CK_DerivedToBaseMemberPointer: {
2361 mlir::Value src = Visit(subExpr);
2365 QualType derivedTy =
2366 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2367 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2368 NestedNameSpecifier qualifier = mpType->getQualifier();
2369 assert(qualifier &&
"member pointer without class qualifier");
2370 const Type *qualifierType = qualifier.getAsType();
2371 assert(qualifierType &&
"member pointer qualifier is not a type");
2378 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2381 if (
kind == CK_BaseToDerivedMemberPointer)
2382 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2384 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2387 if (
kind == CK_BaseToDerivedMemberPointer)
2388 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2390 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2394 case CK_LValueToRValue:
2396 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2397 return Visit(
const_cast<Expr *
>(subExpr));
2399 case CK_IntegralCast: {
2400 ScalarConversionOpts opts;
2401 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2402 if (!ice->isPartOfExplicitCast())
2403 opts = ScalarConversionOpts(cgf.
sanOpts);
2405 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2409 case CK_FloatingComplexToReal:
2410 case CK_IntegralComplexToReal:
2411 case CK_FloatingComplexToBoolean:
2412 case CK_IntegralComplexToBoolean: {
2418 case CK_FloatingRealToComplex:
2419 case CK_FloatingComplexCast:
2420 case CK_IntegralRealToComplex:
2421 case CK_IntegralComplexCast:
2422 case CK_IntegralComplexToFloatingComplex:
2423 case CK_FloatingComplexToIntegralComplex:
2424 llvm_unreachable(
"scalar cast to non-scalar value");
2426 case CK_PointerToIntegral: {
2427 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2430 "strict vtable pointers");
2437 case CK_IntegralToFloating:
2438 case CK_FloatingToIntegral:
2439 case CK_FloatingCast:
2440 case CK_FixedPointToFloating:
2441 case CK_FloatingToFixedPoint: {
2442 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2444 "fixed point casts");
2447 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2448 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2452 case CK_IntegralToBoolean:
2453 return emitIntToBoolConversion(Visit(subExpr),
2456 case CK_PointerToBoolean:
2457 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2458 case CK_FloatingToBoolean:
2459 return emitFloatToBoolConversion(Visit(subExpr),
2461 case CK_MemberPointerToBoolean: {
2462 mlir::Value memPtr = Visit(subExpr);
2464 cir::CastKind::member_ptr_to_bool, memPtr,
2468 case CK_VectorSplat: {
2470 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2471 return cir::VecSplatOp::create(builder,
2475 case CK_FunctionToPointerDecay:
2485mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2487 return emitLoadOfLValue(e);
2494mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2499 Expr::EvalResult result;
2501 llvm::APSInt value = result.
Val.
getInt();
2511 return builder.
getBool(value.getBoolValue(), loc);
2514 return emitLoadOfLValue(e);
2517mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2518 const unsigned numInitElements = e->
getNumInits();
2520 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2521 assert((ignore ==
false ||
2523 "init list ignored");
2531 const auto vectorType =
2534 SmallVector<mlir::Value, 16> elements;
2535 for (Expr *init : e->
inits()) {
2536 elements.push_back(Visit(init));
2540 if (numInitElements < vectorType.getSize()) {
2543 std::fill_n(std::back_inserter(elements),
2544 vectorType.getSize() - numInitElements, zeroValue);
2547 return cir::VecCreateOp::create(cgf.
getBuilder(),
2553 if (numInitElements == 0)
2564 "Invalid scalar expression to emit");
2566 .emitScalarConversion(src, srcTy, dstTy, loc);
2574 "Invalid complex -> scalar conversion");
2579 ? cir::CastKind::float_complex_to_bool
2580 : cir::CastKind::int_complex_to_bool;
2585 ? cir::CastKind::float_complex_to_real
2586 : cir::CastKind::int_complex_to_real;
2592mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2599 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2601 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2602 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2616mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2621 llvm::APSInt value = evalResult.
Val.
getInt();
2627 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2631mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2633 mlir::Value result = VisitRealImag(e, promotionTy);
2634 if (result && !promotionTy.
isNull())
2635 result = emitUnPromotedValue(result, e->
getType());
2639mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2641 mlir::Value result = VisitRealImag(e, promotionTy);
2642 if (result && !promotionTy.
isNull())
2643 result = emitUnPromotedValue(result, e->
getType());
2647mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2648 QualType promotionTy) {
2651 "Invalid UnaryOp kind for ComplexType Real or Imag");
2673 mlir::Value operand = promotionTy.
isNull()
2675 : cgf.emitPromotedScalarExpr(op, promotionTy);
2681 mlir::Value operand;
2684 operand = cir::LoadOp::create(builder, loc, operand);
2685 }
else if (!promotionTy.
isNull()) {
2695mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2696 const UnaryExprOrTypeTraitExpr *e) {
2700 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2701 if (
const VariableArrayType *vat =
2706 bool evaluateExtent =
true;
2707 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2709 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2712 if (evaluateExtent) {
2723 if (
kind == UETT_CountOf)
2728 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2729 mlir::Value numElts = vlaSize.
numElts;
2733 if (!eltSize.
isOne()) {
2735 mlir::Value eltSizeValue =
2738 return builder.
createMul(loc, eltSizeValue, numElts,
2745 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2752 }
else if (e->
getKind() == UETT_VectorElements) {
2754 if (vecTy.getIsScalable()) {
2757 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2764 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getSize()));
2791mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2792 const AbstractConditionalOperator *e) {
2795 ignoreResultAssign =
false;
2798 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2800 Expr *condExpr = e->
getCond();
2808 Expr *live = lhsExpr, *dead = rhsExpr;
2810 std::swap(live, dead);
2816 mlir::Value result = Visit(live);
2823 loc, cir::PoisonAttr::get(builder.getContext(),
2831 QualType condType = condExpr->
getType();
2840 mlir::Value lhsValue = Visit(lhsExpr);
2841 mlir::Value rhsValue = Visit(rhsExpr);
2843 mlir::Type vecTy = convertType(condType);
2844 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
2845 auto testMSB = cir::VecCmpOp::create(
2846 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2848 mlir::Value tmp2 = builder.
createNot(tmp);
2851 mlir::Value rhsTmp = rhsValue;
2852 mlir::Value lhsTmp = lhsValue;
2853 bool wasCast =
false;
2855 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2861 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
2862 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
2863 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
2872 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2876 mlir::Value condValue = Visit(condExpr);
2877 mlir::Value lhsValue = Visit(lhsExpr);
2878 mlir::Value rhsValue = Visit(rhsExpr);
2879 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2888 bool lhsIsVoid =
false;
2892 mlir::Value lhs = Visit(lhsExpr);
2898 mlir::Value rhs = Visit(rhsExpr);
2900 assert(!rhs &&
"lhs and rhs types must match");
2908 CIRGenFunction::ConditionalEvaluation eval(cgf);
2909 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2910 mlir::Type yieldTy{};
2912 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
2913 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2920 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
2922 eval.beginEvaluation();
2923 branch = Visit(
expr);
2924 eval.endEvaluation();
2925 branchCleanups.forceCleanup({&branch});
2929 yieldTy = branch.getType();
2930 cir::YieldOp::create(b, loc, branch);
2934 insertPoints.push_back(b.saveInsertionPoint());
2938 mlir::Value result = cir::TernaryOp::create(
2939 builder, loc, condV,
2941 [&](mlir::OpBuilder &b, mlir::Location loc) {
2942 emitBranch(b, loc, lhsExpr);
2945 [&](mlir::OpBuilder &b, mlir::Location loc) {
2946 emitBranch(b, loc, rhsExpr);
2950 if (!insertPoints.empty()) {
2956 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2957 mlir::OpBuilder::InsertionGuard guard(builder);
2958 builder.restoreInsertionPoint(toInsert);
2961 if (mlir::isa<cir::VoidType>(yieldTy)) {
2962 cir::YieldOp::create(builder, loc);
2965 cir::YieldOp::create(builder, loc, op0);
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 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.
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 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)
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)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
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 createComplexCreate(mlir::Location loc, mlir::Value real, mlir::Value imag)
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.
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
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...
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
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.
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)
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.
The JSON file list parser is used to communicate input to InstallAPI.
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 fixedPointType()
static bool vecTernaryOp()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
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.