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 cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
215 if (!resolvedLabel) {
216 cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
219 cgf.cgm.mapResolvedBlockAddress(blockAddressOp,
nullptr);
221 cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
223 cgf.instantiateIndirectGotoBlock();
224 return blockAddressOp;
227 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
229 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
233 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
235 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
239 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
241 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
242 "expect floating-point type");
243 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
247 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
248 mlir::Type ty = cgf.convertType(e->
getType());
251 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
252 llvm::APInt apValue(intTy.getWidth(), e->
getValue(),
254 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
255 cir::IntAttr::get(ty, apValue));
258 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
262 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
269 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
273 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
275 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
276 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
279 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
280 return cgf.emitPseudoObjectRValue(e).getValue();
282 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
284 "ScalarExprEmitter: sycl unique stable name");
287 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
289 auto it = e->
begin();
290 llvm::APInt value = (*it)->getValue();
291 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
294 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
296 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
300 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
303 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
304 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
307 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
308 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
311 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
312 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
315 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
316 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
319 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
320 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
323 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
325 "ScalarExprEmitter: objc availability check");
329 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
331 "ScalarExprEmitter: matrix subscript");
335 mlir::Value VisitCastExpr(
CastExpr *e);
336 mlir::Value VisitCallExpr(
const CallExpr *e);
338 mlir::Value VisitStmtExpr(StmtExpr *e) {
339 CIRGenFunction::StmtExprEvaluation eval(cgf);
347 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
349 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
353 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
354 ignoreResultAssign =
false;
360 const mlir::Value vecValue = Visit(e->
getBase());
361 const mlir::Value indexValue = Visit(e->
getIdx());
362 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
365 return emitLoadOfLValue(e);
368 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
371 mlir::Value inputVec = Visit(e->
getExpr(0));
372 mlir::Value indexVec = Visit(e->
getExpr(1));
373 return cir::VecShuffleDynamicOp::create(
374 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
377 mlir::Value vec1 = Visit(e->
getExpr(0));
378 mlir::Value vec2 = Visit(e->
getExpr(1));
383 SmallVector<mlir::Attribute, 8> indices;
386 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
392 return cir::VecShuffleOp::create(cgf.builder,
394 cgf.convertType(e->
getType()), vec1, vec2,
395 cgf.builder.getArrayAttr(indices));
398 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
401 return emitScalarConversion(Visit(e->
getSrcExpr()),
406 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
408 mlir::Value VisitMatrixElementExpr(Expr *e) {
409 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
413 mlir::Value VisitMemberExpr(MemberExpr *e);
415 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
416 return emitLoadOfLValue(e);
419 mlir::Value VisitInitListExpr(InitListExpr *e);
421 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
422 assert(cgf.getArrayInitIndex() &&
423 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
424 return cgf.getArrayInitIndex();
427 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
431 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
432 return VisitCastExpr(e);
435 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
436 return cgf.cgm.emitNullConstant(e->
getType(),
441 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
444 return cgf.getBuilder().createPtrToBoolCast(v);
447 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
448 cir::BoolType boolTy = builder.getBoolTy();
449 return cir::CastOp::create(builder, loc, boolTy,
450 cir::CastKind::float_to_bool, src);
453 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
459 cir::BoolType boolTy = builder.getBoolTy();
460 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
466 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
467 mlir::Location loc) {
468 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
471 return emitFloatToBoolConversion(src, loc);
473 if (llvm::isa<MemberPointerType>(srcType)) {
474 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
475 return builder.getFalse(loc);
479 return emitIntToBoolConversion(src, loc);
481 assert(::mlir::isa<cir::PointerType>(src.getType()));
482 return emitPointerToBoolConversion(src, srcType);
487 struct ScalarConversionOpts {
488 bool treatBooleanAsSigned;
489 bool emitImplicitIntegerTruncationChecks;
490 bool emitImplicitIntegerSignChangeChecks;
492 ScalarConversionOpts()
493 : treatBooleanAsSigned(
false),
494 emitImplicitIntegerTruncationChecks(
false),
495 emitImplicitIntegerSignChangeChecks(
false) {}
497 ScalarConversionOpts(clang::SanitizerSet sanOpts)
498 : treatBooleanAsSigned(
false),
499 emitImplicitIntegerTruncationChecks(
500 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
501 emitImplicitIntegerSignChangeChecks(
502 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
509 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
510 QualType dstType, mlir::Type srcTy,
511 mlir::Type dstTy, ScalarConversionOpts opts) {
513 "Internal error: matrix types not handled by this function.");
514 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
515 mlir::isa<mlir::IntegerType>(dstTy)) &&
516 "Obsolete code. Don't use mlir::IntegerType with CIR.");
518 mlir::Type fullDstTy = dstTy;
519 if (mlir::isa<cir::VectorType>(srcTy) &&
520 mlir::isa<cir::VectorType>(dstTy)) {
522 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
523 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
526 std::optional<cir::CastKind> castKind;
528 if (mlir::isa<cir::BoolType>(srcTy)) {
529 if (opts.treatBooleanAsSigned)
530 cgf.getCIRGenModule().errorNYI(
"signed bool");
531 if (cgf.getBuilder().isInt(dstTy))
532 castKind = cir::CastKind::bool_to_int;
533 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
534 castKind = cir::CastKind::bool_to_float;
536 llvm_unreachable(
"Internal error: Cast to unexpected type");
537 }
else if (cgf.getBuilder().isInt(srcTy)) {
538 if (cgf.getBuilder().isInt(dstTy))
539 castKind = cir::CastKind::integral;
540 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
541 castKind = cir::CastKind::int_to_float;
542 else if (mlir::isa<cir::BoolType>(dstTy))
543 castKind = cir::CastKind::int_to_bool;
545 llvm_unreachable(
"Internal error: Cast to unexpected type");
546 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
547 if (cgf.getBuilder().isInt(dstTy)) {
551 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
552 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
554 castKind = cir::CastKind::float_to_int;
555 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
557 return builder.createFloatingCast(src, fullDstTy);
558 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
559 castKind = cir::CastKind::float_to_bool;
561 llvm_unreachable(
"Internal error: Cast to unexpected type");
564 llvm_unreachable(
"Internal error: Cast from unexpected type");
567 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
568 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
573 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
577 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
582 "variably modified types in varargs");
585 return cgf.emitVAArg(ve);
588 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
592 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
594 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
597 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
599 return emitScalarPrePostIncDec(e, lv);
601 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
602 return VisitUnaryPrePostIncDec(e);
604 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
605 return VisitUnaryPrePostIncDec(e);
607 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
608 return VisitUnaryPrePostIncDec(e);
610 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
611 return VisitUnaryPrePostIncDec(e);
613 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
614 if (cgf.getLangOpts().OpenMP)
622 if (
type->getAs<AtomicType>()) {
626 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
629 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
643 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
644 }
else if (
type->isIntegerType()) {
645 QualType promotedType;
646 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
647 if (cgf.getContext().isPromotableIntegerType(
type)) {
648 promotedType = cgf.getContext().getPromotedIntegerType(
type);
649 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
650 canPerformLossyDemotionCheck =
true;
651 canPerformLossyDemotionCheck &=
652 cgf.getContext().getCanonicalType(
type) !=
653 cgf.getContext().getCanonicalType(promotedType);
654 canPerformLossyDemotionCheck &=
661 (!canPerformLossyDemotionCheck ||
662 type->isSignedIntegerOrEnumerationType() ||
664 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
665 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
666 "The following check expects that if we do promotion to different "
667 "underlying canonical type, at least one of the types (either "
668 "base or promoted) will be signed, or the bitwidths will match.");
673 value = emitIncDecConsiderOverflowBehavior(e, value);
676 value = emitIncOrDec(e, input,
false);
678 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
679 QualType
type = ptr->getPointeeType();
680 if (
const VariableArrayType *vla =
681 cgf.getContext().getAsVariableArrayType(
type)) {
683 mlir::Value numElts = cgf.getVLASize(vla).numElts;
685 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
687 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
692 mlir::Value amt = builder.getSInt32(amount, loc);
694 value = builder.createPtrStride(loc, value, amt);
696 }
else if (
type->isVectorType()) {
697 if (
type->hasIntegerRepresentation()) {
698 value = emitIncOrDec(e, input,
false);
700 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec vector of float");
703 }
else if (
type->isRealFloatingType()) {
704 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
706 if (
type->isHalfType() &&
707 !cgf.getContext().getLangOpts().NativeHalfType) {
712 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
714 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
715 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
716 mlir::Value amount = builder.getConstFP(
717 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
718 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
719 : builder.createFSub(loc, value, amount);
721 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
724 }
else if (
type->isFixedPointType()) {
725 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
728 assert(
type->castAs<ObjCObjectPointerType>());
729 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
733 CIRGenFunction::SourceLocRAIIObject sourceloc{
738 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
740 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
744 return e->
isPrefix() ? value : input;
747 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
749 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
750 case LangOptions::SOB_Defined:
751 return emitIncOrDec(e, inVal,
false);
752 case LangOptions::SOB_Undefined:
754 return emitIncOrDec(e, inVal,
true);
755 case LangOptions::SOB_Trapping:
757 return emitIncOrDec(e, inVal,
true);
758 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
761 llvm_unreachable(
"Unexpected signed overflow behavior kind");
764 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
765 if (llvm::isa<MemberPointerType>(e->
getType()))
766 return cgf.cgm.emitMemberPointerConstant(e);
768 return cgf.emitLValue(e->
getSubExpr()).getPointer();
771 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
774 return emitLoadOfLValue(e);
777 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
779 mlir::Value result = VisitUnaryPlus(e, promotionType);
780 if (result && !promotionType.
isNull())
781 return emitUnPromotedValue(result, e->
getType());
785 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
786 ignoreResultAssign =
false;
787 if (!promotionType.
isNull())
788 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
792 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
794 mlir::Value result = VisitUnaryMinus(e, promotionType);
795 if (result && !promotionType.
isNull())
796 return emitUnPromotedValue(result, e->
getType());
800 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
801 ignoreResultAssign =
false;
803 if (!promotionType.
isNull())
804 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
810 if (cir::isFPOrVectorOfFPType(operand.getType()))
811 return builder.createOrFold<cir::FNegOp>(loc, operand);
817 cgf.getLangOpts().getSignedOverflowBehavior() !=
818 LangOptions::SOB_Defined;
820 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
823 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
827 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
828 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
831 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
832 ignoreResultAssign =
false;
834 return builder.createOrFold<cir::NotOp>(
838 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
840 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
841 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
842 mlir::Value VisitRealImag(
const UnaryOperator *e,
843 QualType promotionType = QualType());
845 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
850 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
852 "ScalarExprEmitter: materialize temporary");
855 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
856 ASTContext &ctx = cgf.getContext();
859 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
861 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
862 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
865 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
866 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
869 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
870 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
874 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
876 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
877 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
878 return cgf.emitCXXNewExpr(e);
880 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
881 cgf.emitCXXDeleteExpr(e);
884 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
890 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
895 "Expected int type for TypeTraitExpr");
896 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
902 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
908 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
910 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
913 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
916 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
918 "ScalarExprEmitter: cxx pseudo destructor");
921 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
922 cgf.emitCXXThrowExpr(e);
926 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
935 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
937 ScalarConversionOpts opts = ScalarConversionOpts()) {
947 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
953 if (srcType == dstType) {
954 if (opts.emitImplicitIntegerSignChangeChecks)
955 cgf.getCIRGenModule().errorNYI(loc,
956 "implicit integer sign change checks");
963 mlir::Type mlirSrcType = src.getType();
968 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
970 mlir::Type mlirDstType = cgf.convertType(dstType);
973 !cgf.getContext().getLangOpts().NativeHalfType) {
975 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
976 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
977 cgf.getCIRGenModule().errorNYI(loc,
978 "cast via llvm.convert.from.fp16");
983 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
984 cgf.getCIRGenModule().errorNYI(loc,
985 "cast via llvm.convert.from.fp16");
988 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
990 srcType = cgf.getContext().FloatTy;
991 mlirSrcType = cgf.floatTy;
997 if (mlirSrcType == mlirDstType) {
998 if (opts.emitImplicitIntegerSignChangeChecks)
999 cgf.getCIRGenModule().errorNYI(loc,
1000 "implicit integer sign change checks");
1007 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1008 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1009 return builder.getNullPtr(dstPT, src.getLoc());
1015 return builder.createPtrToInt(src, mlirDstType);
1022 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1024 "Splatted expr doesn't match with vector element type?");
1026 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1031 cgf.getCIRGenModule().errorNYI(loc,
1032 "matrix type to matrix type conversion");
1036 "Internal error: conversion between matrix type and scalar type");
1039 mlir::Value res =
nullptr;
1040 mlir::Type resTy = mlirDstType;
1042 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1044 if (mlirDstType != resTy) {
1045 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1046 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1050 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1054 if (opts.emitImplicitIntegerTruncationChecks)
1055 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1057 if (opts.emitImplicitIntegerSignChangeChecks)
1058 cgf.getCIRGenModule().errorNYI(loc,
1059 "implicit integer sign change checks");
1064 BinOpInfo emitBinOps(
const BinaryOperator *e,
1065 QualType promotionType = QualType()) {
1066 ignoreResultAssign =
false;
1068 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1069 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1070 if (!promotionType.
isNull())
1071 result.fullType = promotionType;
1073 result.fullType = e->
getType();
1074 result.compType = result.fullType;
1075 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1076 result.compType = vecType->getElementType();
1080 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1085 mlir::Value emitMul(
const BinOpInfo &ops);
1086 mlir::Value emitDiv(
const BinOpInfo &ops);
1087 mlir::Value emitRem(
const BinOpInfo &ops);
1088 mlir::Value emitAdd(
const BinOpInfo &ops);
1089 mlir::Value emitSub(
const BinOpInfo &ops);
1090 mlir::Value emitShl(
const BinOpInfo &ops);
1091 mlir::Value emitShr(
const BinOpInfo &ops);
1092 mlir::Value emitAnd(
const BinOpInfo &ops);
1093 mlir::Value emitXor(
const BinOpInfo &ops);
1094 mlir::Value emitOr(
const BinOpInfo &ops);
1096 LValue emitCompoundAssignLValue(
1097 const CompoundAssignOperator *e,
1098 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1099 mlir::Value &result);
1101 emitCompoundAssign(
const CompoundAssignOperator *e,
1102 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1106 QualType getPromotionType(QualType ty) {
1107 const clang::ASTContext &ctx = cgf.getContext();
1108 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1109 QualType elementTy = complexTy->getElementType();
1115 if (
auto *vt = ty->
getAs<VectorType>()) {
1116 unsigned numElements = vt->getNumElements();
1119 return cgf.getContext().FloatTy;
1126#define HANDLEBINOP(OP) \
1127 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1128 QualType promotionTy = getPromotionType(e->getType()); \
1129 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1130 if (result && !promotionTy.isNull()) \
1131 result = emitUnPromotedValue(result, e->getType()); \
1134 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1135 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1151 ignoreResultAssign =
false;
1157 auto clangCmpToCIRCmp =
1161 return cir::CmpOpKind::lt;
1163 return cir::CmpOpKind::gt;
1165 return cir::CmpOpKind::le;
1167 return cir::CmpOpKind::ge;
1169 return cir::CmpOpKind::eq;
1171 return cir::CmpOpKind::ne;
1173 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1185 BinOpInfo boInfo = emitBinOps(e);
1186 mlir::Value lhs = boInfo.lhs;
1187 mlir::Value rhs = boInfo.rhs;
1197 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1199 boInfo.lhs, boInfo.rhs);
1201 }
else if (boInfo.isFixedPointOp()) {
1204 result = builder.
getBool(
false, loc);
1208 mlir::isa<cir::PointerType>(lhs.getType()) &&
1209 mlir::isa<cir::PointerType>(rhs.getType())) {
1210 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1216 "Complex Comparison: can only be an equality comparison");
1222 mlir::Value lhsReal = Visit(e->
getLHS());
1223 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1231 mlir::Value rhsReal = Visit(e->
getRHS());
1232 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1244#define VISITCOMP(CODE) \
1245 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1255 const bool ignore = std::exchange(ignoreResultAssign,
false);
1270 rhs = Visit(e->
getRHS());
1280 if (lhs.isBitField()) {
1302 if (!lhs.isVolatile())
1306 return emitLoadOfLValue(lhs, e->
getExprLoc());
1309 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1310 cgf.emitIgnoredExpr(e->
getLHS());
1312 return Visit(e->
getRHS());
1315 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1317 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1319 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1321 mlir::Value lhs = Visit(e->
getLHS());
1322 mlir::Value rhs = Visit(e->
getRHS());
1324 auto cmpOpKind = cir::CmpOpKind::ne;
1325 mlir::Type resTy = cgf.convertType(e->
getType());
1326 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1327 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1328 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1329 return builder.createIntCast(vecOr, resTy);
1333 mlir::Type resTy = cgf.convertType(e->
getType());
1334 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1336 CIRGenFunction::ConditionalEvaluation eval(cgf);
1338 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1339 auto resOp = cir::TernaryOp::create(
1340 builder, loc, lhsCondV,
1341 [&](mlir::OpBuilder &b, mlir::Location loc) {
1342 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1343 b.getInsertionBlock()};
1344 cgf.curLexScope->setAsTernary();
1345 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1347 cir::YieldOp::create(b, loc, res);
1350 [&](mlir::OpBuilder &b, mlir::Location loc) {
1351 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1352 b.getInsertionBlock()};
1354 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1355 cir::YieldOp::create(b, loc, res.getRes());
1357 return maybePromoteBoolResult(resOp.getResult(), resTy);
1360 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1362 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1364 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1366 mlir::Value lhs = Visit(e->
getLHS());
1367 mlir::Value rhs = Visit(e->
getRHS());
1369 auto cmpOpKind = cir::CmpOpKind::ne;
1370 mlir::Type resTy = cgf.convertType(e->
getType());
1371 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1372 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1373 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1374 return builder.createIntCast(vecOr, resTy);
1378 mlir::Type resTy = cgf.convertType(e->
getType());
1379 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1381 CIRGenFunction::ConditionalEvaluation eval(cgf);
1383 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1384 auto resOp = cir::TernaryOp::create(
1385 builder, loc, lhsCondV,
1386 [&](mlir::OpBuilder &b, mlir::Location loc) {
1387 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1388 b.getInsertionBlock()};
1390 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1391 cir::YieldOp::create(b, loc, res.getRes());
1394 [&](mlir::OpBuilder &b, mlir::Location loc) {
1395 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1396 b.getInsertionBlock()};
1398 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1400 cir::YieldOp::create(b, loc, res);
1403 return maybePromoteBoolResult(resOp.getResult(), resTy);
1406 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1407 return emitLoadOfLValue(e);
1410 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1411 return emitLoadOfLValue(e);
1415 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1416 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1420 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1424 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1426 "ScalarExprEmitter: objc string literal");
1429 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1430 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1433 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1435 "ScalarExprEmitter: objc array literal");
1438 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1440 "ScalarExprEmitter: objc dictionary literal");
1444 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1445 mlir::Value src,
unsigned numElementsDst) {
1446 static constexpr int64_t mask[] = {0, 1, 2, -1};
1447 return builder.createVecShuffle(
1448 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1470 mlir::Type srcTy = src.getType();
1474 return builder.createBitcast(src, dstTy);
1479 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1487 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1491 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1498 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1502 return builder.createIntToPtr(src, dstTy);
1505 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1506 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1507 mlir::Type srcTy = src.getType();
1508 mlir::Type dstTy = cgf.convertType(e->
getType());
1520 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1526 if (numElementsSrc == 3 && numElementsDst != 3) {
1528 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1529 "numElemsDst != 3");
1536 if (numElementsSrc != 3 && numElementsDst == 3) {
1537 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1539 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1541 src = convertVec3AndVec4(builder, loc, src, 3);
1548 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1549 return cgf.emitAtomicExpr(e).getValue();
1553LValue ScalarExprEmitter::emitCompoundAssignLValue(
1555 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1556 mlir::Value &result) {
1567 if (promotionTypeCR.
isNull())
1571 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1573 if (!promotionTypeRHS.
isNull())
1576 opInfo.rhs = Visit(e->
getRHS());
1578 opInfo.fullType = promotionTypeCR;
1579 opInfo.compType = opInfo.fullType;
1580 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1581 opInfo.compType = vecType->getElementType();
1590 if (lhsTy->
getAs<AtomicType>()) {
1591 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1595 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1597 CIRGenFunction::SourceLocRAIIObject sourceloc{
1600 if (!promotionTypeLHS.
isNull())
1601 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1603 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1607 result = (this->*func)(opInfo);
1611 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1612 ScalarConversionOpts(cgf.
sanOpts));
1618 if (lhsLV.isBitField())
1629mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1633 cir::CastKind castOpKind;
1635 case CK_FloatingComplexToReal:
1636 castOpKind = cir::CastKind::float_complex_to_real;
1638 case CK_IntegralComplexToReal:
1639 castOpKind = cir::CastKind::int_complex_to_real;
1641 case CK_FloatingComplexToBoolean:
1642 castOpKind = cir::CastKind::float_complex_to_bool;
1644 case CK_IntegralComplexToBoolean:
1645 castOpKind = cir::CastKind::int_complex_to_bool;
1648 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1654mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1655 QualType promotionType) {
1657 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1658 switch (bo->getOpcode()) {
1659#define HANDLE_BINOP(OP) \
1661 return emit##OP(emitBinOps(bo, promotionType));
1670 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1671 switch (uo->getOpcode()) {
1674 return VisitRealImag(uo, promotionType);
1676 return VisitUnaryMinus(uo, promotionType);
1678 return VisitUnaryPlus(uo, promotionType);
1683 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1685 if (!promotionType.
isNull())
1686 return emitPromotedValue(result, promotionType);
1687 return emitUnPromotedValue(result, e->
getType());
1692mlir::Value ScalarExprEmitter::emitCompoundAssign(
1693 const CompoundAssignOperator *e,
1694 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1696 bool ignore = std::exchange(ignoreResultAssign,
false);
1698 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1709 if (!lhs.isVolatile())
1713 return emitLoadOfLValue(lhs, e->
getExprLoc());
1716mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1717 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1732#define COMPOUND_OP(Op) \
1733 case BO_##Op##Assign: \
1734 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1771 llvm_unreachable(
"Not valid compound assignment operators");
1773 llvm_unreachable(
"Unhandled compound assignment operator");
1778 bool ignoreResultAssign) {
1780 "Invalid scalar expression to emit");
1783 .Visit(
const_cast<Expr *
>(e));
1788 if (!promotionType.
isNull())
1803static std::optional<QualType>
1807 return std::nullopt;
1812 return std::nullopt;
1825 const BinOpInfo &op) {
1827 "Expected a unary or binary operator");
1831 if (!op.mayHaveIntegerOverflow())
1835 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1836 return !uo->canOverflow();
1841 std::optional<QualType> optionalLHSTy =
1846 std::optional<QualType> optionalRHSTy =
1856 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1863 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1864 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1869 const BinOpInfo &op,
1870 bool isSubtraction) {
1875 mlir::Value pointer = op.lhs;
1876 Expr *pointerOperand =
expr->getLHS();
1877 mlir::Value
index = op.rhs;
1878 Expr *indexOperand =
expr->getRHS();
1884 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1885 std::swap(pointer,
index);
1886 std::swap(pointerOperand, indexOperand);
1888 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1889 "Need a pointer operand");
1890 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1925 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1935 numElements.getType());
1946 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1951 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1953 pointer.getType(), pointer,
index);
1957 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1958 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1961mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1962 const mlir::Location loc = cgf.
getLoc(ops.loc);
1965 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1966 case LangOptions::SOB_Defined:
1967 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1968 return builder.
createMul(loc, ops.lhs, ops.rhs);
1970 case LangOptions::SOB_Undefined:
1971 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1974 case LangOptions::SOB_Trapping:
1986 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1988 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1990 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1991 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1992 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1995 if (ops.isFixedPointOp()) {
2001 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2004mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2005 const mlir::Location loc = cgf.
getLoc(ops.loc);
2006 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2007 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2008 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2010 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2013mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2014 const mlir::Location loc = cgf.
getLoc(ops.loc);
2015 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2016 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2017 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2019 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2023mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2024 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2025 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2029 const mlir::Location loc = cgf.
getLoc(ops.loc);
2032 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2033 case LangOptions::SOB_Defined:
2034 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2035 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2037 case LangOptions::SOB_Undefined:
2038 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2041 case LangOptions::SOB_Trapping:
2054 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2056 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2058 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2059 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2060 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2063 if (ops.isFixedPointOp()) {
2069 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2072mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2073 const mlir::Location loc = cgf.
getLoc(ops.loc);
2075 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2078 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2079 case LangOptions::SOB_Defined: {
2080 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2081 return builder.
createSub(loc, ops.lhs, ops.rhs);
2084 case LangOptions::SOB_Undefined:
2085 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2088 case LangOptions::SOB_Trapping:
2102 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2104 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2106 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2107 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2108 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2111 if (ops.isFixedPointOp()) {
2117 return builder.
createSub(loc, ops.lhs, ops.rhs);
2122 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2134 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2138mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2140 if (ops.isFixedPointOp()) {
2150 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2154 bool sanitizeUnsignedBase =
2155 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2157 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2158 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2163 else if ((sanitizeBase || sanitizeExponent) &&
2164 mlir::isa<cir::IntType>(ops.lhs.getType()))
2170mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2172 if (ops.isFixedPointOp()) {
2185 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2186 mlir::isa<cir::IntType>(ops.lhs.getType()))
2194mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2195 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2197mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2198 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2200mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2201 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2208mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2210 QualType destTy = ce->
getType();
2215 ignoreResultAssign =
false;
2218 case clang::CK_Dependent:
2219 llvm_unreachable(
"dependent cast kind in CIR gen!");
2220 case clang::CK_BuiltinFnToFnPtr:
2221 llvm_unreachable(
"builtin functions are handled elsewhere");
2222 case CK_LValueBitCast:
2223 case CK_LValueToRValueBitCast: {
2225 Address sourceAddr = sourceLVal.getAddress();
2231 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2234 case CK_CPointerToObjCPointerCast:
2235 case CK_BlockPointerToObjCPointerCast:
2236 case CK_AnyPointerToBlockPointerCast:
2238 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2243 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2245 "sanitizer support");
2249 "strict vtable pointers");
2275 case CK_AddressSpaceConversion: {
2276 Expr::EvalResult result;
2290 case CK_AtomicToNonAtomic:
2291 case CK_NonAtomicToAtomic:
2292 case CK_UserDefinedConversion:
2293 return Visit(
const_cast<Expr *
>(subExpr));
2297 case CK_IntegralToPointer: {
2299 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2308 : cir::CastKind::integral,
2313 "IntegralToPointer: strict vtable pointers");
2320 case CK_BaseToDerived: {
2322 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2334 case CK_UncheckedDerivedToBase:
2335 case CK_DerivedToBase: {
2346 case CK_ArrayToPointerDecay:
2349 case CK_NullToPointer: {
2359 case CK_NullToMemberPointer: {
2365 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2371 case CK_ReinterpretMemberPointer: {
2372 mlir::Value src = Visit(subExpr);
2376 case CK_BaseToDerivedMemberPointer:
2377 case CK_DerivedToBaseMemberPointer: {
2378 mlir::Value src = Visit(subExpr);
2382 QualType derivedTy =
2383 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2384 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2385 NestedNameSpecifier qualifier = mpType->getQualifier();
2386 assert(qualifier &&
"member pointer without class qualifier");
2387 const Type *qualifierType = qualifier.getAsType();
2388 assert(qualifierType &&
"member pointer qualifier is not a type");
2395 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2398 if (
kind == CK_BaseToDerivedMemberPointer)
2399 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2401 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2404 if (
kind == CK_BaseToDerivedMemberPointer)
2405 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2407 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2411 case CK_LValueToRValue:
2413 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2414 return Visit(
const_cast<Expr *
>(subExpr));
2416 case CK_IntegralCast: {
2417 ScalarConversionOpts opts;
2418 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2419 if (!ice->isPartOfExplicitCast())
2420 opts = ScalarConversionOpts(cgf.
sanOpts);
2422 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2426 case CK_FloatingComplexToReal:
2427 case CK_IntegralComplexToReal:
2428 case CK_FloatingComplexToBoolean:
2429 case CK_IntegralComplexToBoolean: {
2435 case CK_FloatingRealToComplex:
2436 case CK_FloatingComplexCast:
2437 case CK_IntegralRealToComplex:
2438 case CK_IntegralComplexCast:
2439 case CK_IntegralComplexToFloatingComplex:
2440 case CK_FloatingComplexToIntegralComplex:
2441 llvm_unreachable(
"scalar cast to non-scalar value");
2443 case CK_PointerToIntegral: {
2444 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2447 "strict vtable pointers");
2454 case CK_IntegralToFloating:
2455 case CK_FloatingToIntegral:
2456 case CK_FloatingCast:
2457 case CK_FixedPointToFloating:
2458 case CK_FloatingToFixedPoint: {
2459 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2461 "fixed point casts");
2464 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2465 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2469 case CK_IntegralToBoolean:
2470 return emitIntToBoolConversion(Visit(subExpr),
2473 case CK_PointerToBoolean:
2474 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2475 case CK_FloatingToBoolean:
2476 return emitFloatToBoolConversion(Visit(subExpr),
2478 case CK_MemberPointerToBoolean: {
2479 mlir::Value memPtr = Visit(subExpr);
2481 cir::CastKind::member_ptr_to_bool, memPtr,
2485 case CK_VectorSplat: {
2487 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2488 return cir::VecSplatOp::create(builder,
2492 case CK_FunctionToPointerDecay:
2502mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2504 return emitLoadOfLValue(e);
2511mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2516 Expr::EvalResult result;
2518 llvm::APSInt value = result.
Val.
getInt();
2528 return builder.
getBool(value.getBoolValue(), loc);
2531 return emitLoadOfLValue(e);
2534mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2535 const unsigned numInitElements = e->
getNumInits();
2537 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2538 assert((ignore ==
false ||
2540 "init list ignored");
2548 const auto vectorType =
2551 SmallVector<mlir::Value, 16> elements;
2552 for (Expr *init : e->
inits()) {
2553 elements.push_back(Visit(init));
2557 if (numInitElements < vectorType.getSize()) {
2560 std::fill_n(std::back_inserter(elements),
2561 vectorType.getSize() - numInitElements, zeroValue);
2564 return cir::VecCreateOp::create(cgf.
getBuilder(),
2570 if (numInitElements == 0)
2581 "Invalid scalar expression to emit");
2583 .emitScalarConversion(src, srcTy, dstTy, loc);
2591 "Invalid complex -> scalar conversion");
2596 ? cir::CastKind::float_complex_to_bool
2597 : cir::CastKind::int_complex_to_bool;
2602 ? cir::CastKind::float_complex_to_real
2603 : cir::CastKind::int_complex_to_real;
2609mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2616 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2618 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2619 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2633mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2638 llvm::APSInt value = evalResult.
Val.
getInt();
2644 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2648mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2650 mlir::Value result = VisitRealImag(e, promotionTy);
2651 if (result && !promotionTy.
isNull())
2652 result = emitUnPromotedValue(result, e->
getType());
2656mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2658 mlir::Value result = VisitRealImag(e, promotionTy);
2659 if (result && !promotionTy.
isNull())
2660 result = emitUnPromotedValue(result, e->
getType());
2664mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2665 QualType promotionTy) {
2668 "Invalid UnaryOp kind for ComplexType Real or Imag");
2690 mlir::Value operand = promotionTy.
isNull()
2692 : cgf.emitPromotedScalarExpr(op, promotionTy);
2698 mlir::Value operand;
2701 operand = cir::LoadOp::create(builder, loc, operand);
2702 }
else if (!promotionTy.
isNull()) {
2712mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2713 const UnaryExprOrTypeTraitExpr *e) {
2717 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2718 if (
const VariableArrayType *vat =
2723 bool evaluateExtent =
true;
2724 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2726 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2729 if (evaluateExtent) {
2740 if (
kind == UETT_CountOf)
2745 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2746 mlir::Value numElts = vlaSize.
numElts;
2750 if (!eltSize.
isOne()) {
2752 mlir::Value eltSizeValue =
2755 return builder.
createMul(loc, eltSizeValue, numElts,
2762 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2769 }
else if (e->
getKind() == UETT_VectorElements) {
2771 if (vecTy.getIsScalable()) {
2774 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2781 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2806mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2807 const AbstractConditionalOperator *e) {
2810 ignoreResultAssign =
false;
2813 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2815 Expr *condExpr = e->
getCond();
2823 Expr *live = lhsExpr, *dead = rhsExpr;
2825 std::swap(live, dead);
2831 mlir::Value result = Visit(live);
2838 loc, cir::PoisonAttr::get(builder.getContext(),
2846 QualType condType = condExpr->
getType();
2855 mlir::Value lhsValue = Visit(lhsExpr);
2856 mlir::Value rhsValue = Visit(rhsExpr);
2858 mlir::Type vecTy = convertType(condType);
2859 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
2860 auto testMSB = cir::VecCmpOp::create(
2861 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2863 mlir::Value tmp2 = builder.
createNot(tmp);
2866 mlir::Value rhsTmp = rhsValue;
2867 mlir::Value lhsTmp = lhsValue;
2868 bool wasCast =
false;
2870 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2876 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
2877 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
2878 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
2887 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2891 mlir::Value condValue = Visit(condExpr);
2892 mlir::Value lhsValue = Visit(lhsExpr);
2893 mlir::Value rhsValue = Visit(rhsExpr);
2894 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2903 bool lhsIsVoid =
false;
2907 mlir::Value lhs = Visit(lhsExpr);
2913 mlir::Value rhs = Visit(rhsExpr);
2915 assert(!rhs &&
"lhs and rhs types must match");
2923 CIRGenFunction::ConditionalEvaluation eval(cgf);
2924 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2925 mlir::Type yieldTy{};
2927 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
2928 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2935 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
2937 eval.beginEvaluation();
2938 branch = Visit(
expr);
2939 eval.endEvaluation();
2940 branchCleanups.forceCleanup({&branch});
2944 yieldTy = branch.getType();
2945 cir::YieldOp::create(b, loc, branch);
2949 insertPoints.push_back(b.saveInsertionPoint());
2953 mlir::Value result = cir::TernaryOp::create(
2954 builder, loc, condV,
2956 [&](mlir::OpBuilder &b, mlir::Location loc) {
2957 emitBranch(b, loc, lhsExpr);
2960 [&](mlir::OpBuilder &b, mlir::Location loc) {
2961 emitBranch(b, loc, rhsExpr);
2965 if (!insertPoints.empty()) {
2971 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2972 mlir::OpBuilder::InsertionGuard guard(builder);
2973 builder.restoreInsertionPoint(toInsert);
2976 if (mlir::isa<cir::VoidType>(yieldTy)) {
2977 cir::YieldOp::create(builder, loc);
2980 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.