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) {
418 assert(cgf.getArrayInitIndex() &&
419 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
420 return cgf.getArrayInitIndex();
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, cir::LongDoubleType>(
701 value = emitIncOrDec(e, value);
703 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
706 }
else if (
type->isFixedPointType()) {
707 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
710 assert(
type->castAs<ObjCObjectPointerType>());
711 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
715 CIRGenFunction::SourceLocRAIIObject sourceloc{
720 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
722 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
726 return e->
isPrefix() ? value : input;
729 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
731 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
732 case LangOptions::SOB_Defined:
733 return emitIncOrDec(e, inVal,
false);
734 case LangOptions::SOB_Undefined:
736 return emitIncOrDec(e, inVal,
true);
737 case LangOptions::SOB_Trapping:
739 return emitIncOrDec(e, inVal,
true);
740 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
743 llvm_unreachable(
"Unexpected signed overflow behavior kind");
746 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
747 if (llvm::isa<MemberPointerType>(e->
getType()))
748 return cgf.cgm.emitMemberPointerConstant(e);
750 return cgf.emitLValue(e->
getSubExpr()).getPointer();
753 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
756 return emitLoadOfLValue(e);
759 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
761 mlir::Value result = VisitUnaryPlus(e, promotionType);
762 if (result && !promotionType.
isNull())
763 return emitUnPromotedValue(result, e->
getType());
767 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
768 ignoreResultAssign =
false;
769 if (!promotionType.
isNull())
770 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
774 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
776 mlir::Value result = VisitUnaryMinus(e, promotionType);
777 if (result && !promotionType.
isNull())
778 return emitUnPromotedValue(result, e->
getType());
782 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
783 ignoreResultAssign =
false;
785 if (!promotionType.
isNull())
786 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
794 cgf.getLangOpts().getSignedOverflowBehavior() !=
795 LangOptions::SOB_Defined;
799 return builder.createOrFold<cir::MinusOp>(
803 mlir::Value emitIncOrDec(
const UnaryOperator *e, mlir::Value input,
807 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
808 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
811 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
812 ignoreResultAssign =
false;
814 return builder.createOrFold<cir::NotOp>(
818 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
820 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
821 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
822 mlir::Value VisitRealImag(
const UnaryOperator *e,
823 QualType promotionType = QualType());
825 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
830 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
832 "ScalarExprEmitter: materialize temporary");
835 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
836 ASTContext &ctx = cgf.getContext();
839 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
841 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
842 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
845 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
846 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
849 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
850 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
854 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
856 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
857 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
858 return cgf.emitCXXNewExpr(e);
860 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
861 cgf.emitCXXDeleteExpr(e);
864 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
870 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
875 "Expected int type for TypeTraitExpr");
876 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
882 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
888 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
890 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
893 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
896 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
898 "ScalarExprEmitter: cxx pseudo destructor");
901 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
902 cgf.emitCXXThrowExpr(e);
906 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
915 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
917 ScalarConversionOpts opts = ScalarConversionOpts()) {
927 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
933 if (srcType == dstType) {
934 if (opts.emitImplicitIntegerSignChangeChecks)
935 cgf.getCIRGenModule().errorNYI(loc,
936 "implicit integer sign change checks");
943 mlir::Type mlirSrcType = src.getType();
948 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
950 mlir::Type mlirDstType = cgf.convertType(dstType);
953 !cgf.getContext().getLangOpts().NativeHalfType) {
955 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
956 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
957 cgf.getCIRGenModule().errorNYI(loc,
958 "cast via llvm.convert.from.fp16");
963 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
964 cgf.getCIRGenModule().errorNYI(loc,
965 "cast via llvm.convert.from.fp16");
968 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
970 srcType = cgf.getContext().FloatTy;
971 mlirSrcType = cgf.floatTy;
977 if (mlirSrcType == mlirDstType) {
978 if (opts.emitImplicitIntegerSignChangeChecks)
979 cgf.getCIRGenModule().errorNYI(loc,
980 "implicit integer sign change checks");
987 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
988 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
989 return builder.getNullPtr(dstPT, src.getLoc());
995 return builder.createPtrToInt(src, mlirDstType);
1002 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1004 "Splatted expr doesn't match with vector element type?");
1006 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1011 cgf.getCIRGenModule().errorNYI(loc,
1012 "matrix type to matrix type conversion");
1016 "Internal error: conversion between matrix type and scalar type");
1019 mlir::Value res =
nullptr;
1020 mlir::Type resTy = mlirDstType;
1022 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1024 if (mlirDstType != resTy) {
1025 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1026 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1030 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1034 if (opts.emitImplicitIntegerTruncationChecks)
1035 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1037 if (opts.emitImplicitIntegerSignChangeChecks)
1038 cgf.getCIRGenModule().errorNYI(loc,
1039 "implicit integer sign change checks");
1044 BinOpInfo emitBinOps(
const BinaryOperator *e,
1045 QualType promotionType = QualType()) {
1046 ignoreResultAssign =
false;
1048 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1049 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1050 if (!promotionType.
isNull())
1051 result.fullType = promotionType;
1053 result.fullType = e->
getType();
1054 result.compType = result.fullType;
1055 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1056 result.compType = vecType->getElementType();
1061 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
1066 mlir::Value emitMul(
const BinOpInfo &ops);
1067 mlir::Value emitDiv(
const BinOpInfo &ops);
1068 mlir::Value emitRem(
const BinOpInfo &ops);
1069 mlir::Value emitAdd(
const BinOpInfo &ops);
1070 mlir::Value emitSub(
const BinOpInfo &ops);
1071 mlir::Value emitShl(
const BinOpInfo &ops);
1072 mlir::Value emitShr(
const BinOpInfo &ops);
1073 mlir::Value emitAnd(
const BinOpInfo &ops);
1074 mlir::Value emitXor(
const BinOpInfo &ops);
1075 mlir::Value emitOr(
const BinOpInfo &ops);
1077 LValue emitCompoundAssignLValue(
1078 const CompoundAssignOperator *e,
1079 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1080 mlir::Value &result);
1082 emitCompoundAssign(
const CompoundAssignOperator *e,
1083 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1087 QualType getPromotionType(QualType ty) {
1088 const clang::ASTContext &ctx = cgf.getContext();
1089 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1090 QualType elementTy = complexTy->getElementType();
1096 if (
auto *vt = ty->
getAs<VectorType>()) {
1097 unsigned numElements = vt->getNumElements();
1100 return cgf.getContext().FloatTy;
1107#define HANDLEBINOP(OP) \
1108 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1109 QualType promotionTy = getPromotionType(e->getType()); \
1110 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1111 if (result && !promotionTy.isNull()) \
1112 result = emitUnPromotedValue(result, e->getType()); \
1115 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1116 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1132 ignoreResultAssign =
false;
1138 auto clangCmpToCIRCmp =
1142 return cir::CmpOpKind::lt;
1144 return cir::CmpOpKind::gt;
1146 return cir::CmpOpKind::le;
1148 return cir::CmpOpKind::ge;
1150 return cir::CmpOpKind::eq;
1152 return cir::CmpOpKind::ne;
1154 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1166 BinOpInfo boInfo = emitBinOps(e);
1167 mlir::Value lhs = boInfo.lhs;
1168 mlir::Value rhs = boInfo.rhs;
1178 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1180 boInfo.lhs, boInfo.rhs);
1182 }
else if (boInfo.isFixedPointOp()) {
1185 result = builder.
getBool(
false, loc);
1189 mlir::isa<cir::PointerType>(lhs.getType()) &&
1190 mlir::isa<cir::PointerType>(rhs.getType())) {
1191 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1197 "Complex Comparison: can only be an equality comparison");
1203 mlir::Value lhsReal = Visit(e->
getLHS());
1204 mlir::Value lhsImag = builder.
getNullValue(convertType(lhsTy), loc);
1212 mlir::Value rhsReal = Visit(e->
getRHS());
1213 mlir::Value rhsImag = builder.
getNullValue(convertType(rhsTy), loc);
1225#define VISITCOMP(CODE) \
1226 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1236 const bool ignore = std::exchange(ignoreResultAssign,
false);
1251 rhs = Visit(e->
getRHS());
1261 if (lhs.isBitField()) {
1283 if (!lhs.isVolatile())
1287 return emitLoadOfLValue(lhs, e->
getExprLoc());
1290 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1291 cgf.emitIgnoredExpr(e->
getLHS());
1293 return Visit(e->
getRHS());
1296 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1298 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1300 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1302 mlir::Value lhs = Visit(e->
getLHS());
1303 mlir::Value rhs = Visit(e->
getRHS());
1305 auto cmpOpKind = cir::CmpOpKind::ne;
1306 mlir::Type resTy = cgf.convertType(e->
getType());
1307 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1308 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1309 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1310 return builder.createIntCast(vecOr, resTy);
1314 mlir::Type resTy = cgf.convertType(e->
getType());
1315 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1317 CIRGenFunction::ConditionalEvaluation eval(cgf);
1319 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1320 auto resOp = cir::TernaryOp::create(
1321 builder, loc, lhsCondV,
1322 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1323 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1324 b.getInsertionBlock()};
1325 cgf.curLexScope->setAsTernary();
1326 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1328 cir::YieldOp::create(
b, loc, res);
1331 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1332 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1333 b.getInsertionBlock()};
1335 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1336 cir::YieldOp::create(
b, loc, res.getRes());
1338 return maybePromoteBoolResult(resOp.getResult(), resTy);
1341 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1343 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1345 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1347 mlir::Value lhs = Visit(e->
getLHS());
1348 mlir::Value rhs = Visit(e->
getRHS());
1350 auto cmpOpKind = cir::CmpOpKind::ne;
1351 mlir::Type resTy = cgf.convertType(e->
getType());
1352 lhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, lhs, zeroVec);
1353 rhs = cir::VecCmpOp::create(builder, loc, resTy, cmpOpKind, rhs, zeroVec);
1354 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1355 return builder.createIntCast(vecOr, resTy);
1359 mlir::Type resTy = cgf.convertType(e->
getType());
1360 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1362 CIRGenFunction::ConditionalEvaluation eval(cgf);
1364 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1365 auto resOp = cir::TernaryOp::create(
1366 builder, loc, lhsCondV,
1367 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1368 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1369 b.getInsertionBlock()};
1371 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1372 cir::YieldOp::create(
b, loc, res.getRes());
1375 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1376 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1377 b.getInsertionBlock()};
1379 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1381 cir::YieldOp::create(
b, loc, res);
1384 return maybePromoteBoolResult(resOp.getResult(), resTy);
1387 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1388 return emitLoadOfLValue(e);
1391 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1392 return emitLoadOfLValue(e);
1396 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1397 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1401 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1405 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1407 "ScalarExprEmitter: objc string literal");
1410 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1411 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1414 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1416 "ScalarExprEmitter: objc array literal");
1419 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1421 "ScalarExprEmitter: objc dictionary literal");
1425 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1426 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1430 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1431 return cgf.emitAtomicExpr(e).getValue();
1435LValue ScalarExprEmitter::emitCompoundAssignLValue(
1437 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1438 mlir::Value &result) {
1449 if (promotionTypeCR.
isNull())
1453 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1455 if (!promotionTypeRHS.
isNull())
1458 opInfo.rhs = Visit(e->
getRHS());
1460 opInfo.fullType = promotionTypeCR;
1461 opInfo.compType = opInfo.fullType;
1462 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1463 opInfo.compType = vecType->getElementType();
1472 if (lhsTy->
getAs<AtomicType>()) {
1473 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1477 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1479 CIRGenFunction::SourceLocRAIIObject sourceloc{
1482 if (!promotionTypeLHS.
isNull())
1483 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1485 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1489 result = (this->*func)(opInfo);
1493 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1494 ScalarConversionOpts(cgf.
sanOpts));
1500 if (lhsLV.isBitField())
1511mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1515 cir::CastKind castOpKind;
1517 case CK_FloatingComplexToReal:
1518 castOpKind = cir::CastKind::float_complex_to_real;
1520 case CK_IntegralComplexToReal:
1521 castOpKind = cir::CastKind::int_complex_to_real;
1523 case CK_FloatingComplexToBoolean:
1524 castOpKind = cir::CastKind::float_complex_to_bool;
1526 case CK_IntegralComplexToBoolean:
1527 castOpKind = cir::CastKind::int_complex_to_bool;
1530 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1536mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1537 QualType promotionType) {
1539 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1540 switch (bo->getOpcode()) {
1541#define HANDLE_BINOP(OP) \
1543 return emit##OP(emitBinOps(bo, promotionType));
1552 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1553 switch (uo->getOpcode()) {
1556 return VisitRealImag(uo, promotionType);
1558 return VisitUnaryMinus(uo, promotionType);
1560 return VisitUnaryPlus(uo, promotionType);
1565 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1567 if (!promotionType.
isNull())
1568 return emitPromotedValue(result, promotionType);
1569 return emitUnPromotedValue(result, e->
getType());
1574mlir::Value ScalarExprEmitter::emitCompoundAssign(
1575 const CompoundAssignOperator *e,
1576 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1578 bool ignore = std::exchange(ignoreResultAssign,
false);
1580 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1591 if (!lhs.isVolatile())
1595 return emitLoadOfLValue(lhs, e->
getExprLoc());
1598mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1599 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1614#define COMPOUND_OP(Op) \
1615 case BO_##Op##Assign: \
1616 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1653 llvm_unreachable(
"Not valid compound assignment operators");
1655 llvm_unreachable(
"Unhandled compound assignment operator");
1660 bool ignoreResultAssign) {
1662 "Invalid scalar expression to emit");
1665 .Visit(
const_cast<Expr *
>(e));
1670 if (!promotionType.
isNull())
1685static std::optional<QualType>
1689 return std::nullopt;
1694 return std::nullopt;
1707 const BinOpInfo &op) {
1709 "Expected a unary or binary operator");
1713 if (!op.mayHaveIntegerOverflow())
1717 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1718 return !uo->canOverflow();
1723 std::optional<QualType> optionalLHSTy =
1728 std::optional<QualType> optionalRHSTy =
1738 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1745 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1746 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1751 const BinOpInfo &op,
1752 bool isSubtraction) {
1757 mlir::Value pointer = op.lhs;
1758 Expr *pointerOperand =
expr->getLHS();
1759 mlir::Value
index = op.rhs;
1760 Expr *indexOperand =
expr->getRHS();
1766 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1767 std::swap(pointer,
index);
1768 std::swap(pointerOperand, indexOperand);
1770 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1771 "Need a pointer operand");
1772 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1807 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1818 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1820 pointer.getType(), pointer,
index);
1823mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1824 const mlir::Location loc = cgf.
getLoc(ops.loc);
1826 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1827 case LangOptions::SOB_Defined:
1828 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1829 return builder.
createMul(loc, ops.lhs, ops.rhs);
1831 case LangOptions::SOB_Undefined:
1832 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1835 case LangOptions::SOB_Trapping:
1847 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1849 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1851 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1852 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1853 return builder.
createFMul(loc, ops.lhs, ops.rhs);
1856 if (ops.isFixedPointOp()) {
1862 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
1865mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1866 return cir::DivOp::create(builder, cgf.
getLoc(ops.loc),
1869mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1870 return cir::RemOp::create(builder, cgf.
getLoc(ops.loc),
1874mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1875 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1876 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1879 const mlir::Location loc = cgf.
getLoc(ops.loc);
1881 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1882 case LangOptions::SOB_Defined:
1883 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1884 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1886 case LangOptions::SOB_Undefined:
1887 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1890 case LangOptions::SOB_Trapping:
1903 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1905 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1907 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1908 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1909 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
1912 if (ops.isFixedPointOp()) {
1918 return builder.
createAdd(loc, ops.lhs, ops.rhs);
1921mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1922 const mlir::Location loc = cgf.
getLoc(ops.loc);
1924 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1926 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1927 case LangOptions::SOB_Defined: {
1928 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1929 return builder.
createSub(loc, ops.lhs, ops.rhs);
1932 case LangOptions::SOB_Undefined:
1933 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1936 case LangOptions::SOB_Trapping:
1950 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1952 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1954 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1955 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
1956 return builder.
createFSub(loc, ops.lhs, ops.rhs);
1959 if (ops.isFixedPointOp()) {
1965 return builder.
createSub(loc, ops.lhs, ops.rhs);
1970 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1982 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1986mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1988 if (ops.isFixedPointOp()) {
1998 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2002 bool sanitizeUnsignedBase =
2003 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2005 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2006 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2011 else if ((sanitizeBase || sanitizeExponent) &&
2012 mlir::isa<cir::IntType>(ops.lhs.getType()))
2018mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2020 if (ops.isFixedPointOp()) {
2033 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2034 mlir::isa<cir::IntType>(ops.lhs.getType()))
2042mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2043 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2045mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2046 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2048mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2049 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2056mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2058 QualType destTy = ce->
getType();
2063 ignoreResultAssign =
false;
2066 case clang::CK_Dependent:
2067 llvm_unreachable(
"dependent cast kind in CIR gen!");
2068 case clang::CK_BuiltinFnToFnPtr:
2069 llvm_unreachable(
"builtin functions are handled elsewhere");
2070 case CK_LValueBitCast:
2071 case CK_LValueToRValueBitCast: {
2073 Address sourceAddr = sourceLVal.getAddress();
2079 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2082 case CK_CPointerToObjCPointerCast:
2083 case CK_BlockPointerToObjCPointerCast:
2084 case CK_AnyPointerToBlockPointerCast:
2086 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2091 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2093 "sanitizer support");
2097 "strict vtable pointers");
2123 case CK_AddressSpaceConversion: {
2124 Expr::EvalResult result;
2138 case CK_AtomicToNonAtomic: {
2144 case CK_NonAtomicToAtomic:
2145 case CK_UserDefinedConversion:
2146 return Visit(
const_cast<Expr *
>(subExpr));
2150 case CK_IntegralToPointer: {
2152 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2161 : cir::CastKind::integral,
2166 "IntegralToPointer: strict vtable pointers");
2173 case CK_BaseToDerived: {
2175 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2187 case CK_UncheckedDerivedToBase:
2188 case CK_DerivedToBase: {
2199 case CK_ArrayToPointerDecay:
2202 case CK_NullToPointer: {
2212 case CK_NullToMemberPointer: {
2218 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2224 case CK_ReinterpretMemberPointer: {
2225 mlir::Value src = Visit(subExpr);
2229 case CK_BaseToDerivedMemberPointer:
2230 case CK_DerivedToBaseMemberPointer: {
2231 mlir::Value src = Visit(subExpr);
2235 QualType derivedTy =
2236 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2237 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2238 NestedNameSpecifier qualifier = mpType->getQualifier();
2239 assert(qualifier &&
"member pointer without class qualifier");
2240 const Type *qualifierType = qualifier.getAsType();
2241 assert(qualifierType &&
"member pointer qualifier is not a type");
2248 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2251 if (
kind == CK_BaseToDerivedMemberPointer)
2252 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2254 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2257 if (
kind == CK_BaseToDerivedMemberPointer)
2258 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2260 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2264 case CK_LValueToRValue:
2266 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2267 return Visit(
const_cast<Expr *
>(subExpr));
2269 case CK_IntegralCast: {
2270 ScalarConversionOpts opts;
2271 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2272 if (!ice->isPartOfExplicitCast())
2273 opts = ScalarConversionOpts(cgf.
sanOpts);
2275 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2279 case CK_FloatingComplexToReal:
2280 case CK_IntegralComplexToReal:
2281 case CK_FloatingComplexToBoolean:
2282 case CK_IntegralComplexToBoolean: {
2288 case CK_FloatingRealToComplex:
2289 case CK_FloatingComplexCast:
2290 case CK_IntegralRealToComplex:
2291 case CK_IntegralComplexCast:
2292 case CK_IntegralComplexToFloatingComplex:
2293 case CK_FloatingComplexToIntegralComplex:
2294 llvm_unreachable(
"scalar cast to non-scalar value");
2296 case CK_PointerToIntegral: {
2297 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2300 "strict vtable pointers");
2307 case CK_IntegralToFloating:
2308 case CK_FloatingToIntegral:
2309 case CK_FloatingCast:
2310 case CK_FixedPointToFloating:
2311 case CK_FloatingToFixedPoint: {
2312 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2314 "fixed point casts");
2317 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2318 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2322 case CK_IntegralToBoolean:
2323 return emitIntToBoolConversion(Visit(subExpr),
2326 case CK_PointerToBoolean:
2327 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2328 case CK_FloatingToBoolean:
2329 return emitFloatToBoolConversion(Visit(subExpr),
2331 case CK_MemberPointerToBoolean: {
2332 mlir::Value memPtr = Visit(subExpr);
2334 cir::CastKind::member_ptr_to_bool, memPtr,
2338 case CK_VectorSplat: {
2340 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2341 return cir::VecSplatOp::create(builder,
2345 case CK_FunctionToPointerDecay:
2355mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2357 return emitLoadOfLValue(e);
2364mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2369 Expr::EvalResult result;
2371 llvm::APSInt value = result.
Val.
getInt();
2375 return emitLoadOfLValue(e);
2378mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2379 const unsigned numInitElements = e->
getNumInits();
2381 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2382 assert((ignore ==
false ||
2384 "init list ignored");
2392 const auto vectorType =
2395 SmallVector<mlir::Value, 16> elements;
2396 for (Expr *init : e->
inits()) {
2397 elements.push_back(Visit(init));
2401 if (numInitElements < vectorType.getSize()) {
2404 std::fill_n(std::back_inserter(elements),
2405 vectorType.getSize() - numInitElements, zeroValue);
2408 return cir::VecCreateOp::create(cgf.
getBuilder(),
2414 if (numInitElements == 0)
2425 "Invalid scalar expression to emit");
2427 .emitScalarConversion(src, srcTy, dstTy, loc);
2435 "Invalid complex -> scalar conversion");
2440 ? cir::CastKind::float_complex_to_bool
2441 : cir::CastKind::int_complex_to_bool;
2446 ? cir::CastKind::float_complex_to_real
2447 : cir::CastKind::int_complex_to_real;
2453mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2460 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2462 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
2463 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2477mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2482 llvm::APSInt value = evalResult.
Val.
getInt();
2488 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2492mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2494 mlir::Value result = VisitRealImag(e, promotionTy);
2495 if (result && !promotionTy.
isNull())
2496 result = emitUnPromotedValue(result, e->
getType());
2500mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2502 mlir::Value result = VisitRealImag(e, promotionTy);
2503 if (result && !promotionTy.
isNull())
2504 result = emitUnPromotedValue(result, e->
getType());
2508mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2509 QualType promotionTy) {
2512 "Invalid UnaryOp kind for ComplexType Real or Imag");
2534 mlir::Value operand = promotionTy.
isNull()
2536 : cgf.emitPromotedScalarExpr(op, promotionTy);
2542 mlir::Value operand;
2545 operand = cir::LoadOp::create(builder, loc, operand);
2546 }
else if (!promotionTy.
isNull()) {
2556mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2557 const UnaryExprOrTypeTraitExpr *e) {
2561 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2562 if (
const VariableArrayType *vat =
2567 bool evaluateExtent =
true;
2568 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2570 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2573 if (evaluateExtent) {
2584 if (
kind == UETT_CountOf)
2589 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2590 mlir::Value numElts = vlaSize.
numElts;
2594 if (!eltSize.
isOne()) {
2596 mlir::Value eltSizeValue =
2599 return builder.
createMul(loc, eltSizeValue, numElts,
2606 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2613 }
else if (e->
getKind() == UETT_VectorElements) {
2615 if (vecTy.getIsScalable()) {
2618 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2625 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2650mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2651 const AbstractConditionalOperator *e) {
2654 ignoreResultAssign =
false;
2657 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2659 Expr *condExpr = e->
getCond();
2667 Expr *live = lhsExpr, *dead = rhsExpr;
2669 std::swap(live, dead);
2675 mlir::Value result = Visit(live);
2682 loc, cir::PoisonAttr::get(builder.getContext(),
2690 QualType condType = condExpr->
getType();
2703 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2707 mlir::Value condValue = Visit(condExpr);
2708 mlir::Value lhsValue = Visit(lhsExpr);
2709 mlir::Value rhsValue = Visit(rhsExpr);
2710 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2719 bool lhsIsVoid =
false;
2723 mlir::Value lhs = Visit(lhsExpr);
2729 mlir::Value rhs = Visit(rhsExpr);
2731 assert(!rhs &&
"lhs and rhs types must match");
2739 CIRGenFunction::ConditionalEvaluation eval(cgf);
2740 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2741 mlir::Type yieldTy{};
2743 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2744 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2748 eval.beginEvaluation();
2749 mlir::Value branch = Visit(
expr);
2750 eval.endEvaluation();
2753 yieldTy = branch.getType();
2754 cir::YieldOp::create(
b, loc, branch);
2758 insertPoints.push_back(
b.saveInsertionPoint());
2762 mlir::Value result = cir::TernaryOp::create(
2763 builder, loc, condV,
2765 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2766 emitBranch(
b, loc, lhsExpr);
2769 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2770 emitBranch(
b, loc, rhsExpr);
2774 if (!insertPoints.empty()) {
2780 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2781 mlir::OpBuilder::InsertionGuard guard(builder);
2782 builder.restoreInsertionPoint(toInsert);
2785 if (mlir::isa<cir::VoidType>(yieldTy)) {
2786 cir::YieldOp::create(builder, loc);
2789 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
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 ...
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::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.
@ 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.