22#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
23#include "mlir/IR/Location.h"
24#include "mlir/IR/Value.h"
46 bool isDivRemOp()
const {
47 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
48 opcode == BO_RemAssign;
52 bool mayHaveIntegerOverflow()
const {
54 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
55 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
67 bool isFixedPointOp()
const {
70 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
71 QualType lhstype = binOp->getLHS()->getType();
72 QualType rhstype = binOp->getRHS()->getType();
75 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
76 return unop->getSubExpr()->getType()->isFixedPointType();
81class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
83 CIRGenBuilderTy &builder;
87 bool ignoreResultAssign;
90 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
91 bool ignoreResultAssign =
false)
92 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
97 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
99 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
103 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
104 return cgf.cgm.emitNullConstant(ty, loc);
107 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
108 return builder.createFloatingCast(result, cgf.convertType(promotionType));
111 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
112 return builder.createFloatingCast(result, cgf.convertType(exprType));
115 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
117 mlir::Value maybePromoteBoolResult(mlir::Value value,
118 mlir::Type dstTy)
const {
119 if (mlir::isa<cir::IntType>(dstTy))
120 return builder.createBoolToInt(value, dstTy);
121 if (mlir::isa<cir::BoolType>(dstTy))
123 llvm_unreachable(
"Can only promote integer or boolean types");
130 mlir::Value Visit(Expr *e) {
131 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
134 mlir::Value VisitStmt(Stmt *
s) {
135 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
138 mlir::Value VisitExpr(Expr *e) {
139 cgf.getCIRGenModule().errorNYI(
144 mlir::Value VisitConstantExpr(ConstantExpr *e) {
150 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
153 "ScalarExprEmitter: constant expr GL Value");
158 mlir::cast<mlir::TypedAttr>(result));
161 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
165 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
169 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
171 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
176 mlir::Value emitLoadOfLValue(
const Expr *e) {
177 LValue lv = cgf.emitLValue(e);
179 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
182 mlir::Value VisitCoawaitExpr(CoawaitExpr *
s) {
183 return cgf.emitCoawaitExpr(*s).getValue();
186 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
187 return cgf.emitCoyieldExpr(*e).getValue();
190 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
191 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
195 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
196 return cgf.emitLoadOfLValue(lv, loc).getValue();
200 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
201 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
202 return cgf.emitScalarConstant(constant, e);
204 return emitLoadOfLValue(e);
207 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
209 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
211 cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
214 cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
215 if (!resolvedLabel) {
216 cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
219 cgf.cgm.mapResolvedBlockAddress(blockAddressOp,
nullptr);
221 cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
223 cgf.instantiateIndirectGotoBlock();
224 return blockAddressOp;
227 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
229 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
233 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
235 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
239 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
241 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
242 "expect floating-point type");
243 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
247 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
248 mlir::Type ty = cgf.convertType(e->
getType());
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 return cgf.emitPseudoObjectRValue(e).getValue();
277 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
279 "ScalarExprEmitter: sycl unique stable name");
282 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
284 auto it = e->
begin();
285 llvm::APInt value = (*it)->getValue();
286 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
289 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
291 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
295 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
298 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
299 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
302 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
303 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
306 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
307 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
310 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
311 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
314 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
315 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
318 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
320 "ScalarExprEmitter: objc availability check");
324 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
326 "ScalarExprEmitter: matrix subscript");
330 mlir::Value VisitCastExpr(
CastExpr *e);
331 mlir::Value VisitCallExpr(
const CallExpr *e);
333 mlir::Value VisitStmtExpr(StmtExpr *e) {
334 CIRGenFunction::StmtExprEvaluation eval(cgf);
342 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
344 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
348 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
349 ignoreResultAssign =
false;
355 const mlir::Value vecValue = Visit(e->
getBase());
356 const mlir::Value indexValue = Visit(e->
getIdx());
357 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
360 return emitLoadOfLValue(e);
363 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
366 mlir::Value inputVec = Visit(e->
getExpr(0));
367 mlir::Value indexVec = Visit(e->
getExpr(1));
368 return cir::VecShuffleDynamicOp::create(
369 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
372 mlir::Value vec1 = Visit(e->
getExpr(0));
373 mlir::Value vec2 = Visit(e->
getExpr(1));
378 SmallVector<mlir::Attribute, 8> indices;
381 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
387 return cir::VecShuffleOp::create(cgf.builder,
389 cgf.convertType(e->
getType()), vec1, vec2,
390 cgf.builder.getArrayAttr(indices));
393 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
396 return emitScalarConversion(Visit(e->
getSrcExpr()),
401 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
403 mlir::Value VisitMatrixElementExpr(Expr *e) {
404 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: matrix element");
408 mlir::Value VisitMemberExpr(MemberExpr *e);
410 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
411 return emitLoadOfLValue(e);
414 mlir::Value VisitInitListExpr(InitListExpr *e);
416 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
417 assert(cgf.getArrayInitIndex() &&
418 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
419 return cgf.getArrayInitIndex();
422 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
426 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
427 return VisitCastExpr(e);
430 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
431 return cgf.cgm.emitNullConstant(e->
getType(),
436 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
439 return cgf.getBuilder().createPtrToBoolCast(v);
442 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
443 cir::BoolType boolTy = builder.getBoolTy();
444 return cir::CastOp::create(builder, loc, boolTy,
445 cir::CastKind::float_to_bool, src);
448 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
454 cir::BoolType boolTy = builder.getBoolTy();
455 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
461 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
462 mlir::Location loc) {
463 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
466 return emitFloatToBoolConversion(src, loc);
468 if (llvm::isa<MemberPointerType>(srcType)) {
469 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
470 return builder.getFalse(loc);
474 return emitIntToBoolConversion(src, loc);
476 assert(::mlir::isa<cir::PointerType>(src.getType()));
477 return emitPointerToBoolConversion(src, srcType);
482 struct ScalarConversionOpts {
483 bool treatBooleanAsSigned;
484 bool emitImplicitIntegerTruncationChecks;
485 bool emitImplicitIntegerSignChangeChecks;
487 ScalarConversionOpts()
488 : treatBooleanAsSigned(
false),
489 emitImplicitIntegerTruncationChecks(
false),
490 emitImplicitIntegerSignChangeChecks(
false) {}
492 ScalarConversionOpts(clang::SanitizerSet sanOpts)
493 : treatBooleanAsSigned(
false),
494 emitImplicitIntegerTruncationChecks(
495 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
496 emitImplicitIntegerSignChangeChecks(
497 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
504 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
505 QualType dstType, mlir::Type srcTy,
506 mlir::Type dstTy, ScalarConversionOpts opts) {
508 "Internal error: matrix types not handled by this function.");
509 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
510 mlir::isa<mlir::IntegerType>(dstTy)) &&
511 "Obsolete code. Don't use mlir::IntegerType with CIR.");
513 mlir::Type fullDstTy = dstTy;
514 if (mlir::isa<cir::VectorType>(srcTy) &&
515 mlir::isa<cir::VectorType>(dstTy)) {
517 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
518 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
521 std::optional<cir::CastKind> castKind;
523 if (mlir::isa<cir::BoolType>(srcTy)) {
524 if (opts.treatBooleanAsSigned)
525 cgf.getCIRGenModule().errorNYI(
"signed bool");
526 if (cgf.getBuilder().isInt(dstTy))
527 castKind = cir::CastKind::bool_to_int;
528 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
529 castKind = cir::CastKind::bool_to_float;
531 llvm_unreachable(
"Internal error: Cast to unexpected type");
532 }
else if (cgf.getBuilder().isInt(srcTy)) {
533 if (cgf.getBuilder().isInt(dstTy))
534 castKind = cir::CastKind::integral;
535 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
536 castKind = cir::CastKind::int_to_float;
538 llvm_unreachable(
"Internal error: Cast to unexpected type");
539 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
540 if (cgf.getBuilder().isInt(dstTy)) {
544 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
545 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
547 castKind = cir::CastKind::float_to_int;
548 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
550 return builder.createFloatingCast(src, fullDstTy);
552 llvm_unreachable(
"Internal error: Cast to unexpected type");
555 llvm_unreachable(
"Internal error: Cast from unexpected type");
558 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
559 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
564 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
568 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
573 "variably modified types in varargs");
576 return cgf.emitVAArg(ve);
579 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
583 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
585 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
588 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
590 return emitScalarPrePostIncDec(e, lv);
592 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
593 return VisitUnaryPrePostIncDec(e);
595 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
596 return VisitUnaryPrePostIncDec(e);
598 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
599 return VisitUnaryPrePostIncDec(e);
601 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
602 return VisitUnaryPrePostIncDec(e);
604 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
605 if (cgf.getLangOpts().OpenMP)
613 if (
type->getAs<AtomicType>()) {
617 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
620 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
634 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
635 }
else if (
type->isIntegerType()) {
636 QualType promotedType;
637 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
638 if (cgf.getContext().isPromotableIntegerType(
type)) {
639 promotedType = cgf.getContext().getPromotedIntegerType(
type);
640 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
641 canPerformLossyDemotionCheck =
true;
642 canPerformLossyDemotionCheck &=
643 cgf.getContext().getCanonicalType(
type) !=
644 cgf.getContext().getCanonicalType(promotedType);
645 canPerformLossyDemotionCheck &=
652 (!canPerformLossyDemotionCheck ||
653 type->isSignedIntegerOrEnumerationType() ||
655 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
656 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
657 "The following check expects that if we do promotion to different "
658 "underlying canonical type, at least one of the types (either "
659 "base or promoted) will be signed, or the bitwidths will match.");
664 value = emitIncDecConsiderOverflowBehavior(e, value);
667 value = emitIncOrDec(e, input,
false);
669 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
670 QualType
type = ptr->getPointeeType();
671 if (cgf.getContext().getAsVariableArrayType(
type)) {
673 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
678 CIRGenBuilderTy &builder = cgf.getBuilder();
680 mlir::Value amt = builder.getSInt32(amount, loc);
682 value = builder.createPtrStride(loc, value, amt);
684 }
else if (
type->isVectorType()) {
687 }
else if (
type->isRealFloatingType()) {
688 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
690 if (
type->isHalfType() &&
691 !cgf.getContext().getLangOpts().NativeHalfType) {
696 if (mlir::isa<cir::SingleType, cir::DoubleType, cir::LongDoubleType>(
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");
1443 mlir::Type srcTy = src.
getType();
1447 return builder.createBitcast(src, dstTy);
1452 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1460 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1464 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1471 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1475 return builder.createIntToPtr(src, dstTy);
1478 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1479 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1480 mlir::Type srcTy = src.getType();
1481 mlir::Type dstTy = cgf.convertType(e->
getType());
1493 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1499 if (numElementsSrc == 3 && numElementsDst != 3) {
1501 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1502 "numElemsDst != 3");
1509 if (numElementsSrc != 3 && numElementsDst == 3) {
1511 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc != 3, "
1519 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1520 return cgf.emitAtomicExpr(e).getValue();
1524LValue ScalarExprEmitter::emitCompoundAssignLValue(
1526 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1527 mlir::Value &result) {
1538 if (promotionTypeCR.
isNull())
1542 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1544 if (!promotionTypeRHS.
isNull())
1547 opInfo.rhs = Visit(e->
getRHS());
1549 opInfo.fullType = promotionTypeCR;
1550 opInfo.compType = opInfo.fullType;
1551 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1552 opInfo.compType = vecType->getElementType();
1561 if (lhsTy->
getAs<AtomicType>()) {
1562 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1566 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1568 CIRGenFunction::SourceLocRAIIObject sourceloc{
1571 if (!promotionTypeLHS.
isNull())
1572 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1574 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1578 result = (this->*func)(opInfo);
1582 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1583 ScalarConversionOpts(cgf.
sanOpts));
1589 if (lhsLV.isBitField())
1600mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1604 cir::CastKind castOpKind;
1606 case CK_FloatingComplexToReal:
1607 castOpKind = cir::CastKind::float_complex_to_real;
1609 case CK_IntegralComplexToReal:
1610 castOpKind = cir::CastKind::int_complex_to_real;
1612 case CK_FloatingComplexToBoolean:
1613 castOpKind = cir::CastKind::float_complex_to_bool;
1615 case CK_IntegralComplexToBoolean:
1616 castOpKind = cir::CastKind::int_complex_to_bool;
1619 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1625mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1626 QualType promotionType) {
1628 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1629 switch (bo->getOpcode()) {
1630#define HANDLE_BINOP(OP) \
1632 return emit##OP(emitBinOps(bo, promotionType));
1641 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1642 switch (uo->getOpcode()) {
1645 return VisitRealImag(uo, promotionType);
1647 return VisitUnaryMinus(uo, promotionType);
1649 return VisitUnaryPlus(uo, promotionType);
1654 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1656 if (!promotionType.
isNull())
1657 return emitPromotedValue(result, promotionType);
1658 return emitUnPromotedValue(result, e->
getType());
1663mlir::Value ScalarExprEmitter::emitCompoundAssign(
1664 const CompoundAssignOperator *e,
1665 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1667 bool ignore = std::exchange(ignoreResultAssign,
false);
1669 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1680 if (!lhs.isVolatile())
1684 return emitLoadOfLValue(lhs, e->
getExprLoc());
1687mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1688 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1703#define COMPOUND_OP(Op) \
1704 case BO_##Op##Assign: \
1705 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1742 llvm_unreachable(
"Not valid compound assignment operators");
1744 llvm_unreachable(
"Unhandled compound assignment operator");
1749 bool ignoreResultAssign) {
1751 "Invalid scalar expression to emit");
1754 .Visit(
const_cast<Expr *
>(e));
1759 if (!promotionType.
isNull())
1774static std::optional<QualType>
1778 return std::nullopt;
1783 return std::nullopt;
1796 const BinOpInfo &op) {
1798 "Expected a unary or binary operator");
1802 if (!op.mayHaveIntegerOverflow())
1806 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1807 return !uo->canOverflow();
1812 std::optional<QualType> optionalLHSTy =
1817 std::optional<QualType> optionalRHSTy =
1827 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1834 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1835 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1840 const BinOpInfo &op,
1841 bool isSubtraction) {
1846 mlir::Value pointer = op.lhs;
1847 Expr *pointerOperand =
expr->getLHS();
1848 mlir::Value
index = op.rhs;
1849 Expr *indexOperand =
expr->getRHS();
1855 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1856 std::swap(pointer,
index);
1857 std::swap(pointerOperand, indexOperand);
1859 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1860 "Need a pointer operand");
1861 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1896 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1907 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1909 pointer.getType(), pointer,
index);
1912mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1913 const mlir::Location loc = cgf.
getLoc(ops.loc);
1915 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1916 case LangOptions::SOB_Defined:
1917 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1918 return builder.
createMul(loc, ops.lhs, ops.rhs);
1920 case LangOptions::SOB_Undefined:
1921 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1924 case LangOptions::SOB_Trapping:
1936 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1938 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1940 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1941 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1942 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1945 if (ops.isFixedPointOp()) {
1951 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1954mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1955 return cir::DivOp::create(builder, cgf.
getLoc(ops.loc),
1958mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1959 return cir::RemOp::create(builder, cgf.
getLoc(ops.loc),
1963mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1964 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1965 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1968 const mlir::Location loc = cgf.
getLoc(ops.loc);
1970 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1971 case LangOptions::SOB_Defined:
1972 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1973 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1975 case LangOptions::SOB_Undefined:
1976 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1979 case LangOptions::SOB_Trapping:
1992 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1994 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1996 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1997 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1998 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2001 if (ops.isFixedPointOp()) {
2007 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2010mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2011 const mlir::Location loc = cgf.
getLoc(ops.loc);
2013 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2015 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2016 case LangOptions::SOB_Defined: {
2017 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2018 return builder.
createSub(loc, ops.lhs, ops.rhs);
2021 case LangOptions::SOB_Undefined:
2022 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2025 case LangOptions::SOB_Trapping:
2039 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2041 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2043 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2044 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2045 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2048 if (ops.isFixedPointOp()) {
2054 return builder.
createSub(loc, ops.lhs, ops.rhs);
2059 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2071 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2075mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2077 if (ops.isFixedPointOp()) {
2087 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2091 bool sanitizeUnsignedBase =
2092 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2094 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2095 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2100 else if ((sanitizeBase || sanitizeExponent) &&
2101 mlir::isa<cir::IntType>(ops.lhs.getType()))
2107mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2109 if (ops.isFixedPointOp()) {
2122 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2123 mlir::isa<cir::IntType>(ops.lhs.getType()))
2131mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2132 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2134mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2135 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2137mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2138 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2145mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2147 QualType destTy = ce->
getType();
2152 ignoreResultAssign =
false;
2155 case clang::CK_Dependent:
2156 llvm_unreachable(
"dependent cast kind in CIR gen!");
2157 case clang::CK_BuiltinFnToFnPtr:
2158 llvm_unreachable(
"builtin functions are handled elsewhere");
2159 case CK_LValueBitCast:
2160 case CK_LValueToRValueBitCast: {
2162 Address sourceAddr = sourceLVal.getAddress();
2168 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2171 case CK_CPointerToObjCPointerCast:
2172 case CK_BlockPointerToObjCPointerCast:
2173 case CK_AnyPointerToBlockPointerCast:
2175 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2180 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2182 "sanitizer support");
2186 "strict vtable pointers");
2212 case CK_AddressSpaceConversion: {
2213 Expr::EvalResult result;
2227 case CK_AtomicToNonAtomic:
2228 case CK_NonAtomicToAtomic:
2229 case CK_UserDefinedConversion:
2230 return Visit(
const_cast<Expr *
>(subExpr));
2234 case CK_IntegralToPointer: {
2236 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2245 : cir::CastKind::integral,
2250 "IntegralToPointer: strict vtable pointers");
2257 case CK_BaseToDerived: {
2259 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2271 case CK_UncheckedDerivedToBase:
2272 case CK_DerivedToBase: {
2283 case CK_ArrayToPointerDecay:
2286 case CK_NullToPointer: {
2296 case CK_NullToMemberPointer: {
2302 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2308 case CK_ReinterpretMemberPointer: {
2309 mlir::Value src = Visit(subExpr);
2313 case CK_BaseToDerivedMemberPointer:
2314 case CK_DerivedToBaseMemberPointer: {
2315 mlir::Value src = Visit(subExpr);
2319 QualType derivedTy =
2320 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2321 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2322 NestedNameSpecifier qualifier = mpType->getQualifier();
2323 assert(qualifier &&
"member pointer without class qualifier");
2324 const Type *qualifierType = qualifier.getAsType();
2325 assert(qualifierType &&
"member pointer qualifier is not a type");
2332 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2335 if (
kind == CK_BaseToDerivedMemberPointer)
2336 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2338 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2341 if (
kind == CK_BaseToDerivedMemberPointer)
2342 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2344 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2348 case CK_LValueToRValue:
2350 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2351 return Visit(
const_cast<Expr *
>(subExpr));
2353 case CK_IntegralCast: {
2354 ScalarConversionOpts opts;
2355 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2356 if (!ice->isPartOfExplicitCast())
2357 opts = ScalarConversionOpts(cgf.
sanOpts);
2359 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2363 case CK_FloatingComplexToReal:
2364 case CK_IntegralComplexToReal:
2365 case CK_FloatingComplexToBoolean:
2366 case CK_IntegralComplexToBoolean: {
2372 case CK_FloatingRealToComplex:
2373 case CK_FloatingComplexCast:
2374 case CK_IntegralRealToComplex:
2375 case CK_IntegralComplexCast:
2376 case CK_IntegralComplexToFloatingComplex:
2377 case CK_FloatingComplexToIntegralComplex:
2378 llvm_unreachable(
"scalar cast to non-scalar value");
2380 case CK_PointerToIntegral: {
2381 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2384 "strict vtable pointers");
2391 case CK_IntegralToFloating:
2392 case CK_FloatingToIntegral:
2393 case CK_FloatingCast:
2394 case CK_FixedPointToFloating:
2395 case CK_FloatingToFixedPoint: {
2396 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2398 "fixed point casts");
2401 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2402 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2406 case CK_IntegralToBoolean:
2407 return emitIntToBoolConversion(Visit(subExpr),
2410 case CK_PointerToBoolean:
2411 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2412 case CK_FloatingToBoolean:
2413 return emitFloatToBoolConversion(Visit(subExpr),
2415 case CK_MemberPointerToBoolean: {
2416 mlir::Value memPtr = Visit(subExpr);
2418 cir::CastKind::member_ptr_to_bool, memPtr,
2422 case CK_VectorSplat: {
2424 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2425 return cir::VecSplatOp::create(builder,
2429 case CK_FunctionToPointerDecay:
2439mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2441 return emitLoadOfLValue(e);
2448mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2453 Expr::EvalResult result;
2455 llvm::APSInt value = result.
Val.
getInt();
2459 return emitLoadOfLValue(e);
2462mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2463 const unsigned numInitElements = e->
getNumInits();
2465 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2466 assert((ignore ==
false ||
2468 "init list ignored");
2476 const auto vectorType =
2479 SmallVector<mlir::Value, 16> elements;
2480 for (Expr *init : e->
inits()) {
2481 elements.push_back(Visit(init));
2485 if (numInitElements < vectorType.getSize()) {
2488 std::fill_n(std::back_inserter(elements),
2489 vectorType.getSize() - numInitElements, zeroValue);
2492 return cir::VecCreateOp::create(cgf.
getBuilder(),
2498 if (numInitElements == 0)
2509 "Invalid scalar expression to emit");
2511 .emitScalarConversion(src, srcTy, dstTy, loc);
2519 "Invalid complex -> scalar conversion");
2524 ? cir::CastKind::float_complex_to_bool
2525 : cir::CastKind::int_complex_to_bool;
2530 ? cir::CastKind::float_complex_to_real
2531 : cir::CastKind::int_complex_to_real;
2537mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2544 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2546 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2547 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2561mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2566 llvm::APSInt value = evalResult.
Val.
getInt();
2572 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2576mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2578 mlir::Value result = VisitRealImag(e, promotionTy);
2579 if (result && !promotionTy.
isNull())
2580 result = emitUnPromotedValue(result, e->
getType());
2584mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2586 mlir::Value result = VisitRealImag(e, promotionTy);
2587 if (result && !promotionTy.
isNull())
2588 result = emitUnPromotedValue(result, e->
getType());
2592mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2593 QualType promotionTy) {
2596 "Invalid UnaryOp kind for ComplexType Real or Imag");
2618 mlir::Value operand = promotionTy.
isNull()
2620 : cgf.emitPromotedScalarExpr(op, promotionTy);
2626 mlir::Value operand;
2629 operand = cir::LoadOp::create(builder, loc, operand);
2630 }
else if (!promotionTy.
isNull()) {
2640mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2641 const UnaryExprOrTypeTraitExpr *e) {
2645 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2646 if (
const VariableArrayType *vat =
2651 bool evaluateExtent =
true;
2652 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2654 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2657 if (evaluateExtent) {
2668 if (
kind == UETT_CountOf)
2673 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2674 mlir::Value numElts = vlaSize.
numElts;
2678 if (!eltSize.
isOne()) {
2680 mlir::Value eltSizeValue =
2683 return builder.
createMul(loc, eltSizeValue, numElts,
2690 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2697 }
else if (e->
getKind() == UETT_VectorElements) {
2699 if (vecTy.getIsScalable()) {
2702 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2709 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2734mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2735 const AbstractConditionalOperator *e) {
2738 ignoreResultAssign =
false;
2741 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2743 Expr *condExpr = e->
getCond();
2751 Expr *live = lhsExpr, *dead = rhsExpr;
2753 std::swap(live, dead);
2759 mlir::Value result = Visit(live);
2766 loc, cir::PoisonAttr::get(builder.getContext(),
2774 QualType condType = condExpr->
getType();
2787 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2791 mlir::Value condValue = Visit(condExpr);
2792 mlir::Value lhsValue = Visit(lhsExpr);
2793 mlir::Value rhsValue = Visit(rhsExpr);
2794 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2803 bool lhsIsVoid =
false;
2807 mlir::Value lhs = Visit(lhsExpr);
2813 mlir::Value rhs = Visit(rhsExpr);
2815 assert(!rhs &&
"lhs and rhs types must match");
2823 CIRGenFunction::ConditionalEvaluation eval(cgf);
2824 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2825 mlir::Type yieldTy{};
2827 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2828 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2832 eval.beginEvaluation();
2833 mlir::Value branch = Visit(
expr);
2834 eval.endEvaluation();
2837 yieldTy = branch.getType();
2838 cir::YieldOp::create(
b, loc, branch);
2842 insertPoints.push_back(
b.saveInsertionPoint());
2846 mlir::Value result = cir::TernaryOp::create(
2847 builder, loc, condV,
2849 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2850 emitBranch(
b, loc, lhsExpr);
2853 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2854 emitBranch(
b, loc, rhsExpr);
2858 if (!insertPoints.empty()) {
2864 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2865 mlir::OpBuilder::InsertionGuard guard(builder);
2866 builder.restoreInsertionPoint(toInsert);
2869 if (mlir::isa<cir::VoidType>(yieldTy)) {
2870 cir::YieldOp::create(builder, loc);
2873 cir::YieldOp::create(builder, loc, op0);
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
*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
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
BinaryOperatorKind Opcode
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
mlir::Value 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)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
LexicalScope * curLexScope
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
Expr * getExpr()
Get the initialization expression that will be used.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
bool changesVolatileQualification() const
Return.
static const char * getCastKindName(CastKind CK)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isOne() const
isOne - Test whether the quantity equals one.
unsigned getValue() const
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
ChildElementIter< false > begin()
size_t getDataElementCount() const
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits() const
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
A pointer to member type per C++ 8.3.3 - Pointers to members.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
SourceLocation getExprLoc() const LLVM_READONLY
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getCanonicalType() const
bool UseExcessPrecision(const ASTContext &Ctx)
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
bool isSatisfied() const
Whether or not the requires clause is satisfied.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
unsigned getPackLength() const
Retrieve the length of the parameter pack.
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
SourceLocation getLocation() const
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
Expr * getReplacement() const
bool getBoolValue() const
const APValue & getAPValue() const
bool isStoredAsBoolean() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantMatrixType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isExtVectorType() const
bool isExtVectorBoolType() const
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isMemberFunctionPointerType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
SourceLocation getExprLoc() const
Expr * getSubExpr() const
static bool isIncrementOp(Opcode Op)
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ Type
The name was classified as a type.
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
U cast(CodeGen::Address addr)
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool addressSpace()
static bool fixedPointType()
static bool vecTernaryOp()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
static bool memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool HasSideEffects
Whether the evaluated expression has side effects.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.