22#include "mlir/IR/Location.h"
23#include "mlir/IR/Value.h"
45 bool isDivRemOp()
const {
46 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
47 opcode == BO_RemAssign;
51 bool mayHaveIntegerOverflow()
const {
53 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
54 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
66 bool isFixedPointOp()
const {
69 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
70 QualType lhstype = binOp->getLHS()->getType();
71 QualType rhstype = binOp->getRHS()->getType();
74 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
75 return unop->getSubExpr()->getType()->isFixedPointType();
80class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
82 CIRGenBuilderTy &builder;
86 bool ignoreResultAssign;
89 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
90 bool ignoreResultAssign =
false)
91 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
96 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
98 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
102 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
103 return cgf.cgm.emitNullConstant(ty, loc);
106 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
107 return builder.createFloatingCast(result, cgf.convertType(promotionType));
110 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
111 return builder.createFloatingCast(result, cgf.convertType(exprType));
114 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
116 mlir::Value maybePromoteBoolResult(mlir::Value value,
117 mlir::Type dstTy)
const {
118 if (mlir::isa<cir::IntType>(dstTy))
119 return builder.createBoolToInt(value, dstTy);
120 if (mlir::isa<cir::BoolType>(dstTy))
122 llvm_unreachable(
"Can only promote integer or boolean types");
129 mlir::Value Visit(Expr *e) {
130 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
133 mlir::Value VisitStmt(Stmt *
s) {
134 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
137 mlir::Value VisitExpr(Expr *e) {
138 cgf.getCIRGenModule().errorNYI(
143 mlir::Value VisitConstantExpr(ConstantExpr *e) {
149 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
152 "ScalarExprEmitter: constant expr GL Value");
157 mlir::cast<mlir::TypedAttr>(result));
160 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
164 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
168 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
170 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
175 mlir::Value emitLoadOfLValue(
const Expr *e) {
176 LValue lv = cgf.emitLValue(e);
178 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
181 mlir::Value VisitCoawaitExpr(CoawaitExpr *
s) {
182 return cgf.emitCoawaitExpr(*s).getValue();
184 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
185 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: coyield");
188 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
189 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
193 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
194 return cgf.emitLoadOfLValue(lv, loc).getValue();
198 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
199 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
200 return cgf.emitScalarConstant(constant, e);
202 return emitLoadOfLValue(e);
205 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
207 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
209 cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
212 cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
213 if (!resolvedLabel) {
214 cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
217 cgf.cgm.mapResolvedBlockAddress(blockAddressOp,
nullptr);
219 cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
221 cgf.instantiateIndirectGotoBlock();
222 return blockAddressOp;
225 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
227 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
231 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
233 "ScalarExprEmitter: fixed point literal");
237 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
239 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
240 "expect floating-point type");
241 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
245 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
246 mlir::Type ty = cgf.convertType(e->
getType());
247 auto init = cir::IntAttr::get(ty, e->
getValue());
248 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()), init);
251 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
255 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
262 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
266 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
268 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
269 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: size of pack");
272 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
273 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: pseudo object");
276 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
278 "ScalarExprEmitter: sycl unique stable name");
281 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
283 auto it = e->
begin();
284 llvm::APInt value = (*it)->getValue();
285 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
288 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
290 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
294 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
297 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
298 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
301 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
302 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
305 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
306 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
309 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
310 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
313 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
314 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
317 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
319 "ScalarExprEmitter: objc availability check");
323 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
325 "ScalarExprEmitter: matrix subscript");
329 mlir::Value VisitCastExpr(
CastExpr *e);
330 mlir::Value VisitCallExpr(
const CallExpr *e);
332 mlir::Value VisitStmtExpr(StmtExpr *e) {
333 CIRGenFunction::StmtExprEvaluation eval(cgf);
341 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
343 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
347 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
348 ignoreResultAssign =
false;
354 const mlir::Value vecValue = Visit(e->
getBase());
355 const mlir::Value indexValue = Visit(e->
getIdx());
356 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
359 return emitLoadOfLValue(e);
362 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
365 mlir::Value inputVec = Visit(e->
getExpr(0));
366 mlir::Value indexVec = Visit(e->
getExpr(1));
367 return cir::VecShuffleDynamicOp::create(
368 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
371 mlir::Value vec1 = Visit(e->
getExpr(0));
372 mlir::Value vec2 = Visit(e->
getExpr(1));
377 SmallVector<mlir::Attribute, 8> indices;
380 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
386 return cir::VecShuffleOp::create(cgf.builder,
388 cgf.convertType(e->
getType()), vec1, vec2,
389 cgf.builder.getArrayAttr(indices));
392 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
395 return emitScalarConversion(Visit(e->
getSrcExpr()),
400 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
402 mlir::Value VisitMemberExpr(MemberExpr *e);
404 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
405 return emitLoadOfLValue(e);
408 mlir::Value VisitInitListExpr(InitListExpr *e);
410 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
412 "ScalarExprEmitter: array init index");
416 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
418 "ScalarExprEmitter: implicit value init");
422 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
423 return VisitCastExpr(e);
426 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
427 return cgf.cgm.emitNullConstant(e->
getType(),
432 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
435 return cgf.getBuilder().createPtrToBoolCast(v);
438 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
439 cir::BoolType boolTy = builder.getBoolTy();
440 return cir::CastOp::create(builder, loc, boolTy,
441 cir::CastKind::float_to_bool, src);
444 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
450 cir::BoolType boolTy = builder.getBoolTy();
451 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
457 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
458 mlir::Location loc) {
459 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
462 return emitFloatToBoolConversion(src, loc);
464 if (llvm::isa<MemberPointerType>(srcType)) {
465 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
466 return builder.getFalse(loc);
470 return emitIntToBoolConversion(src, loc);
472 assert(::mlir::isa<cir::PointerType>(src.getType()));
473 return emitPointerToBoolConversion(src, srcType);
478 struct ScalarConversionOpts {
479 bool treatBooleanAsSigned;
480 bool emitImplicitIntegerTruncationChecks;
481 bool emitImplicitIntegerSignChangeChecks;
483 ScalarConversionOpts()
484 : treatBooleanAsSigned(
false),
485 emitImplicitIntegerTruncationChecks(
false),
486 emitImplicitIntegerSignChangeChecks(
false) {}
488 ScalarConversionOpts(clang::SanitizerSet sanOpts)
489 : treatBooleanAsSigned(
false),
490 emitImplicitIntegerTruncationChecks(
491 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
492 emitImplicitIntegerSignChangeChecks(
493 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
500 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
501 QualType dstType, mlir::Type srcTy,
502 mlir::Type dstTy, ScalarConversionOpts opts) {
504 "Internal error: matrix types not handled by this function.");
505 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
506 mlir::isa<mlir::IntegerType>(dstTy)) &&
507 "Obsolete code. Don't use mlir::IntegerType with CIR.");
509 mlir::Type fullDstTy = dstTy;
510 if (mlir::isa<cir::VectorType>(srcTy) &&
511 mlir::isa<cir::VectorType>(dstTy)) {
513 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
514 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
517 std::optional<cir::CastKind> castKind;
519 if (mlir::isa<cir::BoolType>(srcTy)) {
520 if (opts.treatBooleanAsSigned)
521 cgf.getCIRGenModule().errorNYI(
"signed bool");
522 if (cgf.getBuilder().isInt(dstTy))
523 castKind = cir::CastKind::bool_to_int;
524 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
525 castKind = cir::CastKind::bool_to_float;
527 llvm_unreachable(
"Internal error: Cast to unexpected type");
528 }
else if (cgf.getBuilder().isInt(srcTy)) {
529 if (cgf.getBuilder().isInt(dstTy))
530 castKind = cir::CastKind::integral;
531 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
532 castKind = cir::CastKind::int_to_float;
534 llvm_unreachable(
"Internal error: Cast to unexpected type");
535 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
536 if (cgf.getBuilder().isInt(dstTy)) {
540 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
541 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
543 castKind = cir::CastKind::float_to_int;
544 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
546 return builder.createFloatingCast(src, fullDstTy);
548 llvm_unreachable(
"Internal error: Cast to unexpected type");
551 llvm_unreachable(
"Internal error: Cast from unexpected type");
554 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
555 return cir::CastOp::create(builder, src.getLoc(), fullDstTy, *castKind,
560 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
564 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
569 "variably modified types in varargs");
572 return cgf.emitVAArg(ve);
575 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
579 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
581 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
584 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
586 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
588 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
590 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
592 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
594 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
596 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
598 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
600 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
601 cir::UnaryOpKind kind,
bool isPre) {
602 if (cgf.getLangOpts().OpenMP)
610 if (
type->getAs<AtomicType>()) {
614 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
617 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
630 if (kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
631 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
632 }
else if (
type->isIntegerType()) {
633 QualType promotedType;
634 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
635 if (cgf.getContext().isPromotableIntegerType(
type)) {
636 promotedType = cgf.getContext().getPromotedIntegerType(
type);
637 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
638 canPerformLossyDemotionCheck =
true;
639 canPerformLossyDemotionCheck &=
640 cgf.getContext().getCanonicalType(
type) !=
641 cgf.getContext().getCanonicalType(promotedType);
642 canPerformLossyDemotionCheck &=
649 (!canPerformLossyDemotionCheck ||
650 type->isSignedIntegerOrEnumerationType() ||
652 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
653 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
654 "The following check expects that if we do promotion to different "
655 "underlying canonical type, at least one of the types (either "
656 "base or promoted) will be signed, or the bitwidths will match.");
661 value = emitIncDecConsiderOverflowBehavior(e, value, kind);
663 cir::UnaryOpKind
kind =
664 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
666 value = emitUnaryOp(e, kind, input,
false);
668 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
669 QualType
type = ptr->getPointeeType();
670 if (cgf.getContext().getAsVariableArrayType(
type)) {
672 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
674 }
else if (
type->isFunctionType()) {
677 "Pointer arithmetic on function pointer");
682 CIRGenBuilderTy &builder = cgf.getBuilder();
683 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
684 mlir::Value amt = builder.getSInt32(amount, loc);
686 value = builder.createPtrStride(loc, value, amt);
688 }
else if (
type->isVectorType()) {
691 }
else if (
type->isRealFloatingType()) {
694 if (
type->isHalfType() &&
695 !cgf.getContext().getLangOpts().NativeHalfType) {
700 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
703 assert(kind == cir::UnaryOpKind::Inc ||
704 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
705 value = emitUnaryOp(e, kind, value);
707 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
710 }
else if (
type->isFixedPointType()) {
711 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
714 assert(
type->castAs<ObjCObjectPointerType>());
715 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
719 CIRGenFunction::SourceLocRAIIObject sourceloc{
724 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
726 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
730 return isPre ? value : input;
733 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
735 cir::UnaryOpKind kind) {
736 assert(kind == cir::UnaryOpKind::Inc ||
737 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
738 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
739 case LangOptions::SOB_Defined:
740 return emitUnaryOp(e, kind, inVal,
false);
741 case LangOptions::SOB_Undefined:
743 return emitUnaryOp(e, kind, inVal,
true);
744 case LangOptions::SOB_Trapping:
746 return emitUnaryOp(e, kind, inVal,
true);
747 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
750 llvm_unreachable(
"Unexpected signed overflow behavior kind");
753 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
754 if (llvm::isa<MemberPointerType>(e->
getType()))
755 return cgf.cgm.emitMemberPointerConstant(e);
757 return cgf.emitLValue(e->
getSubExpr()).getPointer();
760 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
763 return emitLoadOfLValue(e);
766 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
769 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
770 if (result && !promotionType.
isNull())
771 return emitUnPromotedValue(result, e->
getType());
775 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
778 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
779 if (result && !promotionType.
isNull())
780 return emitUnPromotedValue(result, e->
getType());
784 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
785 cir::UnaryOpKind kind,
786 QualType promotionType) {
787 ignoreResultAssign =
false;
789 if (!promotionType.
isNull())
790 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
799 return emitUnaryOp(e, kind, operand, nsw);
802 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind kind,
803 mlir::Value input,
bool nsw =
false) {
804 return cir::UnaryOp::create(builder,
806 input.getType(), kind, input, nsw);
809 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
810 ignoreResultAssign =
false;
812 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
815 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
817 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
818 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
819 mlir::Value VisitRealImag(
const UnaryOperator *e,
820 QualType promotionType = QualType());
822 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
827 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
829 "ScalarExprEmitter: materialize temporary");
832 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
833 ASTContext &ctx = cgf.getContext();
836 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
838 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
839 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
842 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
843 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
846 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
847 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
851 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
853 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
854 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
855 return cgf.emitCXXNewExpr(e);
857 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
858 cgf.emitCXXDeleteExpr(e);
861 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
862 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
866 "ScalarExprEmitter: TypeTraitExpr stored as int");
870 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
876 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
878 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
881 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
884 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
886 "ScalarExprEmitter: cxx pseudo destructor");
889 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
890 cgf.emitCXXThrowExpr(e);
894 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
903 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
905 ScalarConversionOpts opts = ScalarConversionOpts()) {
915 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
921 if (srcType == dstType) {
922 if (opts.emitImplicitIntegerSignChangeChecks)
923 cgf.getCIRGenModule().errorNYI(loc,
924 "implicit integer sign change checks");
931 mlir::Type mlirSrcType = src.getType();
936 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
938 mlir::Type mlirDstType = cgf.convertType(dstType);
941 !cgf.getContext().getLangOpts().NativeHalfType) {
943 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
944 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
945 cgf.getCIRGenModule().errorNYI(loc,
946 "cast via llvm.convert.from.fp16");
951 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
952 cgf.getCIRGenModule().errorNYI(loc,
953 "cast via llvm.convert.from.fp16");
956 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
958 srcType = cgf.getContext().FloatTy;
959 mlirSrcType = cgf.floatTy;
965 if (mlirSrcType == mlirDstType) {
966 if (opts.emitImplicitIntegerSignChangeChecks)
967 cgf.getCIRGenModule().errorNYI(loc,
968 "implicit integer sign change checks");
975 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
976 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
977 return builder.getNullPtr(dstPT, src.getLoc());
983 return builder.createPtrToInt(src, mlirDstType);
990 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
992 "Splatted expr doesn't match with vector element type?");
994 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
999 cgf.getCIRGenModule().errorNYI(loc,
1000 "matrix type to matrix type conversion");
1004 "Internal error: conversion between matrix type and scalar type");
1007 mlir::Value res =
nullptr;
1008 mlir::Type resTy = mlirDstType;
1010 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1012 if (mlirDstType != resTy) {
1013 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1014 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1018 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1022 if (opts.emitImplicitIntegerTruncationChecks)
1023 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1025 if (opts.emitImplicitIntegerSignChangeChecks)
1026 cgf.getCIRGenModule().errorNYI(loc,
1027 "implicit integer sign change checks");
1032 BinOpInfo emitBinOps(
const BinaryOperator *e,
1033 QualType promotionType = QualType()) {
1034 ignoreResultAssign =
false;
1036 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1037 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1038 if (!promotionType.
isNull())
1039 result.fullType = promotionType;
1041 result.fullType = e->
getType();
1042 result.compType = result.fullType;
1043 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1044 result.compType = vecType->getElementType();
1054 mlir::Value emitMul(
const BinOpInfo &ops);
1055 mlir::Value emitDiv(
const BinOpInfo &ops);
1056 mlir::Value emitRem(
const BinOpInfo &ops);
1057 mlir::Value emitAdd(
const BinOpInfo &ops);
1058 mlir::Value emitSub(
const BinOpInfo &ops);
1059 mlir::Value emitShl(
const BinOpInfo &ops);
1060 mlir::Value emitShr(
const BinOpInfo &ops);
1061 mlir::Value emitAnd(
const BinOpInfo &ops);
1062 mlir::Value emitXor(
const BinOpInfo &ops);
1063 mlir::Value emitOr(
const BinOpInfo &ops);
1065 LValue emitCompoundAssignLValue(
1066 const CompoundAssignOperator *e,
1067 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1068 mlir::Value &result);
1070 emitCompoundAssign(
const CompoundAssignOperator *e,
1071 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1075 QualType getPromotionType(QualType ty) {
1076 const clang::ASTContext &ctx = cgf.getContext();
1077 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1078 QualType elementTy = complexTy->getElementType();
1084 if (
auto *vt = ty->
getAs<VectorType>()) {
1085 unsigned numElements = vt->getNumElements();
1088 return cgf.getContext().FloatTy;
1095#define HANDLEBINOP(OP) \
1096 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1097 QualType promotionTy = getPromotionType(e->getType()); \
1098 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1099 if (result && !promotionTy.isNull()) \
1100 result = emitUnPromotedValue(result, e->getType()); \
1103 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1104 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1120 ignoreResultAssign =
false;
1126 auto clangCmpToCIRCmp =
1130 return cir::CmpOpKind::lt;
1132 return cir::CmpOpKind::gt;
1134 return cir::CmpOpKind::le;
1136 return cir::CmpOpKind::ge;
1138 return cir::CmpOpKind::eq;
1140 return cir::CmpOpKind::ne;
1142 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1146 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1154 BinOpInfo boInfo = emitBinOps(e);
1155 mlir::Value lhs = boInfo.lhs;
1156 mlir::Value rhs = boInfo.rhs;
1166 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1168 boInfo.lhs, boInfo.rhs);
1170 }
else if (boInfo.isFixedPointOp()) {
1173 result = builder.
getBool(
false, loc);
1177 mlir::isa<cir::PointerType>(lhs.getType()) &&
1178 mlir::isa<cir::PointerType>(rhs.getType())) {
1179 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1182 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1189 BinOpInfo boInfo = emitBinOps(e);
1190 result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);
1198#define VISITCOMP(CODE) \
1199 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1209 const bool ignore = std::exchange(ignoreResultAssign,
false);
1224 rhs = Visit(e->
getRHS());
1234 if (lhs.isBitField()) {
1254 if (!lhs.isVolatile())
1258 return emitLoadOfLValue(lhs, e->
getExprLoc());
1261 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1262 cgf.emitIgnoredExpr(e->
getLHS());
1264 return Visit(e->
getRHS());
1267 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1269 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1270 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1271 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1272 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1273 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1275 mlir::Value lhs = Visit(e->
getLHS());
1276 mlir::Value rhs = Visit(e->
getRHS());
1278 auto cmpOpKind = cir::CmpOpKind::ne;
1279 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1280 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1281 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1282 return builder.createIntCast(vecOr, vecTy);
1286 mlir::Type resTy = cgf.convertType(e->
getType());
1287 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1289 CIRGenFunction::ConditionalEvaluation eval(cgf);
1291 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1292 auto resOp = cir::TernaryOp::create(
1293 builder, loc, lhsCondV,
1294 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1295 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1296 b.getInsertionBlock()};
1297 cgf.curLexScope->setAsTernary();
1298 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1300 cir::YieldOp::create(
b, loc, res);
1303 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1304 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1305 b.getInsertionBlock()};
1307 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1308 cir::YieldOp::create(
b, loc, res.getRes());
1310 return maybePromoteBoolResult(resOp.getResult(), resTy);
1313 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1315 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1316 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1317 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1318 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1319 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1321 mlir::Value lhs = Visit(e->
getLHS());
1322 mlir::Value rhs = Visit(e->
getRHS());
1324 auto cmpOpKind = cir::CmpOpKind::ne;
1325 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1326 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1327 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1328 return builder.createIntCast(vecOr, vecTy);
1332 mlir::Type resTy = cgf.convertType(e->
getType());
1333 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1335 CIRGenFunction::ConditionalEvaluation eval(cgf);
1337 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1338 auto resOp = cir::TernaryOp::create(
1339 builder, loc, lhsCondV,
1340 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1341 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1342 b.getInsertionBlock()};
1344 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1345 cir::YieldOp::create(
b, loc, res.getRes());
1348 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1349 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1350 b.getInsertionBlock()};
1352 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1354 cir::YieldOp::create(
b, loc, res);
1357 return maybePromoteBoolResult(resOp.getResult(), resTy);
1360 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1361 return emitLoadOfLValue(e);
1364 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1365 return emitLoadOfLValue(e);
1369 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1370 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1374 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1378 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1380 "ScalarExprEmitter: objc string literal");
1383 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1384 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1387 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1389 "ScalarExprEmitter: objc array literal");
1392 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1394 "ScalarExprEmitter: objc dictionary literal");
1398 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1399 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1403 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1404 return cgf.emitAtomicExpr(e).getValue();
1408LValue ScalarExprEmitter::emitCompoundAssignLValue(
1410 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1411 mlir::Value &result) {
1422 if (promotionTypeCR.
isNull())
1426 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1428 if (!promotionTypeRHS.
isNull())
1431 opInfo.rhs = Visit(e->
getRHS());
1433 opInfo.fullType = promotionTypeCR;
1434 opInfo.compType = opInfo.fullType;
1435 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1436 opInfo.compType = vecType->getElementType();
1445 if (lhsTy->
getAs<AtomicType>()) {
1446 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1450 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1452 CIRGenFunction::SourceLocRAIIObject sourceloc{
1455 if (!promotionTypeLHS.
isNull())
1456 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1458 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1462 result = (this->*func)(opInfo);
1466 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1467 ScalarConversionOpts(cgf.
sanOpts));
1473 if (lhsLV.isBitField())
1484mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1488 cir::CastKind castOpKind;
1490 case CK_FloatingComplexToReal:
1491 castOpKind = cir::CastKind::float_complex_to_real;
1493 case CK_IntegralComplexToReal:
1494 castOpKind = cir::CastKind::int_complex_to_real;
1496 case CK_FloatingComplexToBoolean:
1497 castOpKind = cir::CastKind::float_complex_to_bool;
1499 case CK_IntegralComplexToBoolean:
1500 castOpKind = cir::CastKind::int_complex_to_bool;
1503 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1509mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1510 QualType promotionType) {
1512 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1513 switch (bo->getOpcode()) {
1514#define HANDLE_BINOP(OP) \
1516 return emit##OP(emitBinOps(bo, promotionType));
1525 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1526 switch (uo->getOpcode()) {
1529 return VisitRealImag(uo, promotionType);
1531 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1533 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1538 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1540 if (!promotionType.
isNull())
1541 return emitPromotedValue(result, promotionType);
1542 return emitUnPromotedValue(result, e->
getType());
1547mlir::Value ScalarExprEmitter::emitCompoundAssign(
1548 const CompoundAssignOperator *e,
1549 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1551 bool ignore = std::exchange(ignoreResultAssign,
false);
1553 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1564 if (!lhs.isVolatile())
1568 return emitLoadOfLValue(lhs, e->
getExprLoc());
1571mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1573 mlir::OpBuilder &builder = cgf.builder;
1575 auto scope = cir::ScopeOp::create(
1578 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1579 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1580 builder.getInsertionBlock()};
1581 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1582 if (scopeYieldVal) {
1586 cir::YieldOp::create(builder, loc, scopeYieldVal);
1587 yieldTy = scopeYieldVal.getType();
1591 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1601#define COMPOUND_OP(Op) \
1602 case BO_##Op##Assign: \
1603 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1640 llvm_unreachable(
"Not valid compound assignment operators");
1642 llvm_unreachable(
"Unhandled compound assignment operator");
1647 bool ignoreResultAssign) {
1649 "Invalid scalar expression to emit");
1652 .Visit(
const_cast<Expr *
>(e));
1657 if (!promotionType.
isNull())
1672static std::optional<QualType>
1676 return std::nullopt;
1681 return std::nullopt;
1694 const BinOpInfo &op) {
1696 "Expected a unary or binary operator");
1700 if (!op.mayHaveIntegerOverflow())
1704 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1705 return !uo->canOverflow();
1710 std::optional<QualType> optionalLHSTy =
1715 std::optional<QualType> optionalRHSTy =
1725 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1732 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1733 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1738 const BinOpInfo &op,
1739 bool isSubtraction) {
1744 mlir::Value pointer = op.lhs;
1745 Expr *pointerOperand =
expr->getLHS();
1746 mlir::Value
index = op.rhs;
1747 Expr *indexOperand =
expr->getRHS();
1753 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1754 std::swap(pointer,
index);
1755 std::swap(pointerOperand, indexOperand);
1757 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1758 "Need a pointer operand");
1759 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1794 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1805 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1810 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1812 pointer.getType(), pointer,
index);
1815mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1816 const mlir::Location loc = cgf.
getLoc(ops.loc);
1818 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1819 case LangOptions::SOB_Defined:
1820 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1821 return builder.createMul(loc, ops.lhs, ops.rhs);
1823 case LangOptions::SOB_Undefined:
1824 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1825 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1827 case LangOptions::SOB_Trapping:
1829 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1839 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1841 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1843 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1845 return builder.createFMul(loc, ops.lhs, ops.rhs);
1848 if (ops.isFixedPointOp()) {
1854 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1855 cgf.
convertType(ops.fullType), cir::BinOpKind::Mul,
1858mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1859 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1860 cgf.
convertType(ops.fullType), cir::BinOpKind::Div,
1863mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1864 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1865 cgf.
convertType(ops.fullType), cir::BinOpKind::Rem,
1869mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1870 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1871 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1874 const mlir::Location loc = cgf.
getLoc(ops.loc);
1876 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1877 case LangOptions::SOB_Defined:
1878 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1879 return builder.createAdd(loc, ops.lhs, ops.rhs);
1881 case LangOptions::SOB_Undefined:
1882 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1883 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1885 case LangOptions::SOB_Trapping:
1887 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1898 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1900 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1902 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1904 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1907 if (ops.isFixedPointOp()) {
1913 return cir::BinOp::create(builder, loc, cgf.
convertType(ops.fullType),
1914 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1917mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1918 const mlir::Location loc = cgf.
getLoc(ops.loc);
1920 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1922 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1923 case LangOptions::SOB_Defined: {
1924 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1925 return builder.createSub(loc, ops.lhs, ops.rhs);
1928 case LangOptions::SOB_Undefined:
1929 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1930 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1932 case LangOptions::SOB_Trapping:
1934 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1946 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1948 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1950 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1952 return builder.createFSub(loc, ops.lhs, ops.rhs);
1955 if (ops.isFixedPointOp()) {
1961 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1963 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1968 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1980 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1984mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1986 if (ops.isFixedPointOp()) {
1996 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2000 bool sanitizeUnsignedBase =
2001 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2003 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2004 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2009 else if ((sanitizeBase || sanitizeExponent) &&
2010 mlir::isa<cir::IntType>(ops.lhs.getType()))
2013 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2016mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2018 if (ops.isFixedPointOp()) {
2031 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2032 mlir::isa<cir::IntType>(ops.lhs.getType()))
2037 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2040mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2041 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2042 cgf.
convertType(ops.fullType), cir::BinOpKind::And,
2045mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2046 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2047 cgf.
convertType(ops.fullType), cir::BinOpKind::Xor,
2050mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2051 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2052 cgf.
convertType(ops.fullType), cir::BinOpKind::Or,
2060mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2062 QualType destTy = ce->
getType();
2067 ignoreResultAssign =
false;
2070 case clang::CK_Dependent:
2071 llvm_unreachable(
"dependent cast kind in CIR gen!");
2072 case clang::CK_BuiltinFnToFnPtr:
2073 llvm_unreachable(
"builtin functions are handled elsewhere");
2075 case CK_CPointerToObjCPointerCast:
2076 case CK_BlockPointerToObjCPointerCast:
2077 case CK_AnyPointerToBlockPointerCast:
2079 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2084 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2086 "sanitizer support");
2090 "strict vtable pointers");
2116 case CK_AddressSpaceConversion: {
2117 Expr::EvalResult result;
2134 cir::TargetAddressSpaceAttr subExprAS;
2139 "non-target address space conversion");
2143 cgf, Visit(subExpr), subExprAS, convertType(destTy));
2146 case CK_AtomicToNonAtomic: {
2152 case CK_NonAtomicToAtomic:
2153 case CK_UserDefinedConversion:
2154 return Visit(
const_cast<Expr *
>(subExpr));
2156 auto v = Visit(
const_cast<Expr *
>(subExpr));
2162 if (t != v.getType())
2167 case CK_IntegralToPointer: {
2169 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2176 mlir::Value middleVal = builder.createCast(
2178 : cir::CastKind::integral,
2183 "IntegralToPointer: strict vtable pointers");
2187 return builder.createIntToPtr(middleVal, destCIRTy);
2190 case CK_BaseToDerived: {
2192 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2204 case CK_UncheckedDerivedToBase:
2205 case CK_DerivedToBase: {
2216 case CK_ArrayToPointerDecay:
2219 case CK_NullToPointer: {
2229 case CK_NullToMemberPointer: {
2235 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2238 "CK_NullToMemberPointer: member function pointer");
2242 auto ty = mlir::cast<cir::DataMemberType>(cgf.
convertType(destTy));
2243 return builder.getNullDataMemberPtr(ty, cgf.
getLoc(subExpr->
getExprLoc()));
2246 case CK_LValueToRValue:
2248 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2249 return Visit(
const_cast<Expr *
>(subExpr));
2251 case CK_IntegralCast: {
2252 ScalarConversionOpts opts;
2253 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2254 if (!ice->isPartOfExplicitCast())
2255 opts = ScalarConversionOpts(cgf.
sanOpts);
2257 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2261 case CK_FloatingComplexToReal:
2262 case CK_IntegralComplexToReal:
2263 case CK_FloatingComplexToBoolean:
2264 case CK_IntegralComplexToBoolean: {
2270 case CK_FloatingRealToComplex:
2271 case CK_FloatingComplexCast:
2272 case CK_IntegralRealToComplex:
2273 case CK_IntegralComplexCast:
2274 case CK_IntegralComplexToFloatingComplex:
2275 case CK_FloatingComplexToIntegralComplex:
2276 llvm_unreachable(
"scalar cast to non-scalar value");
2278 case CK_PointerToIntegral: {
2279 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2282 "strict vtable pointers");
2283 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
2289 case CK_IntegralToFloating:
2290 case CK_FloatingToIntegral:
2291 case CK_FloatingCast:
2292 case CK_FixedPointToFloating:
2293 case CK_FloatingToFixedPoint: {
2294 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
2296 "fixed point casts");
2300 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2304 case CK_IntegralToBoolean:
2305 return emitIntToBoolConversion(Visit(subExpr),
2308 case CK_PointerToBoolean:
2309 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2310 case CK_FloatingToBoolean:
2311 return emitFloatToBoolConversion(Visit(subExpr),
2313 case CK_MemberPointerToBoolean: {
2314 mlir::Value memPtr = Visit(subExpr);
2316 cir::CastKind::member_ptr_to_bool, memPtr,
2320 case CK_VectorSplat: {
2322 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2323 return cir::VecSplatOp::create(builder,
2327 case CK_FunctionToPointerDecay:
2337mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2339 return emitLoadOfLValue(e);
2346mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2351 Expr::EvalResult result;
2353 llvm::APSInt value = result.
Val.
getInt();
2357 return emitLoadOfLValue(e);
2360mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2361 const unsigned numInitElements = e->
getNumInits();
2363 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2364 assert((ignore ==
false ||
2366 "init list ignored");
2374 const auto vectorType =
2377 SmallVector<mlir::Value, 16> elements;
2378 for (Expr *init : e->
inits()) {
2379 elements.push_back(Visit(init));
2383 if (numInitElements < vectorType.getSize()) {
2386 std::fill_n(std::back_inserter(elements),
2387 vectorType.getSize() - numInitElements, zeroValue);
2390 return cir::VecCreateOp::create(cgf.
getBuilder(),
2396 if (numInitElements == 0)
2407 "Invalid scalar expression to emit");
2409 .emitScalarConversion(src, srcTy, dstTy, loc);
2417 "Invalid complex -> scalar conversion");
2422 ? cir::CastKind::float_complex_to_bool
2423 : cir::CastKind::int_complex_to_bool;
2428 ? cir::CastKind::float_complex_to_real
2429 : cir::CastKind::int_complex_to_real;
2435mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2442 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2444 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2445 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2453 boolVal = builder.createNot(boolVal);
2459mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2464 llvm::APSInt value = evalResult.
Val.
getInt();
2470 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2474mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2476 mlir::Value result = VisitRealImag(e, promotionTy);
2477 if (result && !promotionTy.
isNull())
2478 result = emitUnPromotedValue(result, e->
getType());
2482mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2484 mlir::Value result = VisitRealImag(e, promotionTy);
2485 if (result && !promotionTy.
isNull())
2486 result = emitUnPromotedValue(result, e->
getType());
2490mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2491 QualType promotionTy) {
2492 assert(e->
getOpcode() == clang::UO_Real ||
2494 "Invalid UnaryOp kind for ComplexType Real or Imag");
2511 ? builder.createComplexReal(loc, complex)
2512 : builder.createComplexImag(loc, complex);
2516 mlir::Value operand = promotionTy.
isNull()
2518 : cgf.emitPromotedScalarExpr(op, promotionTy);
2519 return builder.createComplexReal(loc, operand);
2524 mlir::Value operand;
2527 operand = cir::LoadOp::create(builder, loc, operand);
2528 }
else if (!promotionTy.
isNull()) {
2533 return builder.createComplexImag(loc, operand);
2538mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2539 const UnaryExprOrTypeTraitExpr *e) {
2543 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
2544 if (
const VariableArrayType *vat =
2549 bool evaluateExtent =
true;
2550 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2552 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2555 if (evaluateExtent) {
2566 if (kind == UETT_CountOf)
2571 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2572 mlir::Value numElts = vlaSize.
numElts;
2576 if (!eltSize.
isOne()) {
2578 mlir::Value eltSizeValue =
2579 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
2581 return builder.createMul(loc, eltSizeValue, numElts,
2588 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2590 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2592 return builder.getConstant(
2594 llvm::APSInt(llvm::APInt(64, 1),
true)));
2595 }
else if (e->
getKind() == UETT_VectorElements) {
2597 if (vecTy.getIsScalable()) {
2600 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2601 return builder.getConstant(
2606 return builder.getConstant(
2607 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2610 return builder.getConstant(
2632mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2633 const AbstractConditionalOperator *e) {
2636 ignoreResultAssign =
false;
2639 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2641 Expr *condExpr = e->
getCond();
2649 Expr *live = lhsExpr, *dead = rhsExpr;
2651 std::swap(live, dead);
2657 mlir::Value result = Visit(live);
2664 loc, cir::PoisonAttr::get(builder.getContext(),
2672 QualType condType = condExpr->
getType();
2685 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2689 mlir::Value condValue = Visit(condExpr);
2690 mlir::Value lhsValue = Visit(lhsExpr);
2691 mlir::Value rhsValue = Visit(rhsExpr);
2692 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2701 bool lhsIsVoid =
false;
2705 mlir::Value lhs = Visit(lhsExpr);
2711 mlir::Value rhs = Visit(rhsExpr);
2713 assert(!rhs &&
"lhs and rhs types must match");
2721 CIRGenFunction::ConditionalEvaluation eval(cgf);
2722 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2723 mlir::Type yieldTy{};
2725 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2726 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2730 eval.beginEvaluation();
2731 mlir::Value branch = Visit(
expr);
2732 eval.endEvaluation();
2735 yieldTy = branch.getType();
2736 cir::YieldOp::create(
b, loc, branch);
2740 insertPoints.push_back(
b.saveInsertionPoint());
2744 mlir::Value result = cir::TernaryOp::create(
2745 builder, loc, condV,
2747 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2748 emitBranch(
b, loc, lhsExpr);
2751 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2752 emitBranch(
b, loc, rhsExpr);
2756 if (!insertPoints.empty()) {
2762 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2763 mlir::OpBuilder::InsertionGuard guard(builder);
2764 builder.restoreInsertionPoint(toInsert);
2767 if (mlir::isa<cir::VoidType>(yieldTy)) {
2768 cir::YieldOp::create(builder, loc);
2771 cir::YieldOp::create(builder, loc, op0);
2781 cir::UnaryOpKind kind,
2784 .emitScalarPrePostIncDec(e, lv, kind, isPre);
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
__device__ __2f16 float __ockl_bool s
cir::ConstantOp getBool(bool state, mlir::Location loc)
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 createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::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.
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.
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
LabelDecl * getLabel() const
uint64_t getValue() const
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
BinaryOperatorKind Opcode
mlir::Value getPointer() const
mlir::Value createNeg(mlir::Value value)
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
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::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::MLIRContext & getMLIRContext()
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
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)
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
const TargetCIRGenInfo & getTargetCIRGenInfo()
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.
virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr, mlir::Type destTy, bool isNonNull=false) const
Perform address space cast of an expression of pointer type.
Expr * getExpr()
Get the initialization expression that will be used.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
static const char * getCastKindName(CastKind CK)
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.
LangAS getAddressSpace() const
Return the address space of this 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.
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
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,...
bool isConstantMatrixType() const
bool isPointerType() 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 isFunctionType() const
bool isMemberFunctionPointerType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
SourceLocation getExprLoc() const
Expr * getSubExpr() const
static bool isIncrementOp(Opcode Op)
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
cir::TargetAddressSpaceAttr toCIRTargetAddressSpace(mlir::MLIRContext &context, clang::LangAS langAS)
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.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool isTargetAddressSpace(LangAS AS)
LangAS
Defines the address space values used by the address space qualifier of QualType.
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 cgFPOptionsRAII()
static bool fpConstraints()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool tryEmitAsConstant()
static bool llvmLoweringPtrDiffConsidersPointee()
static bool scalableVectors()
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.