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(
213 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->
getSourceRange()),
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;
527 cir::FenvAttr fenvAttr;
529 if (mlir::isa<cir::BoolType>(srcTy)) {
530 if (opts.treatBooleanAsSigned)
531 cgf.getCIRGenModule().errorNYI(
"signed bool");
532 if (cgf.getBuilder().isInt(dstTy)) {
533 castKind = cir::CastKind::bool_to_int;
534 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
535 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
536 castKind = cir::CastKind::bool_to_float;
538 llvm_unreachable(
"Internal error: Cast to unexpected type");
540 }
else if (cgf.getBuilder().isInt(srcTy)) {
541 if (cgf.getBuilder().isInt(dstTy)) {
542 castKind = cir::CastKind::integral;
543 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
544 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
545 castKind = cir::CastKind::int_to_float;
546 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
547 castKind = cir::CastKind::int_to_bool;
549 llvm_unreachable(
"Internal error: Cast to unexpected type");
551 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
552 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
553 if (cgf.getBuilder().isInt(dstTy)) {
557 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
558 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
559 castKind = cir::CastKind::float_to_int;
560 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
562 return builder.createFloatingCast(src, fullDstTy);
563 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
564 castKind = cir::CastKind::float_to_bool;
566 llvm_unreachable(
"Internal error: Cast to unexpected type");
569 llvm_unreachable(
"Internal error: Cast from unexpected type");
572 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
573 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
578 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
582 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
587 "variably modified types in varargs");
590 return cgf.emitVAArg(ve);
593 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
597 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
599 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
602 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
604 return emitScalarPrePostIncDec(e, lv);
606 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
607 return VisitUnaryPrePostIncDec(e);
609 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
610 return VisitUnaryPrePostIncDec(e);
612 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
613 return VisitUnaryPrePostIncDec(e);
615 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
616 return VisitUnaryPrePostIncDec(e);
618 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
619 if (cgf.getLangOpts().OpenMP)
627 if (
type->getAs<AtomicType>()) {
631 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
634 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
648 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
649 }
else if (
type->isIntegerType()) {
650 QualType promotedType;
651 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
652 if (cgf.getContext().isPromotableIntegerType(
type)) {
653 promotedType = cgf.getContext().getPromotedIntegerType(
type);
654 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
655 canPerformLossyDemotionCheck =
true;
656 canPerformLossyDemotionCheck &=
657 cgf.getContext().getCanonicalType(
type) !=
658 cgf.getContext().getCanonicalType(promotedType);
659 canPerformLossyDemotionCheck &=
666 (!canPerformLossyDemotionCheck ||
667 type->isSignedIntegerOrEnumerationType() ||
669 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
670 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
671 "The following check expects that if we do promotion to different "
672 "underlying canonical type, at least one of the types (either "
673 "base or promoted) will be signed, or the bitwidths will match.");
678 value = emitIncDecConsiderOverflowBehavior(e, value);
681 value = emitIncOrDec(e, input,
false);
683 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
684 QualType
type = ptr->getPointeeType();
685 if (
const VariableArrayType *vla =
686 cgf.getContext().getAsVariableArrayType(
type)) {
688 mlir::Value numElts = cgf.getVLASize(vla).numElts;
690 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
692 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
697 mlir::Value amt = builder.getSInt32(amount, loc);
699 value = builder.createPtrStride(loc, value, amt);
701 }
else if (
type->isVectorType()) {
702 if (
type->hasIntegerRepresentation()) {
703 value = emitIncOrDec(e, input,
false);
705 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec vector of float");
708 }
else if (
type->isRealFloatingType()) {
709 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
711 if (
type->isHalfType() &&
712 !cgf.getContext().getLangOpts().NativeHalfType) {
717 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
719 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
720 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
721 mlir::Value amount = builder.getConstFP(
722 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
723 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
724 : builder.createFSub(loc, value, amount);
726 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
729 }
else if (
type->isFixedPointType()) {
730 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
733 assert(
type->castAs<ObjCObjectPointerType>());
734 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
738 CIRGenFunction::SourceLocRAIIObject sourceloc{
743 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
745 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
749 return e->
isPrefix() ? value : input;
752 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
754 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
755 case LangOptions::SOB_Defined:
756 return emitIncOrDec(e, inVal,
false);
757 case LangOptions::SOB_Undefined:
759 return emitIncOrDec(e, inVal,
true);
760 case LangOptions::SOB_Trapping:
762 return emitIncOrDec(e, inVal,
true);
763 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
766 llvm_unreachable(
"Unexpected signed overflow behavior kind");
769 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
770 if (llvm::isa<MemberPointerType>(e->
getType()))
771 return cgf.cgm.emitMemberPointerConstant(e);
773 return cgf.emitLValue(e->
getSubExpr()).getPointer();
776 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
779 return emitLoadOfLValue(e);
782 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
784 mlir::Value result = VisitUnaryPlus(e, promotionType);
785 if (result && !promotionType.
isNull())
786 return emitUnPromotedValue(result, e->
getType());
790 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
791 ignoreResultAssign =
false;
792 if (!promotionType.
isNull())
793 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
797 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
799 mlir::Value result = VisitUnaryMinus(e, promotionType);
800 if (result && !promotionType.
isNull())
801 return emitUnPromotedValue(result, e->
getType());
805 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
806 ignoreResultAssign =
false;
808 if (!promotionType.
isNull())
809 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
815 if (cir::isFPOrVectorOfFPType(operand.getType()))
816 return builder.createOrFold<cir::FNegOp>(loc, operand);
822 cgf.getLangOpts().getSignedOverflowBehavior() !=
823 LangOptions::SOB_Defined;
825 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
828 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
832 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
833 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
836 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
837 ignoreResultAssign =
false;
839 return builder.createOrFold<cir::NotOp>(
843 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
845 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
846 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
847 mlir::Value VisitRealImag(
const UnaryOperator *e,
848 QualType promotionType = QualType());
850 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
855 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
857 "ScalarExprEmitter: materialize temporary");
860 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
861 ASTContext &ctx = cgf.getContext();
864 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
866 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
867 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
870 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
871 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
874 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
875 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
879 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
881 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
882 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
883 return cgf.emitCXXNewExpr(e);
885 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
886 cgf.emitCXXDeleteExpr(e);
889 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
895 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
900 "Expected int type for TypeTraitExpr");
901 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
907 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
913 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
915 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
918 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
921 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
923 "ScalarExprEmitter: cxx pseudo destructor");
926 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
927 cgf.emitCXXThrowExpr(e);
931 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
940 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
942 ScalarConversionOpts opts = ScalarConversionOpts()) {
952 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
958 if (srcType == dstType) {
959 if (opts.emitImplicitIntegerSignChangeChecks)
960 cgf.getCIRGenModule().errorNYI(loc,
961 "implicit integer sign change checks");
968 mlir::Type mlirSrcType = src.getType();
973 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
975 mlir::Type mlirDstType = cgf.convertType(dstType);
978 !cgf.getContext().getLangOpts().NativeHalfType) {
980 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
984 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
986 srcType = cgf.getContext().FloatTy;
987 mlirSrcType = cgf.floatTy;
993 if (mlirSrcType == mlirDstType) {
994 if (opts.emitImplicitIntegerSignChangeChecks)
995 cgf.getCIRGenModule().errorNYI(loc,
996 "implicit integer sign change checks");
1003 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1004 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1005 return builder.getNullPtr(dstPT, src.getLoc());
1011 return builder.createPtrToInt(src, mlirDstType);
1018 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1020 "Splatted expr doesn't match with vector element type?");
1022 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1027 cgf.getCIRGenModule().errorNYI(loc,
1028 "matrix type to matrix type conversion");
1032 "Internal error: conversion between matrix type and scalar type");
1035 mlir::Value res =
nullptr;
1036 mlir::Type resTy = mlirDstType;
1038 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1040 if (mlirDstType != resTy) {
1041 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1045 if (opts.emitImplicitIntegerTruncationChecks)
1046 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1048 if (opts.emitImplicitIntegerSignChangeChecks)
1049 cgf.getCIRGenModule().errorNYI(loc,
1050 "implicit integer sign change checks");
1055 BinOpInfo emitBinOps(
const BinaryOperator *e,
1056 QualType promotionType = QualType()) {
1057 ignoreResultAssign =
false;
1059 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1060 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1061 if (!promotionType.
isNull())
1062 result.fullType = promotionType;
1064 result.fullType = e->
getType();
1065 result.compType = result.fullType;
1066 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1067 result.compType = vecType->getElementType();
1075 mlir::Value emitMul(
const BinOpInfo &ops);
1076 mlir::Value emitDiv(
const BinOpInfo &ops);
1077 mlir::Value emitRem(
const BinOpInfo &ops);
1078 mlir::Value emitAdd(
const BinOpInfo &ops);
1079 mlir::Value emitSub(
const BinOpInfo &ops);
1080 mlir::Value emitShl(
const BinOpInfo &ops);
1081 mlir::Value emitShr(
const BinOpInfo &ops);
1082 mlir::Value emitAnd(
const BinOpInfo &ops);
1083 mlir::Value emitXor(
const BinOpInfo &ops);
1084 mlir::Value emitOr(
const BinOpInfo &ops);
1086 LValue emitCompoundAssignLValue(
1087 const CompoundAssignOperator *e,
1088 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1089 mlir::Value &result);
1091 emitCompoundAssign(
const CompoundAssignOperator *e,
1092 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1096 QualType getPromotionType(QualType ty) {
1097 const clang::ASTContext &ctx = cgf.getContext();
1098 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1099 QualType elementTy = complexTy->getElementType();
1105 if (
auto *vt = ty->
getAs<VectorType>()) {
1106 unsigned numElements = vt->getNumElements();
1109 return cgf.getContext().FloatTy;
1116#define HANDLEBINOP(OP) \
1117 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1118 QualType promotionTy = getPromotionType(e->getType()); \
1119 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1120 if (result && !promotionTy.isNull()) \
1121 result = emitUnPromotedValue(result, e->getType()); \
1124 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1125 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1141 ignoreResultAssign =
false;
1147 auto clangCmpToCIRCmp =
1151 return cir::CmpOpKind::lt;
1153 return cir::CmpOpKind::gt;
1155 return cir::CmpOpKind::le;
1157 return cir::CmpOpKind::ge;
1159 return cir::CmpOpKind::eq;
1161 return cir::CmpOpKind::ne;
1163 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1175 BinOpInfo boInfo = emitBinOps(e);
1176 mlir::Value lhs = boInfo.lhs;
1177 mlir::Value rhs = boInfo.rhs;
1187 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1189 boInfo.lhs, boInfo.rhs);
1191 }
else if (boInfo.isFixedPointOp()) {
1194 result = builder.
getBool(
false, loc);
1198 mlir::isa<cir::PointerType>(lhs.getType()) &&
1199 mlir::isa<cir::PointerType>(rhs.getType())) {
1200 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1206 "Complex Comparison: can only be an equality comparison");
1212 mlir::Value lhsReal = Visit(e->
getLHS());
1213 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1221 mlir::Value rhsReal = Visit(e->
getRHS());
1222 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1234#define VISITCOMP(CODE) \
1235 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1245 const bool ignore = std::exchange(ignoreResultAssign,
false);
1260 rhs = Visit(e->
getRHS());
1270 if (lhs.isBitField()) {
1292 if (!lhs.isVolatile())
1296 return emitLoadOfLValue(lhs, e->
getExprLoc());
1299 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1300 cgf.emitIgnoredExpr(e->
getLHS());
1302 return Visit(e->
getRHS());
1305 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1307 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1309 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1311 mlir::Value lhs = Visit(e->
getLHS());
1312 mlir::Value rhs = Visit(e->
getRHS());
1314 auto cmpOpKind = cir::CmpOpKind::ne;
1315 mlir::Type resTy = cgf.convertType(e->
getType());
1316 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1317 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1318 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1319 return builder.createIntCast(vecOr, resTy);
1323 mlir::Type resTy = cgf.convertType(e->
getType());
1324 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1326 CIRGenFunction::ConditionalEvaluation eval(cgf);
1328 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1329 auto resOp = cir::TernaryOp::create(
1330 builder, loc, lhsCondV,
1331 [&](mlir::OpBuilder &b, mlir::Location loc) {
1332 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1333 b.getInsertionBlock()};
1334 cgf.curLexScope->setAsTernary();
1335 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1337 cir::YieldOp::create(b, loc, res);
1340 [&](mlir::OpBuilder &b, mlir::Location loc) {
1341 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1342 b.getInsertionBlock()};
1344 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1345 cir::YieldOp::create(b, loc, res.getRes());
1347 return maybePromoteBoolResult(resOp.getResult(), resTy);
1350 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1352 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1354 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1356 mlir::Value lhs = Visit(e->
getLHS());
1357 mlir::Value rhs = Visit(e->
getRHS());
1359 auto cmpOpKind = cir::CmpOpKind::ne;
1360 mlir::Type resTy = cgf.convertType(e->
getType());
1361 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1362 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1363 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1364 return builder.createIntCast(vecOr, resTy);
1368 mlir::Type resTy = cgf.convertType(e->
getType());
1369 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1371 CIRGenFunction::ConditionalEvaluation eval(cgf);
1373 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1374 auto resOp = cir::TernaryOp::create(
1375 builder, loc, lhsCondV,
1376 [&](mlir::OpBuilder &b, mlir::Location loc) {
1377 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1378 b.getInsertionBlock()};
1380 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1381 cir::YieldOp::create(b, loc, res.getRes());
1384 [&](mlir::OpBuilder &b, mlir::Location loc) {
1385 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1386 b.getInsertionBlock()};
1388 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1390 cir::YieldOp::create(b, loc, res);
1393 return maybePromoteBoolResult(resOp.getResult(), resTy);
1396 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1397 return emitLoadOfLValue(e);
1400 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1401 return emitLoadOfLValue(e);
1405 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1406 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1410 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1414 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1416 "ScalarExprEmitter: objc string literal");
1419 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1420 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1423 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1425 "ScalarExprEmitter: objc array literal");
1428 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1430 "ScalarExprEmitter: objc dictionary literal");
1434 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1435 mlir::Value src,
unsigned numElementsDst) {
1436 static constexpr int64_t mask[] = {0, 1, 2, -1};
1437 return builder.createVecShuffle(
1438 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1460 mlir::Type srcTy = src.getType();
1464 return builder.createBitcast(src, dstTy);
1469 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1477 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1481 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1488 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1492 return builder.createIntToPtr(src, dstTy);
1495 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1496 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1497 mlir::Type srcTy = src.getType();
1498 mlir::Type dstTy = cgf.convertType(e->
getType());
1510 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1516 if (numElementsSrc == 3 && numElementsDst != 3) {
1518 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1519 "numElemsDst != 3");
1526 if (numElementsSrc != 3 && numElementsDst == 3) {
1527 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1529 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1531 src = convertVec3AndVec4(builder, loc, src, 3);
1538 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1539 return cgf.emitAtomicExpr(e).getValue();
1543LValue ScalarExprEmitter::emitCompoundAssignLValue(
1545 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1546 mlir::Value &result) {
1557 if (promotionTypeCR.
isNull())
1561 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1563 if (!promotionTypeRHS.
isNull())
1566 opInfo.rhs = Visit(e->
getRHS());
1568 opInfo.fullType = promotionTypeCR;
1569 opInfo.compType = opInfo.fullType;
1570 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1571 opInfo.compType = vecType->getElementType();
1580 if (lhsTy->
getAs<AtomicType>()) {
1581 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1585 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1587 CIRGenFunction::SourceLocRAIIObject sourceloc{
1590 if (!promotionTypeLHS.
isNull())
1591 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1593 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1597 result = (this->*func)(opInfo);
1601 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1602 ScalarConversionOpts(cgf.
sanOpts));
1608 if (lhsLV.isBitField())
1619mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1623 cir::CastKind castOpKind;
1625 case CK_FloatingComplexToReal:
1626 castOpKind = cir::CastKind::float_complex_to_real;
1628 case CK_IntegralComplexToReal:
1629 castOpKind = cir::CastKind::int_complex_to_real;
1631 case CK_FloatingComplexToBoolean:
1632 castOpKind = cir::CastKind::float_complex_to_bool;
1634 case CK_IntegralComplexToBoolean:
1635 castOpKind = cir::CastKind::int_complex_to_bool;
1638 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1644mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1645 QualType promotionType) {
1647 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1648 switch (bo->getOpcode()) {
1649#define HANDLE_BINOP(OP) \
1651 return emit##OP(emitBinOps(bo, promotionType));
1660 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1661 switch (uo->getOpcode()) {
1664 return VisitRealImag(uo, promotionType);
1666 return VisitUnaryMinus(uo, promotionType);
1668 return VisitUnaryPlus(uo, promotionType);
1673 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1675 if (!promotionType.
isNull())
1676 return emitPromotedValue(result, promotionType);
1677 return emitUnPromotedValue(result, e->
getType());
1682mlir::Value ScalarExprEmitter::emitCompoundAssign(
1683 const CompoundAssignOperator *e,
1684 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1686 bool ignore = std::exchange(ignoreResultAssign,
false);
1688 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1699 if (!lhs.isVolatile())
1703 return emitLoadOfLValue(lhs, e->
getExprLoc());
1706mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1707 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1722#define COMPOUND_OP(Op) \
1723 case BO_##Op##Assign: \
1724 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1761 llvm_unreachable(
"Not valid compound assignment operators");
1763 llvm_unreachable(
"Unhandled compound assignment operator");
1768 bool ignoreResultAssign) {
1770 "Invalid scalar expression to emit");
1773 .Visit(
const_cast<Expr *
>(e));
1778 if (!promotionType.
isNull())
1793static std::optional<QualType>
1797 return std::nullopt;
1802 return std::nullopt;
1815 const BinOpInfo &op) {
1817 "Expected a unary or binary operator");
1821 if (!op.mayHaveIntegerOverflow())
1825 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1826 return !uo->canOverflow();
1831 std::optional<QualType> optionalLHSTy =
1836 std::optional<QualType> optionalRHSTy =
1846 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1853 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1854 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1859 const BinOpInfo &op,
1860 bool isSubtraction) {
1865 mlir::Value pointer = op.lhs;
1866 Expr *pointerOperand =
expr->getLHS();
1867 mlir::Value
index = op.rhs;
1868 Expr *indexOperand =
expr->getRHS();
1874 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1875 std::swap(pointer,
index);
1876 std::swap(pointerOperand, indexOperand);
1878 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1879 "Need a pointer operand");
1880 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1915 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1925 numElements.getType());
1936 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1941 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1943 pointer.getType(), pointer,
index);
1947 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1948 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1958 bool negMul,
bool negAdd) {
1959 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
1960 mlir::Value mulOp0 = mulOp.getLhs();
1961 mlir::Value mulOp1 = mulOp.getRhs();
1969 mlir::Value fmuladd =
1970 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
1971 addend, mulOp.getFenvAttr());
1984 bool isSub =
false) {
1985 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
1986 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
1987 "Only fadd/fsub can be the root of an fmuladd.");
1996 mlir::Value lhs = op.lhs;
1997 mlir::Value rhs = op.rhs;
2001 bool negLHS =
false;
2002 if (
auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2003 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2004 lhs = lhsNeg.getInput();
2009 bool negRHS =
false;
2010 if (
auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2011 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2012 rhs = rhsNeg.getInput();
2020 if (
auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2021 if (lhsMul.getResult().use_empty() || negLHS) {
2024 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2025 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2028 if (
auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2029 if (rhsMul.getResult().use_empty() || negRHS) {
2032 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2033 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS,
false);
2040mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
2041 const mlir::Location loc = cgf.
getLoc(ops.loc);
2044 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2045 case LangOptions::SOB_Defined:
2046 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2047 return builder.
createMul(loc, ops.lhs, ops.rhs);
2049 case LangOptions::SOB_Undefined:
2050 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2053 case LangOptions::SOB_Trapping:
2065 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2067 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2069 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2070 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2071 return builder.
createFMul(loc, ops.lhs, ops.rhs);
2074 if (ops.isFixedPointOp()) {
2080 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2083mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2084 const mlir::Location loc = cgf.
getLoc(ops.loc);
2085 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2086 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2087 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2089 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2092mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2093 const mlir::Location loc = cgf.
getLoc(ops.loc);
2094 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2095 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2096 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2098 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2102mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2103 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2104 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2108 const mlir::Location loc = cgf.
getLoc(ops.loc);
2111 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2112 case LangOptions::SOB_Defined:
2113 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2114 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2116 case LangOptions::SOB_Undefined:
2117 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2120 case LangOptions::SOB_Trapping:
2133 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2135 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2137 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2138 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2142 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2145 if (ops.isFixedPointOp()) {
2151 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2154mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2155 const mlir::Location loc = cgf.
getLoc(ops.loc);
2157 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2160 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2161 case LangOptions::SOB_Defined: {
2162 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2163 return builder.
createSub(loc, ops.lhs, ops.rhs);
2166 case LangOptions::SOB_Undefined:
2167 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2170 case LangOptions::SOB_Trapping:
2184 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2186 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2188 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2189 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2191 if (mlir::Value fmuladd =
2194 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2197 if (ops.isFixedPointOp()) {
2203 return builder.
createSub(loc, ops.lhs, ops.rhs);
2208 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2220 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2224mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2226 if (ops.isFixedPointOp()) {
2236 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2240 bool sanitizeUnsignedBase =
2241 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2243 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2244 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2249 else if ((sanitizeBase || sanitizeExponent) &&
2250 mlir::isa<cir::IntType>(ops.lhs.getType()))
2256mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2258 if (ops.isFixedPointOp()) {
2271 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2272 mlir::isa<cir::IntType>(ops.lhs.getType()))
2280mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2281 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2283mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2284 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2286mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2287 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2294mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2296 QualType destTy = ce->
getType();
2298 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2302 ignoreResultAssign =
false;
2305 case clang::CK_Dependent:
2306 llvm_unreachable(
"dependent cast kind in CIR gen!");
2307 case clang::CK_BuiltinFnToFnPtr:
2308 llvm_unreachable(
"builtin functions are handled elsewhere");
2309 case CK_LValueBitCast:
2310 case CK_LValueToRValueBitCast: {
2312 Address sourceAddr = sourceLVal.getAddress();
2318 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2321 case CK_CPointerToObjCPointerCast:
2322 case CK_BlockPointerToObjCPointerCast:
2323 case CK_AnyPointerToBlockPointerCast:
2325 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2330 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2332 "sanitizer support");
2336 "strict vtable pointers");
2362 case CK_AddressSpaceConversion: {
2363 Expr::EvalResult result;
2377 case CK_AtomicToNonAtomic:
2378 case CK_NonAtomicToAtomic:
2379 case CK_UserDefinedConversion:
2380 return Visit(
const_cast<Expr *
>(subExpr));
2384 case CK_IntegralToPointer: {
2386 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2395 : cir::CastKind::integral,
2400 "IntegralToPointer: strict vtable pointers");
2407 case CK_BaseToDerived: {
2409 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2421 case CK_UncheckedDerivedToBase:
2422 case CK_DerivedToBase: {
2433 case CK_ArrayToPointerDecay:
2436 case CK_NullToPointer: {
2446 case CK_NullToMemberPointer: {
2452 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2458 case CK_ReinterpretMemberPointer: {
2459 mlir::Value src = Visit(subExpr);
2463 case CK_BaseToDerivedMemberPointer:
2464 case CK_DerivedToBaseMemberPointer: {
2465 mlir::Value src = Visit(subExpr);
2469 QualType derivedTy =
2470 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2471 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2472 NestedNameSpecifier qualifier = mpType->getQualifier();
2473 assert(qualifier &&
"member pointer without class qualifier");
2474 const Type *qualifierType = qualifier.getAsType();
2475 assert(qualifierType &&
"member pointer qualifier is not a type");
2482 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2485 if (
kind == CK_BaseToDerivedMemberPointer)
2486 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2488 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2491 if (
kind == CK_BaseToDerivedMemberPointer)
2492 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2494 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2498 case CK_LValueToRValue:
2500 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2501 return Visit(
const_cast<Expr *
>(subExpr));
2503 case CK_IntegralCast: {
2504 ScalarConversionOpts opts;
2505 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2506 if (!ice->isPartOfExplicitCast())
2507 opts = ScalarConversionOpts(cgf.
sanOpts);
2509 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2513 case CK_FloatingComplexToReal:
2514 case CK_IntegralComplexToReal:
2515 case CK_FloatingComplexToBoolean:
2516 case CK_IntegralComplexToBoolean: {
2522 case CK_FloatingRealToComplex:
2523 case CK_FloatingComplexCast:
2524 case CK_IntegralRealToComplex:
2525 case CK_IntegralComplexCast:
2526 case CK_IntegralComplexToFloatingComplex:
2527 case CK_FloatingComplexToIntegralComplex:
2528 llvm_unreachable(
"scalar cast to non-scalar value");
2530 case CK_PointerToIntegral: {
2531 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2534 "strict vtable pointers");
2541 case CK_IntegralToFloating:
2542 case CK_FloatingToIntegral:
2543 case CK_FloatingCast:
2544 case CK_FixedPointToFloating:
2545 case CK_FloatingToFixedPoint: {
2546 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2548 "fixed point casts");
2551 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2552 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2556 case CK_IntegralToBoolean:
2557 return emitIntToBoolConversion(Visit(subExpr),
2560 case CK_PointerToBoolean:
2561 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2562 case CK_FloatingToBoolean:
2563 return emitFloatToBoolConversion(Visit(subExpr),
2565 case CK_MemberPointerToBoolean: {
2566 mlir::Value memPtr = Visit(subExpr);
2568 cir::CastKind::member_ptr_to_bool, memPtr,
2572 case CK_VectorSplat: {
2574 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2575 return cir::VecSplatOp::create(builder,
2579 case CK_FunctionToPointerDecay:
2589mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2591 return emitLoadOfLValue(e);
2598mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2603 Expr::EvalResult result;
2605 llvm::APSInt value = result.
Val.
getInt();
2615 return builder.
getBool(value.getBoolValue(), loc);
2618 return emitLoadOfLValue(e);
2621mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2622 const unsigned numInitElements = e->
getNumInits();
2624 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2625 assert((ignore ==
false ||
2627 "init list ignored");
2635 const auto vectorType =
2638 SmallVector<mlir::Value, 16> elements;
2639 for (Expr *init : e->
inits()) {
2640 elements.push_back(Visit(init));
2644 if (numInitElements < vectorType.getSize()) {
2647 std::fill_n(std::back_inserter(elements),
2648 vectorType.getSize() - numInitElements, zeroValue);
2651 return cir::VecCreateOp::create(cgf.
getBuilder(),
2657 if (numInitElements == 0)
2668 "Invalid scalar expression to emit");
2670 .emitScalarConversion(src, srcTy, dstTy, loc);
2678 "Invalid complex -> scalar conversion");
2683 ? cir::CastKind::float_complex_to_bool
2684 : cir::CastKind::int_complex_to_bool;
2689 ? cir::CastKind::float_complex_to_real
2690 : cir::CastKind::int_complex_to_real;
2696mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2703 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2705 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2706 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2720mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2725 llvm::APSInt value = evalResult.
Val.
getInt();
2731 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2735mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2737 mlir::Value result = VisitRealImag(e, promotionTy);
2738 if (result && !promotionTy.
isNull())
2739 result = emitUnPromotedValue(result, e->
getType());
2743mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2745 mlir::Value result = VisitRealImag(e, promotionTy);
2746 if (result && !promotionTy.
isNull())
2747 result = emitUnPromotedValue(result, e->
getType());
2751mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2752 QualType promotionTy) {
2755 "Invalid UnaryOp kind for ComplexType Real or Imag");
2777 mlir::Value operand = promotionTy.
isNull()
2779 : cgf.emitPromotedScalarExpr(op, promotionTy);
2785 mlir::Value operand;
2788 operand = cir::LoadOp::create(builder, loc, operand);
2789 }
else if (!promotionTy.
isNull()) {
2799mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2800 const UnaryExprOrTypeTraitExpr *e) {
2804 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2805 if (
const VariableArrayType *vat =
2810 bool evaluateExtent =
true;
2811 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2813 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2816 if (evaluateExtent) {
2827 if (
kind == UETT_CountOf)
2832 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2833 mlir::Value numElts = vlaSize.
numElts;
2837 if (!eltSize.
isOne()) {
2839 mlir::Value eltSizeValue =
2842 return builder.
createMul(loc, eltSizeValue, numElts,
2849 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2856 }
else if (e->
getKind() == UETT_VectorElements) {
2858 if (vecTy.getIsScalable()) {
2861 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2868 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getSize()));
2895mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2896 const AbstractConditionalOperator *e) {
2899 ignoreResultAssign =
false;
2902 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2904 Expr *condExpr = e->
getCond();
2912 Expr *live = lhsExpr, *dead = rhsExpr;
2914 std::swap(live, dead);
2920 mlir::Value result = Visit(live);
2927 loc, cir::PoisonAttr::get(builder.getContext(),
2935 QualType condType = condExpr->
getType();
2944 mlir::Value lhsValue = Visit(lhsExpr);
2945 mlir::Value rhsValue = Visit(rhsExpr);
2947 mlir::Type vecTy = convertType(condType);
2948 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
2949 auto testMSB = cir::VecCmpOp::create(
2950 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2952 mlir::Value tmp2 = builder.
createNot(tmp);
2955 mlir::Value rhsTmp = rhsValue;
2956 mlir::Value lhsTmp = lhsValue;
2957 bool wasCast =
false;
2959 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2965 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
2966 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
2967 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
2976 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2980 mlir::Value condValue = Visit(condExpr);
2981 mlir::Value lhsValue = Visit(lhsExpr);
2982 mlir::Value rhsValue = Visit(rhsExpr);
2983 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2992 bool lhsIsVoid =
false;
2996 mlir::Value lhs = Visit(lhsExpr);
3002 mlir::Value rhs = Visit(rhsExpr);
3004 assert(!rhs &&
"lhs and rhs types must match");
3012 CIRGenFunction::ConditionalEvaluation eval(cgf);
3014 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
3015 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3022 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3024 eval.beginEvaluation();
3025 branch = Visit(
expr);
3026 eval.endEvaluation();
3027 branchCleanups.forceCleanup({&branch});
3031 cir::YieldOp::create(b, loc, branch);
3034 cir::TernaryOp ternary = cir::TernaryOp::create(
3035 builder, loc, condV,
3037 [&](mlir::OpBuilder &b, mlir::Location loc) {
3038 emitBranch(b, loc, lhsExpr);
3041 [&](mlir::OpBuilder &b, mlir::Location loc) {
3042 emitBranch(b, loc, rhsExpr);
3047 for (mlir::Region *region :
3048 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3049 mlir::Block &lastBlock = region->back();
3050 if (lastBlock.empty() ||
3051 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3052 mlir::OpBuilder::InsertionGuard guard(builder);
3053 builder.setInsertionPointToEnd(&lastBlock);
3054 cir::YieldOp::create(builder, loc);
3058 return ternary.getResult();
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op, CIRGenBuilderTy &builder, bool isSub=false)
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp, mlir::Value addend, CIRGenBuilderTy &builder, bool negMul, bool negAdd)
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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...
bool allowFPContractWithinStatement() const
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits() const
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Type
The name was classified as a type.
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
U cast(CodeGen::Address addr)
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool fixedPointType()
static bool vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool fastMathFlags()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool HasSideEffects
Whether the evaluated expression has side effects.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.