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 "ScalarExprEmitter: fixed point literal");
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());
249 auto init = cir::IntAttr::get(ty, e->
getValue());
250 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()), init);
253 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
257 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
264 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
268 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
270 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
271 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
274 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
275 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: pseudo object");
278 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
280 "ScalarExprEmitter: sycl unique stable name");
283 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
285 auto it = e->
begin();
286 llvm::APInt value = (*it)->getValue();
287 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
290 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
292 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
296 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
299 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
300 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
303 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
304 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
307 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
308 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
311 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
312 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
315 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
316 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
319 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
321 "ScalarExprEmitter: objc availability check");
325 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
327 "ScalarExprEmitter: matrix subscript");
331 mlir::Value VisitCastExpr(
CastExpr *e);
332 mlir::Value VisitCallExpr(
const CallExpr *e);
334 mlir::Value VisitStmtExpr(StmtExpr *e) {
335 CIRGenFunction::StmtExprEvaluation eval(cgf);
343 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
345 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
349 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
350 ignoreResultAssign =
false;
356 const mlir::Value vecValue = Visit(e->
getBase());
357 const mlir::Value indexValue = Visit(e->
getIdx());
358 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
361 return emitLoadOfLValue(e);
364 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
367 mlir::Value inputVec = Visit(e->
getExpr(0));
368 mlir::Value indexVec = Visit(e->
getExpr(1));
369 return cir::VecShuffleDynamicOp::create(
370 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
373 mlir::Value vec1 = Visit(e->
getExpr(0));
374 mlir::Value vec2 = Visit(e->
getExpr(1));
379 SmallVector<mlir::Attribute, 8> indices;
382 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
388 return cir::VecShuffleOp::create(cgf.builder,
390 cgf.convertType(e->
getType()), vec1, vec2,
391 cgf.builder.getArrayAttr(indices));
394 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
397 return emitScalarConversion(Visit(e->
getSrcExpr()),
402 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
404 mlir::Value VisitMatrixElementExpr(Expr *e) {
405 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
409 mlir::Value VisitMemberExpr(MemberExpr *e);
411 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
412 return emitLoadOfLValue(e);
415 mlir::Value VisitInitListExpr(InitListExpr *e);
417 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
419 "ScalarExprEmitter: array init index");
423 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
427 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
428 return VisitCastExpr(e);
431 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
432 return cgf.cgm.emitNullConstant(e->
getType(),
437 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
440 return cgf.getBuilder().createPtrToBoolCast(v);
443 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
444 cir::BoolType boolTy = builder.getBoolTy();
445 return cir::CastOp::create(builder, loc, boolTy,
446 cir::CastKind::float_to_bool, src);
449 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
455 cir::BoolType boolTy = builder.getBoolTy();
456 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
462 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
463 mlir::Location loc) {
464 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
467 return emitFloatToBoolConversion(src, loc);
469 if (llvm::isa<MemberPointerType>(srcType)) {
470 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
471 return builder.getFalse(loc);
475 return emitIntToBoolConversion(src, loc);
477 assert(::mlir::isa<cir::PointerType>(src.getType()));
478 return emitPointerToBoolConversion(src, srcType);
483 struct ScalarConversionOpts {
484 bool treatBooleanAsSigned;
485 bool emitImplicitIntegerTruncationChecks;
486 bool emitImplicitIntegerSignChangeChecks;
488 ScalarConversionOpts()
489 : treatBooleanAsSigned(
false),
490 emitImplicitIntegerTruncationChecks(
false),
491 emitImplicitIntegerSignChangeChecks(
false) {}
493 ScalarConversionOpts(clang::SanitizerSet sanOpts)
494 : treatBooleanAsSigned(
false),
495 emitImplicitIntegerTruncationChecks(
496 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
497 emitImplicitIntegerSignChangeChecks(
498 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
505 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
506 QualType dstType, mlir::Type srcTy,
507 mlir::Type dstTy, ScalarConversionOpts opts) {
509 "Internal error: matrix types not handled by this function.");
510 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
511 mlir::isa<mlir::IntegerType>(dstTy)) &&
512 "Obsolete code. Don't use mlir::IntegerType with CIR.");
514 mlir::Type fullDstTy = dstTy;
515 if (mlir::isa<cir::VectorType>(srcTy) &&
516 mlir::isa<cir::VectorType>(dstTy)) {
518 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
519 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
522 std::optional<cir::CastKind> castKind;
524 if (mlir::isa<cir::BoolType>(srcTy)) {
525 if (opts.treatBooleanAsSigned)
526 cgf.getCIRGenModule().errorNYI(
"signed bool");
527 if (cgf.getBuilder().isInt(dstTy))
528 castKind = cir::CastKind::bool_to_int;
529 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
530 castKind = cir::CastKind::bool_to_float;
532 llvm_unreachable(
"Internal error: Cast to unexpected type");
533 }
else if (cgf.getBuilder().isInt(srcTy)) {
534 if (cgf.getBuilder().isInt(dstTy))
535 castKind = cir::CastKind::integral;
536 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
537 castKind = cir::CastKind::int_to_float;
539 llvm_unreachable(
"Internal error: Cast to unexpected type");
540 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
541 if (cgf.getBuilder().isInt(dstTy)) {
545 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
546 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
548 castKind = cir::CastKind::float_to_int;
549 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
551 return builder.createFloatingCast(src, fullDstTy);
553 llvm_unreachable(
"Internal error: Cast to unexpected type");
556 llvm_unreachable(
"Internal error: Cast from unexpected type");
559 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
560 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
565 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
569 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
574 "variably modified types in varargs");
577 return cgf.emitVAArg(ve);
580 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
584 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
586 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
589 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
591 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
593 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
595 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
597 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
599 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
601 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
603 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
605 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
606 cir::UnaryOpKind
kind,
bool isPre) {
607 if (cgf.getLangOpts().OpenMP)
615 if (
type->getAs<AtomicType>()) {
619 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
622 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
635 if (
kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
636 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
637 }
else if (
type->isIntegerType()) {
638 QualType promotedType;
639 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
640 if (cgf.getContext().isPromotableIntegerType(
type)) {
641 promotedType = cgf.getContext().getPromotedIntegerType(
type);
642 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
643 canPerformLossyDemotionCheck =
true;
644 canPerformLossyDemotionCheck &=
645 cgf.getContext().getCanonicalType(
type) !=
646 cgf.getContext().getCanonicalType(promotedType);
647 canPerformLossyDemotionCheck &=
654 (!canPerformLossyDemotionCheck ||
655 type->isSignedIntegerOrEnumerationType() ||
657 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
658 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
659 "The following check expects that if we do promotion to different "
660 "underlying canonical type, at least one of the types (either "
661 "base or promoted) will be signed, or the bitwidths will match.");
666 value = emitIncDecConsiderOverflowBehavior(e, value,
kind);
668 cir::UnaryOpKind
kind =
669 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
671 value = emitUnaryOp(e,
kind, input,
false);
673 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
674 QualType
type = ptr->getPointeeType();
675 if (cgf.getContext().getAsVariableArrayType(
type)) {
677 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
682 CIRGenBuilderTy &builder = cgf.getBuilder();
683 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
684 mlir::Value amt = builder.getSInt32(amount, loc);
686 value = builder.createPtrStride(loc, value, amt);
688 }
else if (
type->isVectorType()) {
691 }
else if (
type->isRealFloatingType()) {
692 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
694 if (
type->isHalfType() &&
695 !cgf.getContext().getLangOpts().NativeHalfType) {
700 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
704 (
kind == cir::UnaryOpKind::Inc ||
kind == cir::UnaryOpKind::Dec) &&
705 "Invalid UnaryOp kind");
706 value = emitUnaryOp(e,
kind, value);
708 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
711 }
else if (
type->isFixedPointType()) {
712 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
715 assert(
type->castAs<ObjCObjectPointerType>());
716 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
720 CIRGenFunction::SourceLocRAIIObject sourceloc{
725 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
727 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
731 return isPre ? value : input;
734 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
736 cir::UnaryOpKind
kind) {
737 assert((
kind == cir::UnaryOpKind::Inc ||
kind == cir::UnaryOpKind::Dec) &&
738 "Invalid UnaryOp kind");
739 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
740 case LangOptions::SOB_Defined:
741 return emitUnaryOp(e,
kind, inVal,
false);
742 case LangOptions::SOB_Undefined:
744 return emitUnaryOp(e,
kind, inVal,
true);
745 case LangOptions::SOB_Trapping:
747 return emitUnaryOp(e,
kind, 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) {
770 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
771 if (result && !promotionType.
isNull())
772 return emitUnPromotedValue(result, e->
getType());
776 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
779 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
780 if (result && !promotionType.
isNull())
781 return emitUnPromotedValue(result, e->
getType());
785 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
786 cir::UnaryOpKind
kind,
787 QualType promotionType) {
788 ignoreResultAssign =
false;
790 if (!promotionType.
isNull())
791 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
798 bool nsw =
kind == cir::UnaryOpKind::Minus &&
800 cgf.getLangOpts().getSignedOverflowBehavior() !=
801 LangOptions::SOB_Defined;
805 return emitUnaryOp(e,
kind, operand, nsw);
808 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind
kind,
809 mlir::Value input,
bool nsw =
false) {
810 return builder.createOrFold<cir::UnaryOp>(
815 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
816 ignoreResultAssign =
false;
818 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
821 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
823 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
824 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
825 mlir::Value VisitRealImag(
const UnaryOperator *e,
826 QualType promotionType = QualType());
828 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
833 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
835 "ScalarExprEmitter: materialize temporary");
838 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
839 ASTContext &ctx = cgf.getContext();
842 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
844 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
845 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
848 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
849 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
852 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
853 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
857 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
859 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
860 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
861 return cgf.emitCXXNewExpr(e);
863 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
864 cgf.emitCXXDeleteExpr(e);
867 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
873 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
878 "Expected int type for TypeTraitExpr");
879 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
885 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
891 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
893 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
896 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
899 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
901 "ScalarExprEmitter: cxx pseudo destructor");
904 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
905 cgf.emitCXXThrowExpr(e);
909 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
918 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
920 ScalarConversionOpts opts = ScalarConversionOpts()) {
930 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
936 if (srcType == dstType) {
937 if (opts.emitImplicitIntegerSignChangeChecks)
938 cgf.getCIRGenModule().errorNYI(loc,
939 "implicit integer sign change checks");
946 mlir::Type mlirSrcType = src.getType();
951 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
953 mlir::Type mlirDstType = cgf.convertType(dstType);
956 !cgf.getContext().getLangOpts().NativeHalfType) {
958 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
959 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
960 cgf.getCIRGenModule().errorNYI(loc,
961 "cast via llvm.convert.from.fp16");
966 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
967 cgf.getCIRGenModule().errorNYI(loc,
968 "cast via llvm.convert.from.fp16");
971 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
973 srcType = cgf.getContext().FloatTy;
974 mlirSrcType = cgf.floatTy;
980 if (mlirSrcType == mlirDstType) {
981 if (opts.emitImplicitIntegerSignChangeChecks)
982 cgf.getCIRGenModule().errorNYI(loc,
983 "implicit integer sign change checks");
990 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
991 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
992 return builder.getNullPtr(dstPT, src.getLoc());
998 return builder.createPtrToInt(src, mlirDstType);
1005 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1007 "Splatted expr doesn't match with vector element type?");
1009 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1014 cgf.getCIRGenModule().errorNYI(loc,
1015 "matrix type to matrix type conversion");
1019 "Internal error: conversion between matrix type and scalar type");
1022 mlir::Value res =
nullptr;
1023 mlir::Type resTy = mlirDstType;
1025 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1027 if (mlirDstType != resTy) {
1028 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1029 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1033 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1037 if (opts.emitImplicitIntegerTruncationChecks)
1038 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1040 if (opts.emitImplicitIntegerSignChangeChecks)
1041 cgf.getCIRGenModule().errorNYI(loc,
1042 "implicit integer sign change checks");
1047 BinOpInfo emitBinOps(
const BinaryOperator *e,
1048 QualType promotionType = QualType()) {
1049 ignoreResultAssign =
false;
1051 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1052 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1053 if (!promotionType.
isNull())
1054 result.fullType = promotionType;
1056 result.fullType = e->
getType();
1057 result.compType = result.fullType;
1058 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1059 result.compType = vecType->getElementType();
1064 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1069 mlir::Value emitMul(
const BinOpInfo &ops);
1070 mlir::Value emitDiv(
const BinOpInfo &ops);
1071 mlir::Value emitRem(
const BinOpInfo &ops);
1072 mlir::Value emitAdd(
const BinOpInfo &ops);
1073 mlir::Value emitSub(
const BinOpInfo &ops);
1074 mlir::Value emitShl(
const BinOpInfo &ops);
1075 mlir::Value emitShr(
const BinOpInfo &ops);
1076 mlir::Value emitAnd(
const BinOpInfo &ops);
1077 mlir::Value emitXor(
const BinOpInfo &ops);
1078 mlir::Value emitOr(
const BinOpInfo &ops);
1080 LValue emitCompoundAssignLValue(
1081 const CompoundAssignOperator *e,
1082 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1083 mlir::Value &result);
1085 emitCompoundAssign(
const CompoundAssignOperator *e,
1086 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1090 QualType getPromotionType(QualType ty) {
1091 const clang::ASTContext &ctx = cgf.getContext();
1092 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1093 QualType elementTy = complexTy->getElementType();
1099 if (
auto *vt = ty->
getAs<VectorType>()) {
1100 unsigned numElements = vt->getNumElements();
1103 return cgf.getContext().FloatTy;
1110#define HANDLEBINOP(OP) \
1111 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1112 QualType promotionTy = getPromotionType(e->getType()); \
1113 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1114 if (result && !promotionTy.isNull()) \
1115 result = emitUnPromotedValue(result, e->getType()); \
1118 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1119 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1135 ignoreResultAssign =
false;
1141 auto clangCmpToCIRCmp =
1145 return cir::CmpOpKind::lt;
1147 return cir::CmpOpKind::gt;
1149 return cir::CmpOpKind::le;
1151 return cir::CmpOpKind::ge;
1153 return cir::CmpOpKind::eq;
1155 return cir::CmpOpKind::ne;
1157 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1169 BinOpInfo boInfo = emitBinOps(e);
1170 mlir::Value lhs = boInfo.lhs;
1171 mlir::Value rhs = boInfo.rhs;
1181 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1183 boInfo.lhs, boInfo.rhs);
1185 }
else if (boInfo.isFixedPointOp()) {
1188 result = builder.
getBool(
false, loc);
1192 mlir::isa<cir::PointerType>(lhs.getType()) &&
1193 mlir::isa<cir::PointerType>(rhs.getType())) {
1194 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1201 BinOpInfo boInfo = emitBinOps(e);
1202 mlir::Value lhs = boInfo.lhs;
1208 mlir::Value rhs = boInfo.rhs;
1222#define VISITCOMP(CODE) \
1223 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1233 const bool ignore = std::exchange(ignoreResultAssign,
false);
1248 rhs = Visit(e->
getRHS());
1258 if (lhs.isBitField()) {
1280 if (!lhs.isVolatile())
1284 return emitLoadOfLValue(lhs, e->
getExprLoc());
1287 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1288 cgf.emitIgnoredExpr(e->
getLHS());
1290 return Visit(e->
getRHS());
1293 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1295 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1297 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1299 mlir::Value lhs = Visit(e->
getLHS());
1300 mlir::Value rhs = Visit(e->
getRHS());
1302 auto cmpOpKind = cir::CmpOpKind::ne;
1303 mlir::Type resTy = cgf.convertType(e->
getType());
1304 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1305 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1306 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1307 return builder.createIntCast(vecOr, resTy);
1311 mlir::Type resTy = cgf.convertType(e->
getType());
1312 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1314 CIRGenFunction::ConditionalEvaluation eval(cgf);
1316 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1317 auto resOp = cir::TernaryOp::create(
1318 builder, loc, lhsCondV,
1319 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1320 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1321 b.getInsertionBlock()};
1322 cgf.curLexScope->setAsTernary();
1323 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1325 cir::YieldOp::create(
b, loc, res);
1326 if (res.getParentBlock() != builder.getInsertionBlock())
1329 "ScalarExprEmitter: VisitBinLAnd ternary with cleanup");
1332 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1333 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1334 b.getInsertionBlock()};
1336 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1337 cir::YieldOp::create(
b, loc, res.getRes());
1339 return maybePromoteBoolResult(resOp.getResult(), resTy);
1342 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1344 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1346 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1348 mlir::Value lhs = Visit(e->
getLHS());
1349 mlir::Value rhs = Visit(e->
getRHS());
1351 auto cmpOpKind = cir::CmpOpKind::ne;
1352 mlir::Type resTy = cgf.convertType(e->
getType());
1353 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1354 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1355 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1356 return builder.createIntCast(vecOr, resTy);
1360 mlir::Type resTy = cgf.convertType(e->
getType());
1361 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1363 CIRGenFunction::ConditionalEvaluation eval(cgf);
1365 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1366 auto resOp = cir::TernaryOp::create(
1367 builder, loc, lhsCondV,
1368 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1369 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1370 b.getInsertionBlock()};
1372 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1373 cir::YieldOp::create(
b, loc, res.getRes());
1376 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1377 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1378 b.getInsertionBlock()};
1380 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1382 cir::YieldOp::create(
b, loc, res);
1383 if (res.getParentBlock() != builder.getInsertionBlock())
1386 "ScalarExprEmitter: VisitBinLOr ternary with cleanup");
1389 return maybePromoteBoolResult(resOp.getResult(), resTy);
1392 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1393 return emitLoadOfLValue(e);
1396 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1397 return emitLoadOfLValue(e);
1401 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1402 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1406 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1410 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1412 "ScalarExprEmitter: objc string literal");
1415 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1416 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1419 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1421 "ScalarExprEmitter: objc array literal");
1424 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1426 "ScalarExprEmitter: objc dictionary literal");
1430 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1431 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1435 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1436 return cgf.emitAtomicExpr(e).getValue();
1440LValue ScalarExprEmitter::emitCompoundAssignLValue(
1442 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1443 mlir::Value &result) {
1454 if (promotionTypeCR.
isNull())
1458 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1460 if (!promotionTypeRHS.
isNull())
1463 opInfo.rhs = Visit(e->
getRHS());
1465 opInfo.fullType = promotionTypeCR;
1466 opInfo.compType = opInfo.fullType;
1467 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1468 opInfo.compType = vecType->getElementType();
1477 if (lhsTy->
getAs<AtomicType>()) {
1478 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1482 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1484 CIRGenFunction::SourceLocRAIIObject sourceloc{
1487 if (!promotionTypeLHS.
isNull())
1488 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1490 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1494 result = (this->*func)(opInfo);
1498 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1499 ScalarConversionOpts(cgf.
sanOpts));
1505 if (lhsLV.isBitField())
1516mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1520 cir::CastKind castOpKind;
1522 case CK_FloatingComplexToReal:
1523 castOpKind = cir::CastKind::float_complex_to_real;
1525 case CK_IntegralComplexToReal:
1526 castOpKind = cir::CastKind::int_complex_to_real;
1528 case CK_FloatingComplexToBoolean:
1529 castOpKind = cir::CastKind::float_complex_to_bool;
1531 case CK_IntegralComplexToBoolean:
1532 castOpKind = cir::CastKind::int_complex_to_bool;
1535 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1541mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1542 QualType promotionType) {
1544 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1545 switch (bo->getOpcode()) {
1546#define HANDLE_BINOP(OP) \
1548 return emit##OP(emitBinOps(bo, promotionType));
1557 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1558 switch (uo->getOpcode()) {
1561 return VisitRealImag(uo, promotionType);
1563 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1565 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1570 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1572 if (!promotionType.
isNull())
1573 return emitPromotedValue(result, promotionType);
1574 return emitUnPromotedValue(result, e->
getType());
1579mlir::Value ScalarExprEmitter::emitCompoundAssign(
1580 const CompoundAssignOperator *e,
1581 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1583 bool ignore = std::exchange(ignoreResultAssign,
false);
1585 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1596 if (!lhs.isVolatile())
1600 return emitLoadOfLValue(lhs, e->
getExprLoc());
1603mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1604 CIRGenFunction::RunCleanupsScope cleanups(cgf);
1608 cleanups.forceCleanup({&v});
1619#define COMPOUND_OP(Op) \
1620 case BO_##Op##Assign: \
1621 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1658 llvm_unreachable(
"Not valid compound assignment operators");
1660 llvm_unreachable(
"Unhandled compound assignment operator");
1665 bool ignoreResultAssign) {
1667 "Invalid scalar expression to emit");
1670 .Visit(
const_cast<Expr *
>(e));
1675 if (!promotionType.
isNull())
1690static std::optional<QualType>
1694 return std::nullopt;
1699 return std::nullopt;
1712 const BinOpInfo &op) {
1714 "Expected a unary or binary operator");
1718 if (!op.mayHaveIntegerOverflow())
1722 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1723 return !uo->canOverflow();
1728 std::optional<QualType> optionalLHSTy =
1733 std::optional<QualType> optionalRHSTy =
1743 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1750 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1751 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1756 const BinOpInfo &op,
1757 bool isSubtraction) {
1762 mlir::Value pointer = op.lhs;
1763 Expr *pointerOperand =
expr->getLHS();
1764 mlir::Value
index = op.rhs;
1765 Expr *indexOperand =
expr->getRHS();
1771 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1772 std::swap(pointer,
index);
1773 std::swap(pointerOperand, indexOperand);
1775 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1776 "Need a pointer operand");
1777 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1812 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1823 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1825 pointer.getType(), pointer,
index);
1828mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1829 const mlir::Location loc = cgf.
getLoc(ops.loc);
1831 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1832 case LangOptions::SOB_Defined:
1833 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1834 return builder.
createMul(loc, ops.lhs, ops.rhs);
1836 case LangOptions::SOB_Undefined:
1837 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1840 case LangOptions::SOB_Trapping:
1852 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1854 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1856 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1857 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1858 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1861 if (ops.isFixedPointOp()) {
1867 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1870mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1871 return cir::DivOp::create(builder, cgf.
getLoc(ops.loc),
1874mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1875 return cir::RemOp::create(builder, cgf.
getLoc(ops.loc),
1879mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1880 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1881 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1884 const mlir::Location loc = cgf.
getLoc(ops.loc);
1886 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1887 case LangOptions::SOB_Defined:
1888 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1889 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1891 case LangOptions::SOB_Undefined:
1892 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1895 case LangOptions::SOB_Trapping:
1908 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1910 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1912 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1913 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1914 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
1917 if (ops.isFixedPointOp()) {
1923 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1926mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1927 const mlir::Location loc = cgf.
getLoc(ops.loc);
1929 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1931 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1932 case LangOptions::SOB_Defined: {
1933 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1934 return builder.
createSub(loc, ops.lhs, ops.rhs);
1937 case LangOptions::SOB_Undefined:
1938 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1941 case LangOptions::SOB_Trapping:
1955 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1957 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1959 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1960 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1961 return builder.
createFSub(loc, ops.lhs, ops.rhs);
1964 if (ops.isFixedPointOp()) {
1970 return builder.
createSub(loc, ops.lhs, ops.rhs);
1975 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1987 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1991mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1993 if (ops.isFixedPointOp()) {
2003 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2007 bool sanitizeUnsignedBase =
2008 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2010 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2011 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2016 else if ((sanitizeBase || sanitizeExponent) &&
2017 mlir::isa<cir::IntType>(ops.lhs.getType()))
2023mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2025 if (ops.isFixedPointOp()) {
2038 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2039 mlir::isa<cir::IntType>(ops.lhs.getType()))
2047mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2048 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2050mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2051 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2053mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2054 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2061mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2063 QualType destTy = ce->
getType();
2068 ignoreResultAssign =
false;
2071 case clang::CK_Dependent:
2072 llvm_unreachable(
"dependent cast kind in CIR gen!");
2073 case clang::CK_BuiltinFnToFnPtr:
2074 llvm_unreachable(
"builtin functions are handled elsewhere");
2075 case CK_LValueBitCast:
2076 case CK_LValueToRValueBitCast: {
2078 Address sourceAddr = sourceLVal.getAddress();
2084 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2087 case CK_CPointerToObjCPointerCast:
2088 case CK_BlockPointerToObjCPointerCast:
2089 case CK_AnyPointerToBlockPointerCast:
2091 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2096 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2098 "sanitizer support");
2102 "strict vtable pointers");
2128 case CK_AddressSpaceConversion: {
2129 Expr::EvalResult result;
2143 case CK_AtomicToNonAtomic: {
2149 case CK_NonAtomicToAtomic:
2150 case CK_UserDefinedConversion:
2151 return Visit(
const_cast<Expr *
>(subExpr));
2153 auto v = Visit(
const_cast<Expr *
>(subExpr));
2159 if (t != v.getType())
2164 case CK_IntegralToPointer: {
2166 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2175 : cir::CastKind::integral,
2180 "IntegralToPointer: strict vtable pointers");
2187 case CK_BaseToDerived: {
2189 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2201 case CK_UncheckedDerivedToBase:
2202 case CK_DerivedToBase: {
2213 case CK_ArrayToPointerDecay:
2216 case CK_NullToPointer: {
2226 case CK_NullToMemberPointer: {
2232 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2234 auto ty = mlir::cast<cir::MethodType>(cgf.
convertType(destTy));
2238 auto ty = mlir::cast<cir::DataMemberType>(cgf.
convertType(destTy));
2242 case CK_ReinterpretMemberPointer: {
2243 mlir::Value src = Visit(subExpr);
2247 case CK_BaseToDerivedMemberPointer:
2248 case CK_DerivedToBaseMemberPointer: {
2249 mlir::Value src = Visit(subExpr);
2253 QualType derivedTy =
2254 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2255 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2256 NestedNameSpecifier qualifier = mpType->getQualifier();
2257 assert(qualifier &&
"member pointer without class qualifier");
2258 const Type *qualifierType = qualifier.getAsType();
2259 assert(qualifierType &&
"member pointer qualifier is not a type");
2266 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2269 if (
kind == CK_BaseToDerivedMemberPointer)
2270 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2272 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2275 if (
kind == CK_BaseToDerivedMemberPointer)
2276 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2278 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2282 case CK_LValueToRValue:
2284 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2285 return Visit(
const_cast<Expr *
>(subExpr));
2287 case CK_IntegralCast: {
2288 ScalarConversionOpts opts;
2289 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2290 if (!ice->isPartOfExplicitCast())
2291 opts = ScalarConversionOpts(cgf.
sanOpts);
2293 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2297 case CK_FloatingComplexToReal:
2298 case CK_IntegralComplexToReal:
2299 case CK_FloatingComplexToBoolean:
2300 case CK_IntegralComplexToBoolean: {
2306 case CK_FloatingRealToComplex:
2307 case CK_FloatingComplexCast:
2308 case CK_IntegralRealToComplex:
2309 case CK_IntegralComplexCast:
2310 case CK_IntegralComplexToFloatingComplex:
2311 case CK_FloatingComplexToIntegralComplex:
2312 llvm_unreachable(
"scalar cast to non-scalar value");
2314 case CK_PointerToIntegral: {
2315 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2318 "strict vtable pointers");
2325 case CK_IntegralToFloating:
2326 case CK_FloatingToIntegral:
2327 case CK_FloatingCast:
2328 case CK_FixedPointToFloating:
2329 case CK_FloatingToFixedPoint: {
2330 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2332 "fixed point casts");
2335 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2336 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2340 case CK_IntegralToBoolean:
2341 return emitIntToBoolConversion(Visit(subExpr),
2344 case CK_PointerToBoolean:
2345 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2346 case CK_FloatingToBoolean:
2347 return emitFloatToBoolConversion(Visit(subExpr),
2349 case CK_MemberPointerToBoolean: {
2350 mlir::Value memPtr = Visit(subExpr);
2352 cir::CastKind::member_ptr_to_bool, memPtr,
2356 case CK_VectorSplat: {
2358 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2359 return cir::VecSplatOp::create(builder,
2363 case CK_FunctionToPointerDecay:
2373mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2375 return emitLoadOfLValue(e);
2382mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2387 Expr::EvalResult result;
2389 llvm::APSInt value = result.
Val.
getInt();
2393 return emitLoadOfLValue(e);
2396mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2397 const unsigned numInitElements = e->
getNumInits();
2399 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2400 assert((ignore ==
false ||
2402 "init list ignored");
2410 const auto vectorType =
2413 SmallVector<mlir::Value, 16> elements;
2414 for (Expr *init : e->
inits()) {
2415 elements.push_back(Visit(init));
2419 if (numInitElements < vectorType.getSize()) {
2422 std::fill_n(std::back_inserter(elements),
2423 vectorType.getSize() - numInitElements, zeroValue);
2426 return cir::VecCreateOp::create(cgf.
getBuilder(),
2432 if (numInitElements == 0)
2443 "Invalid scalar expression to emit");
2445 .emitScalarConversion(src, srcTy, dstTy, loc);
2453 "Invalid complex -> scalar conversion");
2458 ? cir::CastKind::float_complex_to_bool
2459 : cir::CastKind::int_complex_to_bool;
2464 ? cir::CastKind::float_complex_to_real
2465 : cir::CastKind::int_complex_to_real;
2471mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2478 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2480 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2481 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2495mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2500 llvm::APSInt value = evalResult.
Val.
getInt();
2506 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2510mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2512 mlir::Value result = VisitRealImag(e, promotionTy);
2513 if (result && !promotionTy.
isNull())
2514 result = emitUnPromotedValue(result, e->
getType());
2518mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2520 mlir::Value result = VisitRealImag(e, promotionTy);
2521 if (result && !promotionTy.
isNull())
2522 result = emitUnPromotedValue(result, e->
getType());
2526mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2527 QualType promotionTy) {
2530 "Invalid UnaryOp kind for ComplexType Real or Imag");
2552 mlir::Value operand = promotionTy.
isNull()
2554 : cgf.emitPromotedScalarExpr(op, promotionTy);
2560 mlir::Value operand;
2563 operand = cir::LoadOp::create(builder, loc, operand);
2564 }
else if (!promotionTy.
isNull()) {
2574mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2575 const UnaryExprOrTypeTraitExpr *e) {
2579 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2580 if (
const VariableArrayType *vat =
2585 bool evaluateExtent =
true;
2586 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2588 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2591 if (evaluateExtent) {
2602 if (
kind == UETT_CountOf)
2607 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2608 mlir::Value numElts = vlaSize.
numElts;
2612 if (!eltSize.
isOne()) {
2614 mlir::Value eltSizeValue =
2617 return builder.
createMul(loc, eltSizeValue, numElts,
2624 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2631 }
else if (e->
getKind() == UETT_VectorElements) {
2633 if (vecTy.getIsScalable()) {
2636 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2643 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2668mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2669 const AbstractConditionalOperator *e) {
2672 ignoreResultAssign =
false;
2675 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2677 Expr *condExpr = e->
getCond();
2685 Expr *live = lhsExpr, *dead = rhsExpr;
2687 std::swap(live, dead);
2693 mlir::Value result = Visit(live);
2700 loc, cir::PoisonAttr::get(builder.getContext(),
2708 QualType condType = condExpr->
getType();
2721 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2725 mlir::Value condValue = Visit(condExpr);
2726 mlir::Value lhsValue = Visit(lhsExpr);
2727 mlir::Value rhsValue = Visit(rhsExpr);
2728 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2737 bool lhsIsVoid =
false;
2741 mlir::Value lhs = Visit(lhsExpr);
2747 mlir::Value rhs = Visit(rhsExpr);
2749 assert(!rhs &&
"lhs and rhs types must match");
2757 CIRGenFunction::ConditionalEvaluation eval(cgf);
2758 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2759 mlir::Type yieldTy{};
2761 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2762 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2766 eval.beginEvaluation();
2767 mlir::Value branch = Visit(
expr);
2768 eval.endEvaluation();
2771 yieldTy = branch.getType();
2772 cir::YieldOp::create(
b, loc, branch);
2776 insertPoints.push_back(
b.saveInsertionPoint());
2780 mlir::Value result = cir::TernaryOp::create(
2781 builder, loc, condV,
2783 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2784 emitBranch(
b, loc, lhsExpr);
2787 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2788 emitBranch(
b, loc, rhsExpr);
2792 if (!insertPoints.empty()) {
2798 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2799 mlir::OpBuilder::InsertionGuard guard(builder);
2800 builder.restoreInsertionPoint(toInsert);
2803 if (mlir::isa<cir::VoidType>(yieldTy)) {
2804 cir::YieldOp::create(builder, loc);
2807 cir::YieldOp::create(builder, loc, op0);
2817 cir::UnaryOpKind
kind,
2820 .emitScalarPrePostIncDec(e, lv,
kind, isPre);
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.
*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 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 createNot(mlir::Value value)
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 createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
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
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
mlir::Value getPointer() const
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
cir::ConstantOp getNullDataMemberPtr(cir::DataMemberType ty, mlir::Location loc)
Create constant nullptr for pointer-to-data-member type ty.
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::ConstantOp getNullMethodPtr(cir::MethodType ty, mlir::Location loc)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNeg(mlir::Value value)
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 emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
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)
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
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()
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::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 ...
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::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()
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 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)
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
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.
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.