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 VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
591 return emitScalarPrePostIncDec(e, lv);
593 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
594 return VisitUnaryPrePostIncDec(e);
596 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
597 return VisitUnaryPrePostIncDec(e);
599 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
600 return VisitUnaryPrePostIncDec(e);
602 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
603 return VisitUnaryPrePostIncDec(e);
605 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
606 if (cgf.getLangOpts().OpenMP)
614 if (
type->getAs<AtomicType>()) {
618 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
621 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
635 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
636 }
else if (
type->isIntegerType()) {
637 QualType promotedType;
638 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
639 if (cgf.getContext().isPromotableIntegerType(
type)) {
640 promotedType = cgf.getContext().getPromotedIntegerType(
type);
641 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
642 canPerformLossyDemotionCheck =
true;
643 canPerformLossyDemotionCheck &=
644 cgf.getContext().getCanonicalType(
type) !=
645 cgf.getContext().getCanonicalType(promotedType);
646 canPerformLossyDemotionCheck &=
653 (!canPerformLossyDemotionCheck ||
654 type->isSignedIntegerOrEnumerationType() ||
656 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
657 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
658 "The following check expects that if we do promotion to different "
659 "underlying canonical type, at least one of the types (either "
660 "base or promoted) will be signed, or the bitwidths will match.");
665 value = emitIncDecConsiderOverflowBehavior(e, value);
668 value = emitIncOrDec(e, input,
false);
670 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
671 QualType
type = ptr->getPointeeType();
672 if (cgf.getContext().getAsVariableArrayType(
type)) {
674 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
679 CIRGenBuilderTy &builder = cgf.getBuilder();
681 mlir::Value amt = builder.getSInt32(amount, loc);
683 value = builder.createPtrStride(loc, value, amt);
685 }
else if (
type->isVectorType()) {
688 }
else if (
type->isRealFloatingType()) {
689 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
691 if (
type->isHalfType() &&
692 !cgf.getContext().getLangOpts().NativeHalfType) {
697 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
700 value = emitIncOrDec(e, value);
702 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
705 }
else if (
type->isFixedPointType()) {
706 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
709 assert(
type->castAs<ObjCObjectPointerType>());
710 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
714 CIRGenFunction::SourceLocRAIIObject sourceloc{
719 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
721 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
725 return e->
isPrefix() ? value : input;
728 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
730 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
731 case LangOptions::SOB_Defined:
732 return emitIncOrDec(e, inVal,
false);
733 case LangOptions::SOB_Undefined:
735 return emitIncOrDec(e, inVal,
true);
736 case LangOptions::SOB_Trapping:
738 return emitIncOrDec(e, inVal,
true);
739 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
742 llvm_unreachable(
"Unexpected signed overflow behavior kind");
745 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
746 if (llvm::isa<MemberPointerType>(e->
getType()))
747 return cgf.cgm.emitMemberPointerConstant(e);
749 return cgf.emitLValue(e->
getSubExpr()).getPointer();
752 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
755 return emitLoadOfLValue(e);
758 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
760 mlir::Value result = VisitUnaryPlus(e, promotionType);
761 if (result && !promotionType.
isNull())
762 return emitUnPromotedValue(result, e->
getType());
766 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
767 ignoreResultAssign =
false;
768 if (!promotionType.
isNull())
769 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
773 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
775 mlir::Value result = VisitUnaryMinus(e, promotionType);
776 if (result && !promotionType.
isNull())
777 return emitUnPromotedValue(result, e->
getType());
781 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
782 ignoreResultAssign =
false;
784 if (!promotionType.
isNull())
785 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
793 cgf.getLangOpts().getSignedOverflowBehavior() !=
794 LangOptions::SOB_Defined;
798 return builder.createOrFold<cir::MinusOp>(
802 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
806 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
807 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
810 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
811 ignoreResultAssign =
false;
813 return builder.createOrFold<cir::NotOp>(
817 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
819 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
820 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
821 mlir::Value VisitRealImag(
const UnaryOperator *e,
822 QualType promotionType = QualType());
824 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
829 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
831 "ScalarExprEmitter: materialize temporary");
834 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
835 ASTContext &ctx = cgf.getContext();
838 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
840 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
841 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
844 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
845 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
848 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
849 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
853 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
855 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
856 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
857 return cgf.emitCXXNewExpr(e);
859 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
860 cgf.emitCXXDeleteExpr(e);
863 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
869 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
874 "Expected int type for TypeTraitExpr");
875 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
881 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
887 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
889 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
892 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
895 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
897 "ScalarExprEmitter: cxx pseudo destructor");
900 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
901 cgf.emitCXXThrowExpr(e);
905 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
914 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
916 ScalarConversionOpts opts = ScalarConversionOpts()) {
926 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
932 if (srcType == dstType) {
933 if (opts.emitImplicitIntegerSignChangeChecks)
934 cgf.getCIRGenModule().errorNYI(loc,
935 "implicit integer sign change checks");
942 mlir::Type mlirSrcType = src.getType();
947 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
949 mlir::Type mlirDstType = cgf.convertType(dstType);
952 !cgf.getContext().getLangOpts().NativeHalfType) {
954 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
955 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
956 cgf.getCIRGenModule().errorNYI(loc,
957 "cast via llvm.convert.from.fp16");
962 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
963 cgf.getCIRGenModule().errorNYI(loc,
964 "cast via llvm.convert.from.fp16");
967 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
969 srcType = cgf.getContext().FloatTy;
970 mlirSrcType = cgf.floatTy;
976 if (mlirSrcType == mlirDstType) {
977 if (opts.emitImplicitIntegerSignChangeChecks)
978 cgf.getCIRGenModule().errorNYI(loc,
979 "implicit integer sign change checks");
986 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
987 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
988 return builder.getNullPtr(dstPT, src.getLoc());
994 return builder.createPtrToInt(src, mlirDstType);
1001 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1003 "Splatted expr doesn't match with vector element type?");
1005 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1010 cgf.getCIRGenModule().errorNYI(loc,
1011 "matrix type to matrix type conversion");
1015 "Internal error: conversion between matrix type and scalar type");
1018 mlir::Value res =
nullptr;
1019 mlir::Type resTy = mlirDstType;
1021 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1023 if (mlirDstType != resTy) {
1024 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1025 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1029 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1033 if (opts.emitImplicitIntegerTruncationChecks)
1034 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1036 if (opts.emitImplicitIntegerSignChangeChecks)
1037 cgf.getCIRGenModule().errorNYI(loc,
1038 "implicit integer sign change checks");
1043 BinOpInfo emitBinOps(
const BinaryOperator *e,
1044 QualType promotionType = QualType()) {
1045 ignoreResultAssign =
false;
1047 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1048 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1049 if (!promotionType.
isNull())
1050 result.fullType = promotionType;
1052 result.fullType = e->
getType();
1053 result.compType = result.fullType;
1054 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1055 result.compType = vecType->getElementType();
1060 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1065 mlir::Value emitMul(
const BinOpInfo &ops);
1066 mlir::Value emitDiv(
const BinOpInfo &ops);
1067 mlir::Value emitRem(
const BinOpInfo &ops);
1068 mlir::Value emitAdd(
const BinOpInfo &ops);
1069 mlir::Value emitSub(
const BinOpInfo &ops);
1070 mlir::Value emitShl(
const BinOpInfo &ops);
1071 mlir::Value emitShr(
const BinOpInfo &ops);
1072 mlir::Value emitAnd(
const BinOpInfo &ops);
1073 mlir::Value emitXor(
const BinOpInfo &ops);
1074 mlir::Value emitOr(
const BinOpInfo &ops);
1076 LValue emitCompoundAssignLValue(
1077 const CompoundAssignOperator *e,
1078 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1079 mlir::Value &result);
1081 emitCompoundAssign(
const CompoundAssignOperator *e,
1082 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1086 QualType getPromotionType(QualType ty) {
1087 const clang::ASTContext &ctx = cgf.getContext();
1088 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1089 QualType elementTy = complexTy->getElementType();
1095 if (
auto *vt = ty->
getAs<VectorType>()) {
1096 unsigned numElements = vt->getNumElements();
1099 return cgf.getContext().FloatTy;
1106#define HANDLEBINOP(OP) \
1107 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1108 QualType promotionTy = getPromotionType(e->getType()); \
1109 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1110 if (result && !promotionTy.isNull()) \
1111 result = emitUnPromotedValue(result, e->getType()); \
1114 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1115 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1131 ignoreResultAssign =
false;
1137 auto clangCmpToCIRCmp =
1141 return cir::CmpOpKind::lt;
1143 return cir::CmpOpKind::gt;
1145 return cir::CmpOpKind::le;
1147 return cir::CmpOpKind::ge;
1149 return cir::CmpOpKind::eq;
1151 return cir::CmpOpKind::ne;
1153 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1165 BinOpInfo boInfo = emitBinOps(e);
1166 mlir::Value lhs = boInfo.lhs;
1167 mlir::Value rhs = boInfo.rhs;
1177 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1179 boInfo.lhs, boInfo.rhs);
1181 }
else if (boInfo.isFixedPointOp()) {
1184 result = builder.
getBool(
false, loc);
1188 mlir::isa<cir::PointerType>(lhs.getType()) &&
1189 mlir::isa<cir::PointerType>(rhs.getType())) {
1190 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1196 "Complex Comparison: can only be an equality comparison");
1202 mlir::Value lhsReal = Visit(e->
getLHS());
1203 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1211 mlir::Value rhsReal = Visit(e->
getRHS());
1212 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1224#define VISITCOMP(CODE) \
1225 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1235 const bool ignore = std::exchange(ignoreResultAssign,
false);
1250 rhs = Visit(e->
getRHS());
1260 if (lhs.isBitField()) {
1282 if (!lhs.isVolatile())
1286 return emitLoadOfLValue(lhs, e->
getExprLoc());
1289 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1290 cgf.emitIgnoredExpr(e->
getLHS());
1292 return Visit(e->
getRHS());
1295 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1297 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1299 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1301 mlir::Value lhs = Visit(e->
getLHS());
1302 mlir::Value rhs = Visit(e->
getRHS());
1304 auto cmpOpKind = cir::CmpOpKind::ne;
1305 mlir::Type resTy = cgf.convertType(e->
getType());
1306 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1307 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1308 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1309 return builder.createIntCast(vecOr, resTy);
1313 mlir::Type resTy = cgf.convertType(e->
getType());
1314 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1316 CIRGenFunction::ConditionalEvaluation eval(cgf);
1318 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1319 auto resOp = cir::TernaryOp::create(
1320 builder, loc, lhsCondV,
1321 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1322 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1323 b.getInsertionBlock()};
1324 cgf.curLexScope->setAsTernary();
1325 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1327 cir::YieldOp::create(
b, loc, res);
1330 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1331 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1332 b.getInsertionBlock()};
1334 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1335 cir::YieldOp::create(
b, loc, res.getRes());
1337 return maybePromoteBoolResult(resOp.getResult(), resTy);
1340 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1342 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1344 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1346 mlir::Value lhs = Visit(e->
getLHS());
1347 mlir::Value rhs = Visit(e->
getRHS());
1349 auto cmpOpKind = cir::CmpOpKind::ne;
1350 mlir::Type resTy = cgf.convertType(e->
getType());
1351 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1352 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1353 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1354 return builder.createIntCast(vecOr, resTy);
1358 mlir::Type resTy = cgf.convertType(e->
getType());
1359 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1361 CIRGenFunction::ConditionalEvaluation eval(cgf);
1363 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1364 auto resOp = cir::TernaryOp::create(
1365 builder, loc, lhsCondV,
1366 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1367 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1368 b.getInsertionBlock()};
1370 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1371 cir::YieldOp::create(
b, loc, res.getRes());
1374 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1375 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1376 b.getInsertionBlock()};
1378 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1380 cir::YieldOp::create(
b, loc, res);
1383 return maybePromoteBoolResult(resOp.getResult(), resTy);
1386 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1387 return emitLoadOfLValue(e);
1390 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1391 return emitLoadOfLValue(e);
1395 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1396 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1400 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1404 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1406 "ScalarExprEmitter: objc string literal");
1409 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1410 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1413 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1415 "ScalarExprEmitter: objc array literal");
1418 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1420 "ScalarExprEmitter: objc dictionary literal");
1424 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1425 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1429 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1430 return cgf.emitAtomicExpr(e).getValue();
1434LValue ScalarExprEmitter::emitCompoundAssignLValue(
1436 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1437 mlir::Value &result) {
1448 if (promotionTypeCR.
isNull())
1452 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1454 if (!promotionTypeRHS.
isNull())
1457 opInfo.rhs = Visit(e->
getRHS());
1459 opInfo.fullType = promotionTypeCR;
1460 opInfo.compType = opInfo.fullType;
1461 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1462 opInfo.compType = vecType->getElementType();
1471 if (lhsTy->
getAs<AtomicType>()) {
1472 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1476 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1478 CIRGenFunction::SourceLocRAIIObject sourceloc{
1481 if (!promotionTypeLHS.
isNull())
1482 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1484 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1488 result = (this->*func)(opInfo);
1492 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1493 ScalarConversionOpts(cgf.
sanOpts));
1499 if (lhsLV.isBitField())
1510mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1514 cir::CastKind castOpKind;
1516 case CK_FloatingComplexToReal:
1517 castOpKind = cir::CastKind::float_complex_to_real;
1519 case CK_IntegralComplexToReal:
1520 castOpKind = cir::CastKind::int_complex_to_real;
1522 case CK_FloatingComplexToBoolean:
1523 castOpKind = cir::CastKind::float_complex_to_bool;
1525 case CK_IntegralComplexToBoolean:
1526 castOpKind = cir::CastKind::int_complex_to_bool;
1529 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1535mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1536 QualType promotionType) {
1538 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1539 switch (bo->getOpcode()) {
1540#define HANDLE_BINOP(OP) \
1542 return emit##OP(emitBinOps(bo, promotionType));
1551 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1552 switch (uo->getOpcode()) {
1555 return VisitRealImag(uo, promotionType);
1557 return VisitUnaryMinus(uo, promotionType);
1559 return VisitUnaryPlus(uo, promotionType);
1564 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1566 if (!promotionType.
isNull())
1567 return emitPromotedValue(result, promotionType);
1568 return emitUnPromotedValue(result, e->
getType());
1573mlir::Value ScalarExprEmitter::emitCompoundAssign(
1574 const CompoundAssignOperator *e,
1575 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1577 bool ignore = std::exchange(ignoreResultAssign,
false);
1579 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1590 if (!lhs.isVolatile())
1594 return emitLoadOfLValue(lhs, e->
getExprLoc());
1597mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1598 CIRGenFunction::RunCleanupsScope cleanups(cgf);
1602 cleanups.forceCleanup({&v});
1613#define COMPOUND_OP(Op) \
1614 case BO_##Op##Assign: \
1615 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1652 llvm_unreachable(
"Not valid compound assignment operators");
1654 llvm_unreachable(
"Unhandled compound assignment operator");
1659 bool ignoreResultAssign) {
1661 "Invalid scalar expression to emit");
1664 .Visit(
const_cast<Expr *
>(e));
1669 if (!promotionType.
isNull())
1684static std::optional<QualType>
1688 return std::nullopt;
1693 return std::nullopt;
1706 const BinOpInfo &op) {
1708 "Expected a unary or binary operator");
1712 if (!op.mayHaveIntegerOverflow())
1716 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1717 return !uo->canOverflow();
1722 std::optional<QualType> optionalLHSTy =
1727 std::optional<QualType> optionalRHSTy =
1737 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1744 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1745 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1750 const BinOpInfo &op,
1751 bool isSubtraction) {
1756 mlir::Value pointer = op.lhs;
1757 Expr *pointerOperand =
expr->getLHS();
1758 mlir::Value
index = op.rhs;
1759 Expr *indexOperand =
expr->getRHS();
1765 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1766 std::swap(pointer,
index);
1767 std::swap(pointerOperand, indexOperand);
1769 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1770 "Need a pointer operand");
1771 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1806 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1817 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1819 pointer.getType(), pointer,
index);
1822mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1823 const mlir::Location loc = cgf.
getLoc(ops.loc);
1825 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1826 case LangOptions::SOB_Defined:
1827 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1828 return builder.
createMul(loc, ops.lhs, ops.rhs);
1830 case LangOptions::SOB_Undefined:
1831 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1834 case LangOptions::SOB_Trapping:
1846 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1848 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1850 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1851 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1852 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1855 if (ops.isFixedPointOp()) {
1861 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1864mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1865 return cir::DivOp::create(builder, cgf.
getLoc(ops.loc),
1868mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1869 return cir::RemOp::create(builder, cgf.
getLoc(ops.loc),
1873mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1874 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1875 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1878 const mlir::Location loc = cgf.
getLoc(ops.loc);
1880 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1881 case LangOptions::SOB_Defined:
1882 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1883 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1885 case LangOptions::SOB_Undefined:
1886 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1889 case LangOptions::SOB_Trapping:
1902 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1904 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1906 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1907 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1908 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
1911 if (ops.isFixedPointOp()) {
1917 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1920mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1921 const mlir::Location loc = cgf.
getLoc(ops.loc);
1923 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1925 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1926 case LangOptions::SOB_Defined: {
1927 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1928 return builder.
createSub(loc, ops.lhs, ops.rhs);
1931 case LangOptions::SOB_Undefined:
1932 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1935 case LangOptions::SOB_Trapping:
1949 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1951 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1953 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1954 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1955 return builder.
createFSub(loc, ops.lhs, ops.rhs);
1958 if (ops.isFixedPointOp()) {
1964 return builder.
createSub(loc, ops.lhs, ops.rhs);
1969 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1981 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1985mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1987 if (ops.isFixedPointOp()) {
1997 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2001 bool sanitizeUnsignedBase =
2002 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2004 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2005 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2010 else if ((sanitizeBase || sanitizeExponent) &&
2011 mlir::isa<cir::IntType>(ops.lhs.getType()))
2017mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2019 if (ops.isFixedPointOp()) {
2032 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2033 mlir::isa<cir::IntType>(ops.lhs.getType()))
2041mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2042 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2044mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2045 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2047mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2048 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2055mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2057 QualType destTy = ce->
getType();
2062 ignoreResultAssign =
false;
2065 case clang::CK_Dependent:
2066 llvm_unreachable(
"dependent cast kind in CIR gen!");
2067 case clang::CK_BuiltinFnToFnPtr:
2068 llvm_unreachable(
"builtin functions are handled elsewhere");
2069 case CK_LValueBitCast:
2070 case CK_LValueToRValueBitCast: {
2072 Address sourceAddr = sourceLVal.getAddress();
2078 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2081 case CK_CPointerToObjCPointerCast:
2082 case CK_BlockPointerToObjCPointerCast:
2083 case CK_AnyPointerToBlockPointerCast:
2085 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2090 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2092 "sanitizer support");
2096 "strict vtable pointers");
2122 case CK_AddressSpaceConversion: {
2123 Expr::EvalResult result;
2137 case CK_AtomicToNonAtomic: {
2143 case CK_NonAtomicToAtomic:
2144 case CK_UserDefinedConversion:
2145 return Visit(
const_cast<Expr *
>(subExpr));
2147 auto v = Visit(
const_cast<Expr *
>(subExpr));
2153 if (t != v.getType())
2158 case CK_IntegralToPointer: {
2160 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2169 : cir::CastKind::integral,
2174 "IntegralToPointer: strict vtable pointers");
2181 case CK_BaseToDerived: {
2183 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2195 case CK_UncheckedDerivedToBase:
2196 case CK_DerivedToBase: {
2207 case CK_ArrayToPointerDecay:
2210 case CK_NullToPointer: {
2220 case CK_NullToMemberPointer: {
2226 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2232 case CK_ReinterpretMemberPointer: {
2233 mlir::Value src = Visit(subExpr);
2237 case CK_BaseToDerivedMemberPointer:
2238 case CK_DerivedToBaseMemberPointer: {
2239 mlir::Value src = Visit(subExpr);
2243 QualType derivedTy =
2244 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2245 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2246 NestedNameSpecifier qualifier = mpType->getQualifier();
2247 assert(qualifier &&
"member pointer without class qualifier");
2248 const Type *qualifierType = qualifier.getAsType();
2249 assert(qualifierType &&
"member pointer qualifier is not a type");
2256 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2259 if (
kind == CK_BaseToDerivedMemberPointer)
2260 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2262 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2265 if (
kind == CK_BaseToDerivedMemberPointer)
2266 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2268 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2272 case CK_LValueToRValue:
2274 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2275 return Visit(
const_cast<Expr *
>(subExpr));
2277 case CK_IntegralCast: {
2278 ScalarConversionOpts opts;
2279 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2280 if (!ice->isPartOfExplicitCast())
2281 opts = ScalarConversionOpts(cgf.
sanOpts);
2283 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2287 case CK_FloatingComplexToReal:
2288 case CK_IntegralComplexToReal:
2289 case CK_FloatingComplexToBoolean:
2290 case CK_IntegralComplexToBoolean: {
2296 case CK_FloatingRealToComplex:
2297 case CK_FloatingComplexCast:
2298 case CK_IntegralRealToComplex:
2299 case CK_IntegralComplexCast:
2300 case CK_IntegralComplexToFloatingComplex:
2301 case CK_FloatingComplexToIntegralComplex:
2302 llvm_unreachable(
"scalar cast to non-scalar value");
2304 case CK_PointerToIntegral: {
2305 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2308 "strict vtable pointers");
2315 case CK_IntegralToFloating:
2316 case CK_FloatingToIntegral:
2317 case CK_FloatingCast:
2318 case CK_FixedPointToFloating:
2319 case CK_FloatingToFixedPoint: {
2320 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2322 "fixed point casts");
2325 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2326 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2330 case CK_IntegralToBoolean:
2331 return emitIntToBoolConversion(Visit(subExpr),
2334 case CK_PointerToBoolean:
2335 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2336 case CK_FloatingToBoolean:
2337 return emitFloatToBoolConversion(Visit(subExpr),
2339 case CK_MemberPointerToBoolean: {
2340 mlir::Value memPtr = Visit(subExpr);
2342 cir::CastKind::member_ptr_to_bool, memPtr,
2346 case CK_VectorSplat: {
2348 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2349 return cir::VecSplatOp::create(builder,
2353 case CK_FunctionToPointerDecay:
2363mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2365 return emitLoadOfLValue(e);
2372mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2377 Expr::EvalResult result;
2379 llvm::APSInt value = result.
Val.
getInt();
2383 return emitLoadOfLValue(e);
2386mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2387 const unsigned numInitElements = e->
getNumInits();
2389 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2390 assert((ignore ==
false ||
2392 "init list ignored");
2400 const auto vectorType =
2403 SmallVector<mlir::Value, 16> elements;
2404 for (Expr *init : e->
inits()) {
2405 elements.push_back(Visit(init));
2409 if (numInitElements < vectorType.getSize()) {
2412 std::fill_n(std::back_inserter(elements),
2413 vectorType.getSize() - numInitElements, zeroValue);
2416 return cir::VecCreateOp::create(cgf.
getBuilder(),
2422 if (numInitElements == 0)
2433 "Invalid scalar expression to emit");
2435 .emitScalarConversion(src, srcTy, dstTy, loc);
2443 "Invalid complex -> scalar conversion");
2448 ? cir::CastKind::float_complex_to_bool
2449 : cir::CastKind::int_complex_to_bool;
2454 ? cir::CastKind::float_complex_to_real
2455 : cir::CastKind::int_complex_to_real;
2461mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2468 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2470 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2471 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2485mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2490 llvm::APSInt value = evalResult.
Val.
getInt();
2496 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2500mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2502 mlir::Value result = VisitRealImag(e, promotionTy);
2503 if (result && !promotionTy.
isNull())
2504 result = emitUnPromotedValue(result, e->
getType());
2508mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2510 mlir::Value result = VisitRealImag(e, promotionTy);
2511 if (result && !promotionTy.
isNull())
2512 result = emitUnPromotedValue(result, e->
getType());
2516mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2517 QualType promotionTy) {
2520 "Invalid UnaryOp kind for ComplexType Real or Imag");
2542 mlir::Value operand = promotionTy.
isNull()
2544 : cgf.emitPromotedScalarExpr(op, promotionTy);
2550 mlir::Value operand;
2553 operand = cir::LoadOp::create(builder, loc, operand);
2554 }
else if (!promotionTy.
isNull()) {
2564mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2565 const UnaryExprOrTypeTraitExpr *e) {
2569 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2570 if (
const VariableArrayType *vat =
2575 bool evaluateExtent =
true;
2576 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2578 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2581 if (evaluateExtent) {
2592 if (
kind == UETT_CountOf)
2597 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2598 mlir::Value numElts = vlaSize.
numElts;
2602 if (!eltSize.
isOne()) {
2604 mlir::Value eltSizeValue =
2607 return builder.
createMul(loc, eltSizeValue, numElts,
2614 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2621 }
else if (e->
getKind() == UETT_VectorElements) {
2623 if (vecTy.getIsScalable()) {
2626 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2633 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2658mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2659 const AbstractConditionalOperator *e) {
2662 ignoreResultAssign =
false;
2665 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2667 Expr *condExpr = e->
getCond();
2675 Expr *live = lhsExpr, *dead = rhsExpr;
2677 std::swap(live, dead);
2683 mlir::Value result = Visit(live);
2690 loc, cir::PoisonAttr::get(builder.getContext(),
2698 QualType condType = condExpr->
getType();
2711 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2715 mlir::Value condValue = Visit(condExpr);
2716 mlir::Value lhsValue = Visit(lhsExpr);
2717 mlir::Value rhsValue = Visit(rhsExpr);
2718 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2727 bool lhsIsVoid =
false;
2731 mlir::Value lhs = Visit(lhsExpr);
2737 mlir::Value rhs = Visit(rhsExpr);
2739 assert(!rhs &&
"lhs and rhs types must match");
2747 CIRGenFunction::ConditionalEvaluation eval(cgf);
2748 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2749 mlir::Type yieldTy{};
2751 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2752 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2756 eval.beginEvaluation();
2757 mlir::Value branch = Visit(
expr);
2758 eval.endEvaluation();
2761 yieldTy = branch.getType();
2762 cir::YieldOp::create(
b, loc, branch);
2766 insertPoints.push_back(
b.saveInsertionPoint());
2770 mlir::Value result = cir::TernaryOp::create(
2771 builder, loc, condV,
2773 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2774 emitBranch(
b, loc, lhsExpr);
2777 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2778 emitBranch(
b, loc, rhsExpr);
2782 if (!insertPoints.empty()) {
2788 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2789 mlir::OpBuilder::InsertionGuard guard(builder);
2790 builder.restoreInsertionPoint(toInsert);
2793 if (mlir::isa<cir::VoidType>(yieldTy)) {
2794 cir::YieldOp::create(builder, loc);
2797 cir::YieldOp::create(builder, loc, op0);
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 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 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
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.
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)
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 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()
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 ...
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)
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 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.