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;
543 llvm_unreachable(
"Internal error: Cast to unexpected type");
544 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
545 if (cgf.getBuilder().isInt(dstTy)) {
549 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
550 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
552 castKind = cir::CastKind::float_to_int;
553 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
555 return builder.createFloatingCast(src, fullDstTy);
557 llvm_unreachable(
"Internal error: Cast to unexpected type");
560 llvm_unreachable(
"Internal error: Cast from unexpected type");
563 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
564 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
569 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
573 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
578 "variably modified types in varargs");
581 return cgf.emitVAArg(ve);
584 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
588 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
590 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
593 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
595 return emitScalarPrePostIncDec(e, lv);
597 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
598 return VisitUnaryPrePostIncDec(e);
600 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
601 return VisitUnaryPrePostIncDec(e);
603 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
604 return VisitUnaryPrePostIncDec(e);
606 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
607 return VisitUnaryPrePostIncDec(e);
609 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
610 if (cgf.getLangOpts().OpenMP)
618 if (
type->getAs<AtomicType>()) {
622 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
625 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
639 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
640 }
else if (
type->isIntegerType()) {
641 QualType promotedType;
642 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
643 if (cgf.getContext().isPromotableIntegerType(
type)) {
644 promotedType = cgf.getContext().getPromotedIntegerType(
type);
645 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
646 canPerformLossyDemotionCheck =
true;
647 canPerformLossyDemotionCheck &=
648 cgf.getContext().getCanonicalType(
type) !=
649 cgf.getContext().getCanonicalType(promotedType);
650 canPerformLossyDemotionCheck &=
657 (!canPerformLossyDemotionCheck ||
658 type->isSignedIntegerOrEnumerationType() ||
660 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
661 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
662 "The following check expects that if we do promotion to different "
663 "underlying canonical type, at least one of the types (either "
664 "base or promoted) will be signed, or the bitwidths will match.");
669 value = emitIncDecConsiderOverflowBehavior(e, value);
672 value = emitIncOrDec(e, input,
false);
674 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
675 QualType
type = ptr->getPointeeType();
676 if (
const VariableArrayType *vla =
677 cgf.getContext().getAsVariableArrayType(
type)) {
679 mlir::Value numElts = cgf.getVLASize(vla).numElts;
681 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
683 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
687 CIRGenBuilderTy &builder = cgf.getBuilder();
689 mlir::Value amt = builder.getSInt32(amount, loc);
691 value = builder.createPtrStride(loc, value, amt);
693 }
else if (
type->isVectorType()) {
696 }
else if (
type->isRealFloatingType()) {
697 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
699 if (
type->isHalfType() &&
700 !cgf.getContext().getLangOpts().NativeHalfType) {
705 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
707 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
708 auto fpType = mlir::cast<cir::FPTypeInterface>(value.getType());
709 mlir::Value amount = builder.getConstFP(
710 loc, value.getType(), llvm::APFloat(fpType.getFloatSemantics(), 1));
711 value = e->
isIncrementOp() ? builder.createFAdd(loc, value, amount)
712 : builder.createFSub(loc, value, amount);
714 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
717 }
else if (
type->isFixedPointType()) {
718 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
721 assert(
type->castAs<ObjCObjectPointerType>());
722 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
726 CIRGenFunction::SourceLocRAIIObject sourceloc{
731 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
733 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
737 return e->
isPrefix() ? value : input;
740 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
742 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
743 case LangOptions::SOB_Defined:
744 return emitIncOrDec(e, inVal,
false);
745 case LangOptions::SOB_Undefined:
747 return emitIncOrDec(e, inVal,
true);
748 case LangOptions::SOB_Trapping:
750 return emitIncOrDec(e, inVal,
true);
751 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
754 llvm_unreachable(
"Unexpected signed overflow behavior kind");
757 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
758 if (llvm::isa<MemberPointerType>(e->
getType()))
759 return cgf.cgm.emitMemberPointerConstant(e);
761 return cgf.emitLValue(e->
getSubExpr()).getPointer();
764 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
767 return emitLoadOfLValue(e);
770 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
772 mlir::Value result = VisitUnaryPlus(e, promotionType);
773 if (result && !promotionType.
isNull())
774 return emitUnPromotedValue(result, e->
getType());
778 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
779 ignoreResultAssign =
false;
780 if (!promotionType.
isNull())
781 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
785 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
787 mlir::Value result = VisitUnaryMinus(e, promotionType);
788 if (result && !promotionType.
isNull())
789 return emitUnPromotedValue(result, e->
getType());
793 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
794 ignoreResultAssign =
false;
796 if (!promotionType.
isNull())
797 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
803 if (cir::isFPOrVectorOfFPType(operand.getType()))
804 return builder.createOrFold<cir::FNegOp>(loc, operand);
810 cgf.getLangOpts().getSignedOverflowBehavior() !=
811 LangOptions::SOB_Defined;
813 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
816 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
820 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
821 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
824 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
825 ignoreResultAssign =
false;
827 return builder.createOrFold<cir::NotOp>(
831 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
833 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
834 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
835 mlir::Value VisitRealImag(
const UnaryOperator *e,
836 QualType promotionType = QualType());
838 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
843 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
845 "ScalarExprEmitter: materialize temporary");
848 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
849 ASTContext &ctx = cgf.getContext();
852 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
854 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
855 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
858 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
859 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
862 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
863 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
867 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
869 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
870 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
871 return cgf.emitCXXNewExpr(e);
873 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
874 cgf.emitCXXDeleteExpr(e);
877 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
883 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
888 "Expected int type for TypeTraitExpr");
889 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
895 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
901 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
903 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
906 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
909 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
911 "ScalarExprEmitter: cxx pseudo destructor");
914 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
915 cgf.emitCXXThrowExpr(e);
919 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
928 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
930 ScalarConversionOpts opts = ScalarConversionOpts()) {
940 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
946 if (srcType == dstType) {
947 if (opts.emitImplicitIntegerSignChangeChecks)
948 cgf.getCIRGenModule().errorNYI(loc,
949 "implicit integer sign change checks");
956 mlir::Type mlirSrcType = src.getType();
961 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
963 mlir::Type mlirDstType = cgf.convertType(dstType);
966 !cgf.getContext().getLangOpts().NativeHalfType) {
968 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
969 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
970 cgf.getCIRGenModule().errorNYI(loc,
971 "cast via llvm.convert.from.fp16");
976 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
977 cgf.getCIRGenModule().errorNYI(loc,
978 "cast via llvm.convert.from.fp16");
981 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
983 srcType = cgf.getContext().FloatTy;
984 mlirSrcType = cgf.floatTy;
990 if (mlirSrcType == mlirDstType) {
991 if (opts.emitImplicitIntegerSignChangeChecks)
992 cgf.getCIRGenModule().errorNYI(loc,
993 "implicit integer sign change checks");
1000 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1001 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1002 return builder.getNullPtr(dstPT, src.getLoc());
1008 return builder.createPtrToInt(src, mlirDstType);
1015 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1017 "Splatted expr doesn't match with vector element type?");
1019 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1024 cgf.getCIRGenModule().errorNYI(loc,
1025 "matrix type to matrix type conversion");
1029 "Internal error: conversion between matrix type and scalar type");
1032 mlir::Value res =
nullptr;
1033 mlir::Type resTy = mlirDstType;
1035 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1037 if (mlirDstType != resTy) {
1038 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1039 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1043 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1047 if (opts.emitImplicitIntegerTruncationChecks)
1048 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1050 if (opts.emitImplicitIntegerSignChangeChecks)
1051 cgf.getCIRGenModule().errorNYI(loc,
1052 "implicit integer sign change checks");
1057 BinOpInfo emitBinOps(
const BinaryOperator *e,
1058 QualType promotionType = QualType()) {
1059 ignoreResultAssign =
false;
1061 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1062 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1063 if (!promotionType.
isNull())
1064 result.fullType = promotionType;
1066 result.fullType = e->
getType();
1067 result.compType = result.fullType;
1068 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1069 result.compType = vecType->getElementType();
1073 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1078 mlir::Value emitMul(
const BinOpInfo &ops);
1079 mlir::Value emitDiv(
const BinOpInfo &ops);
1080 mlir::Value emitRem(
const BinOpInfo &ops);
1081 mlir::Value emitAdd(
const BinOpInfo &ops);
1082 mlir::Value emitSub(
const BinOpInfo &ops);
1083 mlir::Value emitShl(
const BinOpInfo &ops);
1084 mlir::Value emitShr(
const BinOpInfo &ops);
1085 mlir::Value emitAnd(
const BinOpInfo &ops);
1086 mlir::Value emitXor(
const BinOpInfo &ops);
1087 mlir::Value emitOr(
const BinOpInfo &ops);
1089 LValue emitCompoundAssignLValue(
1090 const CompoundAssignOperator *e,
1091 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1092 mlir::Value &result);
1094 emitCompoundAssign(
const CompoundAssignOperator *e,
1095 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1099 QualType getPromotionType(QualType ty) {
1100 const clang::ASTContext &ctx = cgf.getContext();
1101 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1102 QualType elementTy = complexTy->getElementType();
1108 if (
auto *vt = ty->
getAs<VectorType>()) {
1109 unsigned numElements = vt->getNumElements();
1112 return cgf.getContext().FloatTy;
1119#define HANDLEBINOP(OP) \
1120 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1121 QualType promotionTy = getPromotionType(e->getType()); \
1122 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1123 if (result && !promotionTy.isNull()) \
1124 result = emitUnPromotedValue(result, e->getType()); \
1127 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1128 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1144 ignoreResultAssign =
false;
1150 auto clangCmpToCIRCmp =
1154 return cir::CmpOpKind::lt;
1156 return cir::CmpOpKind::gt;
1158 return cir::CmpOpKind::le;
1160 return cir::CmpOpKind::ge;
1162 return cir::CmpOpKind::eq;
1164 return cir::CmpOpKind::ne;
1166 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1178 BinOpInfo boInfo = emitBinOps(e);
1179 mlir::Value lhs = boInfo.lhs;
1180 mlir::Value rhs = boInfo.rhs;
1190 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1192 boInfo.lhs, boInfo.rhs);
1194 }
else if (boInfo.isFixedPointOp()) {
1197 result = builder.
getBool(
false, loc);
1201 mlir::isa<cir::PointerType>(lhs.getType()) &&
1202 mlir::isa<cir::PointerType>(rhs.getType())) {
1203 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1209 "Complex Comparison: can only be an equality comparison");
1215 mlir::Value lhsReal = Visit(e->
getLHS());
1216 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1224 mlir::Value rhsReal = Visit(e->
getRHS());
1225 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1237#define VISITCOMP(CODE) \
1238 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1248 const bool ignore = std::exchange(ignoreResultAssign,
false);
1263 rhs = Visit(e->
getRHS());
1273 if (lhs.isBitField()) {
1295 if (!lhs.isVolatile())
1299 return emitLoadOfLValue(lhs, e->
getExprLoc());
1302 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1303 cgf.emitIgnoredExpr(e->
getLHS());
1305 return Visit(e->
getRHS());
1308 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1310 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1312 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1314 mlir::Value lhs = Visit(e->
getLHS());
1315 mlir::Value rhs = Visit(e->
getRHS());
1317 auto cmpOpKind = cir::CmpOpKind::ne;
1318 mlir::Type resTy = cgf.convertType(e->
getType());
1319 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1320 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1321 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1322 return builder.createIntCast(vecOr, resTy);
1326 mlir::Type resTy = cgf.convertType(e->
getType());
1327 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1329 CIRGenFunction::ConditionalEvaluation eval(cgf);
1331 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1332 auto resOp = cir::TernaryOp::create(
1333 builder, loc, lhsCondV,
1334 [&](mlir::OpBuilder &b, mlir::Location loc) {
1335 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1336 b.getInsertionBlock()};
1337 cgf.curLexScope->setAsTernary();
1338 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1340 cir::YieldOp::create(b, loc, res);
1343 [&](mlir::OpBuilder &b, mlir::Location loc) {
1344 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1345 b.getInsertionBlock()};
1347 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1348 cir::YieldOp::create(b, loc, res.getRes());
1350 return maybePromoteBoolResult(resOp.getResult(), resTy);
1353 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1355 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1357 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1359 mlir::Value lhs = Visit(e->
getLHS());
1360 mlir::Value rhs = Visit(e->
getRHS());
1362 auto cmpOpKind = cir::CmpOpKind::ne;
1363 mlir::Type resTy = cgf.convertType(e->
getType());
1364 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1365 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1366 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1367 return builder.createIntCast(vecOr, resTy);
1371 mlir::Type resTy = cgf.convertType(e->
getType());
1372 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1374 CIRGenFunction::ConditionalEvaluation eval(cgf);
1376 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1377 auto resOp = cir::TernaryOp::create(
1378 builder, loc, lhsCondV,
1379 [&](mlir::OpBuilder &b, mlir::Location loc) {
1380 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1381 b.getInsertionBlock()};
1383 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1384 cir::YieldOp::create(b, loc, res.getRes());
1387 [&](mlir::OpBuilder &b, mlir::Location loc) {
1388 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1389 b.getInsertionBlock()};
1391 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1393 cir::YieldOp::create(b, loc, res);
1396 return maybePromoteBoolResult(resOp.getResult(), resTy);
1399 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1400 return emitLoadOfLValue(e);
1403 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1404 return emitLoadOfLValue(e);
1408 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1409 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1413 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1417 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1419 "ScalarExprEmitter: objc string literal");
1422 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1423 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1426 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1428 "ScalarExprEmitter: objc array literal");
1431 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1433 "ScalarExprEmitter: objc dictionary literal");
1437 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1438 mlir::Value src,
unsigned numElementsDst) {
1439 static constexpr int64_t mask[] = {0, 1, 2, -1};
1440 return builder.createVecShuffle(
1441 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1463 mlir::Type srcTy = src.getType();
1467 return builder.createBitcast(src, dstTy);
1472 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1480 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1484 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1491 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1495 return builder.createIntToPtr(src, dstTy);
1498 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1499 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1500 mlir::Type srcTy = src.getType();
1501 mlir::Type dstTy = cgf.convertType(e->
getType());
1513 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1519 if (numElementsSrc == 3 && numElementsDst != 3) {
1521 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1522 "numElemsDst != 3");
1529 if (numElementsSrc != 3 && numElementsDst == 3) {
1530 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1532 auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4);
1534 src = convertVec3AndVec4(builder, loc, src, 3);
1541 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1542 return cgf.emitAtomicExpr(e).getValue();
1546LValue ScalarExprEmitter::emitCompoundAssignLValue(
1548 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1549 mlir::Value &result) {
1560 if (promotionTypeCR.
isNull())
1564 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1566 if (!promotionTypeRHS.
isNull())
1569 opInfo.rhs = Visit(e->
getRHS());
1571 opInfo.fullType = promotionTypeCR;
1572 opInfo.compType = opInfo.fullType;
1573 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1574 opInfo.compType = vecType->getElementType();
1583 if (lhsTy->
getAs<AtomicType>()) {
1584 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1588 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1590 CIRGenFunction::SourceLocRAIIObject sourceloc{
1593 if (!promotionTypeLHS.
isNull())
1594 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1596 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1600 result = (this->*func)(opInfo);
1604 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1605 ScalarConversionOpts(cgf.
sanOpts));
1611 if (lhsLV.isBitField())
1622mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1626 cir::CastKind castOpKind;
1628 case CK_FloatingComplexToReal:
1629 castOpKind = cir::CastKind::float_complex_to_real;
1631 case CK_IntegralComplexToReal:
1632 castOpKind = cir::CastKind::int_complex_to_real;
1634 case CK_FloatingComplexToBoolean:
1635 castOpKind = cir::CastKind::float_complex_to_bool;
1637 case CK_IntegralComplexToBoolean:
1638 castOpKind = cir::CastKind::int_complex_to_bool;
1641 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1647mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1648 QualType promotionType) {
1650 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1651 switch (bo->getOpcode()) {
1652#define HANDLE_BINOP(OP) \
1654 return emit##OP(emitBinOps(bo, promotionType));
1663 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1664 switch (uo->getOpcode()) {
1667 return VisitRealImag(uo, promotionType);
1669 return VisitUnaryMinus(uo, promotionType);
1671 return VisitUnaryPlus(uo, promotionType);
1676 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1678 if (!promotionType.
isNull())
1679 return emitPromotedValue(result, promotionType);
1680 return emitUnPromotedValue(result, e->
getType());
1685mlir::Value ScalarExprEmitter::emitCompoundAssign(
1686 const CompoundAssignOperator *e,
1687 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1689 bool ignore = std::exchange(ignoreResultAssign,
false);
1691 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1702 if (!lhs.isVolatile())
1706 return emitLoadOfLValue(lhs, e->
getExprLoc());
1709mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1710 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1725#define COMPOUND_OP(Op) \
1726 case BO_##Op##Assign: \
1727 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1764 llvm_unreachable(
"Not valid compound assignment operators");
1766 llvm_unreachable(
"Unhandled compound assignment operator");
1771 bool ignoreResultAssign) {
1773 "Invalid scalar expression to emit");
1776 .Visit(
const_cast<Expr *
>(e));
1781 if (!promotionType.
isNull())
1796static std::optional<QualType>
1800 return std::nullopt;
1805 return std::nullopt;
1818 const BinOpInfo &op) {
1820 "Expected a unary or binary operator");
1824 if (!op.mayHaveIntegerOverflow())
1828 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1829 return !uo->canOverflow();
1834 std::optional<QualType> optionalLHSTy =
1839 std::optional<QualType> optionalRHSTy =
1849 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1856 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1857 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1862 const BinOpInfo &op,
1863 bool isSubtraction) {
1868 mlir::Value pointer = op.lhs;
1869 Expr *pointerOperand =
expr->getLHS();
1870 mlir::Value
index = op.rhs;
1871 Expr *indexOperand =
expr->getRHS();
1877 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1878 std::swap(pointer,
index);
1879 std::swap(pointerOperand, indexOperand);
1881 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1882 "Need a pointer operand");
1883 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1918 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1928 numElements.getType());
1939 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1944 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1946 pointer.getType(), pointer,
index);
1950 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1951 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1954mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1955 const mlir::Location loc = cgf.
getLoc(ops.loc);
1958 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1959 case LangOptions::SOB_Defined:
1960 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1961 return builder.
createMul(loc, ops.lhs, ops.rhs);
1963 case LangOptions::SOB_Undefined:
1964 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1967 case LangOptions::SOB_Trapping:
1979 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1981 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1983 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1984 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1985 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1988 if (ops.isFixedPointOp()) {
1994 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1997mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1998 const mlir::Location loc = cgf.
getLoc(ops.loc);
1999 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2000 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2001 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2003 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2006mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2007 const mlir::Location loc = cgf.
getLoc(ops.loc);
2008 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2009 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2010 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2012 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2016mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2017 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2018 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2022 const mlir::Location loc = cgf.
getLoc(ops.loc);
2025 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2026 case LangOptions::SOB_Defined:
2027 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2028 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2030 case LangOptions::SOB_Undefined:
2031 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2034 case LangOptions::SOB_Trapping:
2047 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2049 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2051 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2052 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2053 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2056 if (ops.isFixedPointOp()) {
2062 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2065mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2066 const mlir::Location loc = cgf.
getLoc(ops.loc);
2068 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2071 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2072 case LangOptions::SOB_Defined: {
2073 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2074 return builder.
createSub(loc, ops.lhs, ops.rhs);
2077 case LangOptions::SOB_Undefined:
2078 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2081 case LangOptions::SOB_Trapping:
2095 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2097 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2099 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2100 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2101 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2104 if (ops.isFixedPointOp()) {
2110 return builder.
createSub(loc, ops.lhs, ops.rhs);
2115 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2127 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2131mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2133 if (ops.isFixedPointOp()) {
2143 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2147 bool sanitizeUnsignedBase =
2148 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2150 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2151 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2156 else if ((sanitizeBase || sanitizeExponent) &&
2157 mlir::isa<cir::IntType>(ops.lhs.getType()))
2163mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2165 if (ops.isFixedPointOp()) {
2178 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2179 mlir::isa<cir::IntType>(ops.lhs.getType()))
2187mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2188 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2190mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2191 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2193mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2194 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2201mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2203 QualType destTy = ce->
getType();
2208 ignoreResultAssign =
false;
2211 case clang::CK_Dependent:
2212 llvm_unreachable(
"dependent cast kind in CIR gen!");
2213 case clang::CK_BuiltinFnToFnPtr:
2214 llvm_unreachable(
"builtin functions are handled elsewhere");
2215 case CK_LValueBitCast:
2216 case CK_LValueToRValueBitCast: {
2218 Address sourceAddr = sourceLVal.getAddress();
2224 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2227 case CK_CPointerToObjCPointerCast:
2228 case CK_BlockPointerToObjCPointerCast:
2229 case CK_AnyPointerToBlockPointerCast:
2231 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2236 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2238 "sanitizer support");
2242 "strict vtable pointers");
2268 case CK_AddressSpaceConversion: {
2269 Expr::EvalResult result;
2283 case CK_AtomicToNonAtomic:
2284 case CK_NonAtomicToAtomic:
2285 case CK_UserDefinedConversion:
2286 return Visit(
const_cast<Expr *
>(subExpr));
2290 case CK_IntegralToPointer: {
2292 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2301 : cir::CastKind::integral,
2306 "IntegralToPointer: strict vtable pointers");
2313 case CK_BaseToDerived: {
2315 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2327 case CK_UncheckedDerivedToBase:
2328 case CK_DerivedToBase: {
2339 case CK_ArrayToPointerDecay:
2342 case CK_NullToPointer: {
2352 case CK_NullToMemberPointer: {
2358 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2364 case CK_ReinterpretMemberPointer: {
2365 mlir::Value src = Visit(subExpr);
2369 case CK_BaseToDerivedMemberPointer:
2370 case CK_DerivedToBaseMemberPointer: {
2371 mlir::Value src = Visit(subExpr);
2375 QualType derivedTy =
2376 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2377 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2378 NestedNameSpecifier qualifier = mpType->getQualifier();
2379 assert(qualifier &&
"member pointer without class qualifier");
2380 const Type *qualifierType = qualifier.getAsType();
2381 assert(qualifierType &&
"member pointer qualifier is not a type");
2388 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2391 if (
kind == CK_BaseToDerivedMemberPointer)
2392 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2394 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2397 if (
kind == CK_BaseToDerivedMemberPointer)
2398 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2400 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2404 case CK_LValueToRValue:
2406 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2407 return Visit(
const_cast<Expr *
>(subExpr));
2409 case CK_IntegralCast: {
2410 ScalarConversionOpts opts;
2411 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2412 if (!ice->isPartOfExplicitCast())
2413 opts = ScalarConversionOpts(cgf.
sanOpts);
2415 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2419 case CK_FloatingComplexToReal:
2420 case CK_IntegralComplexToReal:
2421 case CK_FloatingComplexToBoolean:
2422 case CK_IntegralComplexToBoolean: {
2428 case CK_FloatingRealToComplex:
2429 case CK_FloatingComplexCast:
2430 case CK_IntegralRealToComplex:
2431 case CK_IntegralComplexCast:
2432 case CK_IntegralComplexToFloatingComplex:
2433 case CK_FloatingComplexToIntegralComplex:
2434 llvm_unreachable(
"scalar cast to non-scalar value");
2436 case CK_PointerToIntegral: {
2437 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2440 "strict vtable pointers");
2447 case CK_IntegralToFloating:
2448 case CK_FloatingToIntegral:
2449 case CK_FloatingCast:
2450 case CK_FixedPointToFloating:
2451 case CK_FloatingToFixedPoint: {
2452 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2454 "fixed point casts");
2457 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2458 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2462 case CK_IntegralToBoolean:
2463 return emitIntToBoolConversion(Visit(subExpr),
2466 case CK_PointerToBoolean:
2467 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2468 case CK_FloatingToBoolean:
2469 return emitFloatToBoolConversion(Visit(subExpr),
2471 case CK_MemberPointerToBoolean: {
2472 mlir::Value memPtr = Visit(subExpr);
2474 cir::CastKind::member_ptr_to_bool, memPtr,
2478 case CK_VectorSplat: {
2480 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2481 return cir::VecSplatOp::create(builder,
2485 case CK_FunctionToPointerDecay:
2495mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2497 return emitLoadOfLValue(e);
2504mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2509 Expr::EvalResult result;
2511 llvm::APSInt value = result.
Val.
getInt();
2521 return builder.
getBool(value.getBoolValue(), loc);
2524 return emitLoadOfLValue(e);
2527mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2528 const unsigned numInitElements = e->
getNumInits();
2530 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2531 assert((ignore ==
false ||
2533 "init list ignored");
2541 const auto vectorType =
2544 SmallVector<mlir::Value, 16> elements;
2545 for (Expr *init : e->
inits()) {
2546 elements.push_back(Visit(init));
2550 if (numInitElements < vectorType.getSize()) {
2553 std::fill_n(std::back_inserter(elements),
2554 vectorType.getSize() - numInitElements, zeroValue);
2557 return cir::VecCreateOp::create(cgf.
getBuilder(),
2563 if (numInitElements == 0)
2574 "Invalid scalar expression to emit");
2576 .emitScalarConversion(src, srcTy, dstTy, loc);
2584 "Invalid complex -> scalar conversion");
2589 ? cir::CastKind::float_complex_to_bool
2590 : cir::CastKind::int_complex_to_bool;
2595 ? cir::CastKind::float_complex_to_real
2596 : cir::CastKind::int_complex_to_real;
2602mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2609 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2611 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2612 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2626mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2631 llvm::APSInt value = evalResult.
Val.
getInt();
2637 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2641mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2643 mlir::Value result = VisitRealImag(e, promotionTy);
2644 if (result && !promotionTy.
isNull())
2645 result = emitUnPromotedValue(result, e->
getType());
2649mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2651 mlir::Value result = VisitRealImag(e, promotionTy);
2652 if (result && !promotionTy.
isNull())
2653 result = emitUnPromotedValue(result, e->
getType());
2657mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2658 QualType promotionTy) {
2661 "Invalid UnaryOp kind for ComplexType Real or Imag");
2683 mlir::Value operand = promotionTy.
isNull()
2685 : cgf.emitPromotedScalarExpr(op, promotionTy);
2691 mlir::Value operand;
2694 operand = cir::LoadOp::create(builder, loc, operand);
2695 }
else if (!promotionTy.
isNull()) {
2705mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2706 const UnaryExprOrTypeTraitExpr *e) {
2710 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2711 if (
const VariableArrayType *vat =
2716 bool evaluateExtent =
true;
2717 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2719 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2722 if (evaluateExtent) {
2733 if (
kind == UETT_CountOf)
2738 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2739 mlir::Value numElts = vlaSize.
numElts;
2743 if (!eltSize.
isOne()) {
2745 mlir::Value eltSizeValue =
2748 return builder.
createMul(loc, eltSizeValue, numElts,
2755 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2762 }
else if (e->
getKind() == UETT_VectorElements) {
2764 if (vecTy.getIsScalable()) {
2767 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2774 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2799mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2800 const AbstractConditionalOperator *e) {
2803 ignoreResultAssign =
false;
2806 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2808 Expr *condExpr = e->
getCond();
2816 Expr *live = lhsExpr, *dead = rhsExpr;
2818 std::swap(live, dead);
2824 mlir::Value result = Visit(live);
2831 loc, cir::PoisonAttr::get(builder.getContext(),
2839 QualType condType = condExpr->
getType();
2848 mlir::Value lhsValue = Visit(lhsExpr);
2849 mlir::Value rhsValue = Visit(rhsExpr);
2851 mlir::Type vecTy = convertType(condType);
2852 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
2853 auto testMSB = cir::VecCmpOp::create(
2854 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2856 mlir::Value tmp2 = builder.
createNot(tmp);
2859 mlir::Value rhsTmp = rhsValue;
2860 mlir::Value lhsTmp = lhsValue;
2861 bool wasCast =
false;
2863 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2869 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
2870 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
2871 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
2880 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2884 mlir::Value condValue = Visit(condExpr);
2885 mlir::Value lhsValue = Visit(lhsExpr);
2886 mlir::Value rhsValue = Visit(rhsExpr);
2887 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2896 bool lhsIsVoid =
false;
2900 mlir::Value lhs = Visit(lhsExpr);
2906 mlir::Value rhs = Visit(rhsExpr);
2908 assert(!rhs &&
"lhs and rhs types must match");
2916 CIRGenFunction::ConditionalEvaluation eval(cgf);
2917 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2918 mlir::Type yieldTy{};
2920 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
2921 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
2928 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
2930 eval.beginEvaluation();
2931 branch = Visit(
expr);
2932 eval.endEvaluation();
2933 branchCleanups.forceCleanup({&branch});
2937 yieldTy = branch.getType();
2938 cir::YieldOp::create(b, loc, branch);
2942 insertPoints.push_back(b.saveInsertionPoint());
2946 mlir::Value result = cir::TernaryOp::create(
2947 builder, loc, condV,
2949 [&](mlir::OpBuilder &b, mlir::Location loc) {
2950 emitBranch(b, loc, lhsExpr);
2953 [&](mlir::OpBuilder &b, mlir::Location loc) {
2954 emitBranch(b, loc, rhsExpr);
2958 if (!insertPoints.empty()) {
2964 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2965 mlir::OpBuilder::InsertionGuard guard(builder);
2966 builder.restoreInsertionPoint(toInsert);
2969 if (mlir::isa<cir::VoidType>(yieldTy)) {
2970 cir::YieldOp::create(builder, loc);
2973 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.