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(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>(
709 value = emitIncOrDec(e, value);
711 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
714 }
else if (
type->isFixedPointType()) {
715 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
718 assert(
type->castAs<ObjCObjectPointerType>());
719 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
723 CIRGenFunction::SourceLocRAIIObject sourceloc{
728 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
730 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
734 return e->
isPrefix() ? value : input;
737 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
739 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
740 case LangOptions::SOB_Defined:
741 return emitIncOrDec(e, inVal,
false);
742 case LangOptions::SOB_Undefined:
744 return emitIncOrDec(e, inVal,
true);
745 case LangOptions::SOB_Trapping:
747 return emitIncOrDec(e, inVal,
true);
748 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
751 llvm_unreachable(
"Unexpected signed overflow behavior kind");
754 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
755 if (llvm::isa<MemberPointerType>(e->
getType()))
756 return cgf.cgm.emitMemberPointerConstant(e);
758 return cgf.emitLValue(e->
getSubExpr()).getPointer();
761 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
764 return emitLoadOfLValue(e);
767 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
769 mlir::Value result = VisitUnaryPlus(e, promotionType);
770 if (result && !promotionType.
isNull())
771 return emitUnPromotedValue(result, e->
getType());
775 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
776 ignoreResultAssign =
false;
777 if (!promotionType.
isNull())
778 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
782 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
784 mlir::Value result = VisitUnaryMinus(e, promotionType);
785 if (result && !promotionType.
isNull())
786 return emitUnPromotedValue(result, e->
getType());
790 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
791 ignoreResultAssign =
false;
793 if (!promotionType.
isNull())
794 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
802 cgf.getLangOpts().getSignedOverflowBehavior() !=
803 LangOptions::SOB_Defined;
807 return builder.createOrFold<cir::MinusOp>(
811 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
815 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
816 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
819 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
820 ignoreResultAssign =
false;
822 return builder.createOrFold<cir::NotOp>(
826 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
828 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
829 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
830 mlir::Value VisitRealImag(
const UnaryOperator *e,
831 QualType promotionType = QualType());
833 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
838 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
840 "ScalarExprEmitter: materialize temporary");
843 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
844 ASTContext &ctx = cgf.getContext();
847 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
849 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
850 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
853 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
854 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
857 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
858 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
862 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
864 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
865 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
866 return cgf.emitCXXNewExpr(e);
868 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
869 cgf.emitCXXDeleteExpr(e);
872 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
878 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
883 "Expected int type for TypeTraitExpr");
884 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
890 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
896 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
898 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
901 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
904 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
906 "ScalarExprEmitter: cxx pseudo destructor");
909 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
910 cgf.emitCXXThrowExpr(e);
914 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
923 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
925 ScalarConversionOpts opts = ScalarConversionOpts()) {
935 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
941 if (srcType == dstType) {
942 if (opts.emitImplicitIntegerSignChangeChecks)
943 cgf.getCIRGenModule().errorNYI(loc,
944 "implicit integer sign change checks");
951 mlir::Type mlirSrcType = src.getType();
956 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
958 mlir::Type mlirDstType = cgf.convertType(dstType);
961 !cgf.getContext().getLangOpts().NativeHalfType) {
963 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
964 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
965 cgf.getCIRGenModule().errorNYI(loc,
966 "cast via llvm.convert.from.fp16");
971 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
972 cgf.getCIRGenModule().errorNYI(loc,
973 "cast via llvm.convert.from.fp16");
976 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
978 srcType = cgf.getContext().FloatTy;
979 mlirSrcType = cgf.floatTy;
985 if (mlirSrcType == mlirDstType) {
986 if (opts.emitImplicitIntegerSignChangeChecks)
987 cgf.getCIRGenModule().errorNYI(loc,
988 "implicit integer sign change checks");
995 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
996 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
997 return builder.getNullPtr(dstPT, src.getLoc());
1003 return builder.createPtrToInt(src, mlirDstType);
1010 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1012 "Splatted expr doesn't match with vector element type?");
1014 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1019 cgf.getCIRGenModule().errorNYI(loc,
1020 "matrix type to matrix type conversion");
1024 "Internal error: conversion between matrix type and scalar type");
1027 mlir::Value res =
nullptr;
1028 mlir::Type resTy = mlirDstType;
1030 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1032 if (mlirDstType != resTy) {
1033 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1034 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1038 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1042 if (opts.emitImplicitIntegerTruncationChecks)
1043 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1045 if (opts.emitImplicitIntegerSignChangeChecks)
1046 cgf.getCIRGenModule().errorNYI(loc,
1047 "implicit integer sign change checks");
1052 BinOpInfo emitBinOps(
const BinaryOperator *e,
1053 QualType promotionType = QualType()) {
1054 ignoreResultAssign =
false;
1056 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1057 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1058 if (!promotionType.
isNull())
1059 result.fullType = promotionType;
1061 result.fullType = e->
getType();
1062 result.compType = result.fullType;
1063 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1064 result.compType = vecType->getElementType();
1068 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1073 mlir::Value emitMul(
const BinOpInfo &ops);
1074 mlir::Value emitDiv(
const BinOpInfo &ops);
1075 mlir::Value emitRem(
const BinOpInfo &ops);
1076 mlir::Value emitAdd(
const BinOpInfo &ops);
1077 mlir::Value emitSub(
const BinOpInfo &ops);
1078 mlir::Value emitShl(
const BinOpInfo &ops);
1079 mlir::Value emitShr(
const BinOpInfo &ops);
1080 mlir::Value emitAnd(
const BinOpInfo &ops);
1081 mlir::Value emitXor(
const BinOpInfo &ops);
1082 mlir::Value emitOr(
const BinOpInfo &ops);
1084 LValue emitCompoundAssignLValue(
1085 const CompoundAssignOperator *e,
1086 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1087 mlir::Value &result);
1089 emitCompoundAssign(
const CompoundAssignOperator *e,
1090 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1094 QualType getPromotionType(QualType ty) {
1095 const clang::ASTContext &ctx = cgf.getContext();
1096 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1097 QualType elementTy = complexTy->getElementType();
1103 if (
auto *vt = ty->
getAs<VectorType>()) {
1104 unsigned numElements = vt->getNumElements();
1107 return cgf.getContext().FloatTy;
1114#define HANDLEBINOP(OP) \
1115 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1116 QualType promotionTy = getPromotionType(e->getType()); \
1117 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1118 if (result && !promotionTy.isNull()) \
1119 result = emitUnPromotedValue(result, e->getType()); \
1122 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1123 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1139 ignoreResultAssign =
false;
1145 auto clangCmpToCIRCmp =
1149 return cir::CmpOpKind::lt;
1151 return cir::CmpOpKind::gt;
1153 return cir::CmpOpKind::le;
1155 return cir::CmpOpKind::ge;
1157 return cir::CmpOpKind::eq;
1159 return cir::CmpOpKind::ne;
1161 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1173 BinOpInfo boInfo = emitBinOps(e);
1174 mlir::Value lhs = boInfo.lhs;
1175 mlir::Value rhs = boInfo.rhs;
1185 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1187 boInfo.lhs, boInfo.rhs);
1189 }
else if (boInfo.isFixedPointOp()) {
1192 result = builder.
getBool(
false, loc);
1196 mlir::isa<cir::PointerType>(lhs.getType()) &&
1197 mlir::isa<cir::PointerType>(rhs.getType())) {
1198 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1204 "Complex Comparison: can only be an equality comparison");
1210 mlir::Value lhsReal = Visit(e->
getLHS());
1211 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1219 mlir::Value rhsReal = Visit(e->
getRHS());
1220 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1232#define VISITCOMP(CODE) \
1233 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1243 const bool ignore = std::exchange(ignoreResultAssign,
false);
1258 rhs = Visit(e->
getRHS());
1268 if (lhs.isBitField()) {
1290 if (!lhs.isVolatile())
1294 return emitLoadOfLValue(lhs, e->
getExprLoc());
1297 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1298 cgf.emitIgnoredExpr(e->
getLHS());
1300 return Visit(e->
getRHS());
1303 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1305 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1307 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1309 mlir::Value lhs = Visit(e->
getLHS());
1310 mlir::Value rhs = Visit(e->
getRHS());
1312 auto cmpOpKind = cir::CmpOpKind::ne;
1313 mlir::Type resTy = cgf.convertType(e->
getType());
1314 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1315 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1316 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1317 return builder.createIntCast(vecOr, resTy);
1321 mlir::Type resTy = cgf.convertType(e->
getType());
1322 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1324 CIRGenFunction::ConditionalEvaluation eval(cgf);
1326 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1327 auto resOp = cir::TernaryOp::create(
1328 builder, loc, lhsCondV,
1329 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1330 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1331 b.getInsertionBlock()};
1332 cgf.curLexScope->setAsTernary();
1333 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1335 cir::YieldOp::create(
b, loc, res);
1338 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1339 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1340 b.getInsertionBlock()};
1342 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1343 cir::YieldOp::create(
b, loc, res.getRes());
1345 return maybePromoteBoolResult(resOp.getResult(), resTy);
1348 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1350 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1352 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1354 mlir::Value lhs = Visit(e->
getLHS());
1355 mlir::Value rhs = Visit(e->
getRHS());
1357 auto cmpOpKind = cir::CmpOpKind::ne;
1358 mlir::Type resTy = cgf.convertType(e->
getType());
1359 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1360 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1361 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1362 return builder.createIntCast(vecOr, resTy);
1366 mlir::Type resTy = cgf.convertType(e->
getType());
1367 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1369 CIRGenFunction::ConditionalEvaluation eval(cgf);
1371 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1372 auto resOp = cir::TernaryOp::create(
1373 builder, loc, lhsCondV,
1374 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1375 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1376 b.getInsertionBlock()};
1378 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1379 cir::YieldOp::create(
b, loc, res.getRes());
1382 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1383 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1384 b.getInsertionBlock()};
1386 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1388 cir::YieldOp::create(
b, loc, res);
1391 return maybePromoteBoolResult(resOp.getResult(), resTy);
1394 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1395 return emitLoadOfLValue(e);
1398 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1399 return emitLoadOfLValue(e);
1403 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1404 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1408 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1412 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1414 "ScalarExprEmitter: objc string literal");
1417 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1418 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1421 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1423 "ScalarExprEmitter: objc array literal");
1426 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1428 "ScalarExprEmitter: objc dictionary literal");
1451 mlir::Type srcTy = src.
getType();
1455 return builder.createBitcast(src, dstTy);
1460 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1468 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1472 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1479 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1483 return builder.createIntToPtr(src, dstTy);
1486 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1487 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1488 mlir::Type srcTy = src.getType();
1489 mlir::Type dstTy = cgf.convertType(e->
getType());
1501 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1507 if (numElementsSrc == 3 && numElementsDst != 3) {
1509 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1510 "numElemsDst != 3");
1517 if (numElementsSrc != 3 && numElementsDst == 3) {
1519 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc != 3, "
1527 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1528 return cgf.emitAtomicExpr(e).getValue();
1532LValue ScalarExprEmitter::emitCompoundAssignLValue(
1534 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1535 mlir::Value &result) {
1546 if (promotionTypeCR.
isNull())
1550 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1552 if (!promotionTypeRHS.
isNull())
1555 opInfo.rhs = Visit(e->
getRHS());
1557 opInfo.fullType = promotionTypeCR;
1558 opInfo.compType = opInfo.fullType;
1559 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1560 opInfo.compType = vecType->getElementType();
1569 if (lhsTy->
getAs<AtomicType>()) {
1570 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1574 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1576 CIRGenFunction::SourceLocRAIIObject sourceloc{
1579 if (!promotionTypeLHS.
isNull())
1580 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1582 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1586 result = (this->*func)(opInfo);
1590 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1591 ScalarConversionOpts(cgf.
sanOpts));
1597 if (lhsLV.isBitField())
1608mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1612 cir::CastKind castOpKind;
1614 case CK_FloatingComplexToReal:
1615 castOpKind = cir::CastKind::float_complex_to_real;
1617 case CK_IntegralComplexToReal:
1618 castOpKind = cir::CastKind::int_complex_to_real;
1620 case CK_FloatingComplexToBoolean:
1621 castOpKind = cir::CastKind::float_complex_to_bool;
1623 case CK_IntegralComplexToBoolean:
1624 castOpKind = cir::CastKind::int_complex_to_bool;
1627 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1633mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1634 QualType promotionType) {
1636 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1637 switch (bo->getOpcode()) {
1638#define HANDLE_BINOP(OP) \
1640 return emit##OP(emitBinOps(bo, promotionType));
1649 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1650 switch (uo->getOpcode()) {
1653 return VisitRealImag(uo, promotionType);
1655 return VisitUnaryMinus(uo, promotionType);
1657 return VisitUnaryPlus(uo, promotionType);
1662 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1664 if (!promotionType.
isNull())
1665 return emitPromotedValue(result, promotionType);
1666 return emitUnPromotedValue(result, e->
getType());
1671mlir::Value ScalarExprEmitter::emitCompoundAssign(
1672 const CompoundAssignOperator *e,
1673 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1675 bool ignore = std::exchange(ignoreResultAssign,
false);
1677 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1688 if (!lhs.isVolatile())
1692 return emitLoadOfLValue(lhs, e->
getExprLoc());
1695mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1696 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1711#define COMPOUND_OP(Op) \
1712 case BO_##Op##Assign: \
1713 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1750 llvm_unreachable(
"Not valid compound assignment operators");
1752 llvm_unreachable(
"Unhandled compound assignment operator");
1757 bool ignoreResultAssign) {
1759 "Invalid scalar expression to emit");
1762 .Visit(
const_cast<Expr *
>(e));
1767 if (!promotionType.
isNull())
1782static std::optional<QualType>
1786 return std::nullopt;
1791 return std::nullopt;
1804 const BinOpInfo &op) {
1806 "Expected a unary or binary operator");
1810 if (!op.mayHaveIntegerOverflow())
1814 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1815 return !uo->canOverflow();
1820 std::optional<QualType> optionalLHSTy =
1825 std::optional<QualType> optionalRHSTy =
1835 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1842 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1843 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1848 const BinOpInfo &op,
1849 bool isSubtraction) {
1854 mlir::Value pointer = op.lhs;
1855 Expr *pointerOperand =
expr->getLHS();
1856 mlir::Value
index = op.rhs;
1857 Expr *indexOperand =
expr->getRHS();
1863 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1864 std::swap(pointer,
index);
1865 std::swap(pointerOperand, indexOperand);
1867 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1868 "Need a pointer operand");
1869 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1904 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1914 numElements.getType());
1925 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
1930 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1932 pointer.getType(), pointer,
index);
1936 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
1937 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
1940mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1941 const mlir::Location loc = cgf.
getLoc(ops.loc);
1944 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1945 case LangOptions::SOB_Defined:
1946 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1947 return builder.
createMul(loc, ops.lhs, ops.rhs);
1949 case LangOptions::SOB_Undefined:
1950 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1953 case LangOptions::SOB_Trapping:
1965 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1967 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1969 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1970 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1971 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1974 if (ops.isFixedPointOp()) {
1980 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1983mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1984 return cir::DivOp::create(builder, cgf.
getLoc(ops.loc),
1987mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1988 return cir::RemOp::create(builder, cgf.
getLoc(ops.loc),
1992mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1993 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1994 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1997 const mlir::Location loc = cgf.
getLoc(ops.loc);
2000 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2001 case LangOptions::SOB_Defined:
2002 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2003 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2005 case LangOptions::SOB_Undefined:
2006 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2009 case LangOptions::SOB_Trapping:
2022 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2024 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2026 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2027 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2028 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2031 if (ops.isFixedPointOp()) {
2037 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2040mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2041 const mlir::Location loc = cgf.
getLoc(ops.loc);
2043 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2046 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2047 case LangOptions::SOB_Defined: {
2048 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2049 return builder.
createSub(loc, ops.lhs, ops.rhs);
2052 case LangOptions::SOB_Undefined:
2053 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2056 case LangOptions::SOB_Trapping:
2070 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2072 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2074 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2075 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2076 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2079 if (ops.isFixedPointOp()) {
2085 return builder.
createSub(loc, ops.lhs, ops.rhs);
2090 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2102 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2106mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2108 if (ops.isFixedPointOp()) {
2118 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2122 bool sanitizeUnsignedBase =
2123 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2125 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2126 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2131 else if ((sanitizeBase || sanitizeExponent) &&
2132 mlir::isa<cir::IntType>(ops.lhs.getType()))
2138mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2140 if (ops.isFixedPointOp()) {
2153 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2154 mlir::isa<cir::IntType>(ops.lhs.getType()))
2162mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2163 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2165mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2166 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2168mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2169 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2176mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2178 QualType destTy = ce->
getType();
2183 ignoreResultAssign =
false;
2186 case clang::CK_Dependent:
2187 llvm_unreachable(
"dependent cast kind in CIR gen!");
2188 case clang::CK_BuiltinFnToFnPtr:
2189 llvm_unreachable(
"builtin functions are handled elsewhere");
2190 case CK_LValueBitCast:
2191 case CK_LValueToRValueBitCast: {
2193 Address sourceAddr = sourceLVal.getAddress();
2199 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2202 case CK_CPointerToObjCPointerCast:
2203 case CK_BlockPointerToObjCPointerCast:
2204 case CK_AnyPointerToBlockPointerCast:
2206 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2211 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2213 "sanitizer support");
2217 "strict vtable pointers");
2243 case CK_AddressSpaceConversion: {
2244 Expr::EvalResult result;
2258 case CK_AtomicToNonAtomic:
2259 case CK_NonAtomicToAtomic:
2260 case CK_UserDefinedConversion:
2261 return Visit(
const_cast<Expr *
>(subExpr));
2265 case CK_IntegralToPointer: {
2267 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2276 : cir::CastKind::integral,
2281 "IntegralToPointer: strict vtable pointers");
2288 case CK_BaseToDerived: {
2290 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2302 case CK_UncheckedDerivedToBase:
2303 case CK_DerivedToBase: {
2314 case CK_ArrayToPointerDecay:
2317 case CK_NullToPointer: {
2327 case CK_NullToMemberPointer: {
2333 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2339 case CK_ReinterpretMemberPointer: {
2340 mlir::Value src = Visit(subExpr);
2344 case CK_BaseToDerivedMemberPointer:
2345 case CK_DerivedToBaseMemberPointer: {
2346 mlir::Value src = Visit(subExpr);
2350 QualType derivedTy =
2351 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2352 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2353 NestedNameSpecifier qualifier = mpType->getQualifier();
2354 assert(qualifier &&
"member pointer without class qualifier");
2355 const Type *qualifierType = qualifier.getAsType();
2356 assert(qualifierType &&
"member pointer qualifier is not a type");
2363 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2366 if (
kind == CK_BaseToDerivedMemberPointer)
2367 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2369 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2372 if (
kind == CK_BaseToDerivedMemberPointer)
2373 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2375 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2379 case CK_LValueToRValue:
2381 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2382 return Visit(
const_cast<Expr *
>(subExpr));
2384 case CK_IntegralCast: {
2385 ScalarConversionOpts opts;
2386 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2387 if (!ice->isPartOfExplicitCast())
2388 opts = ScalarConversionOpts(cgf.
sanOpts);
2390 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2394 case CK_FloatingComplexToReal:
2395 case CK_IntegralComplexToReal:
2396 case CK_FloatingComplexToBoolean:
2397 case CK_IntegralComplexToBoolean: {
2403 case CK_FloatingRealToComplex:
2404 case CK_FloatingComplexCast:
2405 case CK_IntegralRealToComplex:
2406 case CK_IntegralComplexCast:
2407 case CK_IntegralComplexToFloatingComplex:
2408 case CK_FloatingComplexToIntegralComplex:
2409 llvm_unreachable(
"scalar cast to non-scalar value");
2411 case CK_PointerToIntegral: {
2412 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2415 "strict vtable pointers");
2422 case CK_IntegralToFloating:
2423 case CK_FloatingToIntegral:
2424 case CK_FloatingCast:
2425 case CK_FixedPointToFloating:
2426 case CK_FloatingToFixedPoint: {
2427 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2429 "fixed point casts");
2432 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2433 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2437 case CK_IntegralToBoolean:
2438 return emitIntToBoolConversion(Visit(subExpr),
2441 case CK_PointerToBoolean:
2442 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2443 case CK_FloatingToBoolean:
2444 return emitFloatToBoolConversion(Visit(subExpr),
2446 case CK_MemberPointerToBoolean: {
2447 mlir::Value memPtr = Visit(subExpr);
2449 cir::CastKind::member_ptr_to_bool, memPtr,
2453 case CK_VectorSplat: {
2455 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2456 return cir::VecSplatOp::create(builder,
2460 case CK_FunctionToPointerDecay:
2470mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2472 return emitLoadOfLValue(e);
2479mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2484 Expr::EvalResult result;
2486 llvm::APSInt value = result.
Val.
getInt();
2496 return builder.
getBool(value.getBoolValue(), loc);
2499 return emitLoadOfLValue(e);
2502mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2503 const unsigned numInitElements = e->
getNumInits();
2505 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2506 assert((ignore ==
false ||
2508 "init list ignored");
2516 const auto vectorType =
2519 SmallVector<mlir::Value, 16> elements;
2520 for (Expr *init : e->
inits()) {
2521 elements.push_back(Visit(init));
2525 if (numInitElements < vectorType.getSize()) {
2528 std::fill_n(std::back_inserter(elements),
2529 vectorType.getSize() - numInitElements, zeroValue);
2532 return cir::VecCreateOp::create(cgf.
getBuilder(),
2538 if (numInitElements == 0)
2549 "Invalid scalar expression to emit");
2551 .emitScalarConversion(src, srcTy, dstTy, loc);
2559 "Invalid complex -> scalar conversion");
2564 ? cir::CastKind::float_complex_to_bool
2565 : cir::CastKind::int_complex_to_bool;
2570 ? cir::CastKind::float_complex_to_real
2571 : cir::CastKind::int_complex_to_real;
2577mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2584 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2586 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2587 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2601mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2606 llvm::APSInt value = evalResult.
Val.
getInt();
2612 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2616mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2618 mlir::Value result = VisitRealImag(e, promotionTy);
2619 if (result && !promotionTy.
isNull())
2620 result = emitUnPromotedValue(result, e->
getType());
2624mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2626 mlir::Value result = VisitRealImag(e, promotionTy);
2627 if (result && !promotionTy.
isNull())
2628 result = emitUnPromotedValue(result, e->
getType());
2632mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2633 QualType promotionTy) {
2636 "Invalid UnaryOp kind for ComplexType Real or Imag");
2658 mlir::Value operand = promotionTy.
isNull()
2660 : cgf.emitPromotedScalarExpr(op, promotionTy);
2666 mlir::Value operand;
2669 operand = cir::LoadOp::create(builder, loc, operand);
2670 }
else if (!promotionTy.
isNull()) {
2680mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2681 const UnaryExprOrTypeTraitExpr *e) {
2685 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2686 if (
const VariableArrayType *vat =
2691 bool evaluateExtent =
true;
2692 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2694 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2697 if (evaluateExtent) {
2708 if (
kind == UETT_CountOf)
2713 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2714 mlir::Value numElts = vlaSize.
numElts;
2718 if (!eltSize.
isOne()) {
2720 mlir::Value eltSizeValue =
2723 return builder.
createMul(loc, eltSizeValue, numElts,
2730 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2737 }
else if (e->
getKind() == UETT_VectorElements) {
2739 if (vecTy.getIsScalable()) {
2742 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2749 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2774mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2775 const AbstractConditionalOperator *e) {
2778 ignoreResultAssign =
false;
2781 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2783 Expr *condExpr = e->
getCond();
2791 Expr *live = lhsExpr, *dead = rhsExpr;
2793 std::swap(live, dead);
2799 mlir::Value result = Visit(live);
2806 loc, cir::PoisonAttr::get(builder.getContext(),
2814 QualType condType = condExpr->
getType();
2823 mlir::Value lhsValue = Visit(lhsExpr);
2824 mlir::Value rhsValue = Visit(rhsExpr);
2826 mlir::Type vecTy = convertType(condType);
2827 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
2828 auto testMSB = cir::VecCmpOp::create(
2829 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
2831 mlir::Value tmp2 = builder.
createNot(tmp);
2834 mlir::Value rhsTmp = rhsValue;
2835 mlir::Value lhsTmp = lhsValue;
2836 bool wasCast =
false;
2838 if (cir::isAnyFloatingPointType(rhsVecTy.getElementType())) {
2844 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
2845 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
2846 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
2855 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2859 mlir::Value condValue = Visit(condExpr);
2860 mlir::Value lhsValue = Visit(lhsExpr);
2861 mlir::Value rhsValue = Visit(rhsExpr);
2862 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2871 bool lhsIsVoid =
false;
2875 mlir::Value lhs = Visit(lhsExpr);
2881 mlir::Value rhs = Visit(rhsExpr);
2883 assert(!rhs &&
"lhs and rhs types must match");
2891 CIRGenFunction::ConditionalEvaluation eval(cgf);
2892 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2893 mlir::Type yieldTy{};
2895 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2896 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2903 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
2905 eval.beginEvaluation();
2906 branch = Visit(
expr);
2907 eval.endEvaluation();
2908 branchCleanups.forceCleanup({&branch});
2912 yieldTy = branch.getType();
2913 cir::YieldOp::create(
b, loc, branch);
2917 insertPoints.push_back(
b.saveInsertionPoint());
2921 mlir::Value result = cir::TernaryOp::create(
2922 builder, loc, condV,
2924 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2925 emitBranch(
b, loc, lhsExpr);
2928 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2929 emitBranch(
b, loc, rhsExpr);
2933 if (!insertPoints.empty()) {
2939 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2940 mlir::OpBuilder::InsertionGuard guard(builder);
2941 builder.restoreInsertionPoint(toInsert);
2944 if (mlir::isa<cir::VoidType>(yieldTy)) {
2945 cir::YieldOp::create(builder, loc);
2948 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
__device__ __2f16 float __ockl_bool s
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 createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
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)
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 createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
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::Value value, bool nsw=false)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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.