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) {
144 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
148 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
152 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
154 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
159 mlir::Value emitLoadOfLValue(
const Expr *e) {
160 LValue lv = cgf.emitLValue(e);
162 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
165 mlir::Value VisitCoawaitExpr(CoawaitExpr *
s) {
166 return cgf.emitCoawaitExpr(*s).getValue();
168 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
169 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: coyield");
172 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
173 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
177 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
178 return cgf.emitLoadOfLValue(lv, loc).getValue();
182 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
183 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
184 return cgf.emitScalarConstant(constant, e);
186 return emitLoadOfLValue(e);
189 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
191 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
193 cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
196 cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
197 if (!resolvedLabel) {
198 cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
201 cgf.cgm.mapResolvedBlockAddress(blockAddressOp,
nullptr);
203 cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
205 cgf.instantiateIndirectGotoBlock();
206 return blockAddressOp;
209 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
211 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
215 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
217 "ScalarExprEmitter: fixed point literal");
221 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
223 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
224 "expect floating-point type");
225 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
229 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
230 mlir::Type ty = cgf.convertType(e->
getType());
231 auto init = cir::IntAttr::get(ty, e->
getValue());
232 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()), init);
235 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
239 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
246 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
250 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
252 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
253 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: size of pack");
256 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
257 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: pseudo object");
260 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
262 "ScalarExprEmitter: sycl unique stable name");
265 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
266 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: embed");
269 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
271 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
275 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
278 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
279 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
282 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
283 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
286 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
287 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
290 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
291 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
294 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
295 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
298 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
300 "ScalarExprEmitter: objc availability check");
304 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
306 "ScalarExprEmitter: matrix subscript");
310 mlir::Value VisitCastExpr(
CastExpr *e);
311 mlir::Value VisitCallExpr(
const CallExpr *e);
313 mlir::Value VisitStmtExpr(StmtExpr *e) {
314 CIRGenFunction::StmtExprEvaluation eval(cgf);
322 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
324 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
328 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
329 ignoreResultAssign =
false;
335 const mlir::Value vecValue = Visit(e->
getBase());
336 const mlir::Value indexValue = Visit(e->
getIdx());
337 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
340 return emitLoadOfLValue(e);
343 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
346 mlir::Value inputVec = Visit(e->
getExpr(0));
347 mlir::Value indexVec = Visit(e->
getExpr(1));
348 return cir::VecShuffleDynamicOp::create(
349 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
352 mlir::Value vec1 = Visit(e->
getExpr(0));
353 mlir::Value vec2 = Visit(e->
getExpr(1));
358 SmallVector<mlir::Attribute, 8> indices;
361 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
367 return cir::VecShuffleOp::create(cgf.builder,
369 cgf.convertType(e->
getType()), vec1, vec2,
370 cgf.builder.getArrayAttr(indices));
373 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
376 return emitScalarConversion(Visit(e->
getSrcExpr()),
381 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
383 mlir::Value VisitMemberExpr(MemberExpr *e);
385 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
386 return emitLoadOfLValue(e);
389 mlir::Value VisitInitListExpr(InitListExpr *e);
391 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
393 "ScalarExprEmitter: array init index");
397 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
399 "ScalarExprEmitter: implicit value init");
403 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
404 return VisitCastExpr(e);
407 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
408 return cgf.cgm.emitNullConstant(e->
getType(),
413 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
416 return cgf.getBuilder().createPtrToBoolCast(v);
419 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
420 cir::BoolType boolTy = builder.getBoolTy();
421 return cir::CastOp::create(builder, loc, boolTy,
422 cir::CastKind::float_to_bool, src);
425 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
431 cir::BoolType boolTy = builder.getBoolTy();
432 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
438 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
439 mlir::Location loc) {
440 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
443 return emitFloatToBoolConversion(src, loc);
445 if (llvm::isa<MemberPointerType>(srcType)) {
446 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
447 return builder.getFalse(loc);
451 return emitIntToBoolConversion(src, loc);
453 assert(::mlir::isa<cir::PointerType>(src.getType()));
454 return emitPointerToBoolConversion(src, srcType);
459 struct ScalarConversionOpts {
460 bool treatBooleanAsSigned;
461 bool emitImplicitIntegerTruncationChecks;
462 bool emitImplicitIntegerSignChangeChecks;
464 ScalarConversionOpts()
465 : treatBooleanAsSigned(
false),
466 emitImplicitIntegerTruncationChecks(
false),
467 emitImplicitIntegerSignChangeChecks(
false) {}
469 ScalarConversionOpts(clang::SanitizerSet sanOpts)
470 : treatBooleanAsSigned(
false),
471 emitImplicitIntegerTruncationChecks(
472 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
473 emitImplicitIntegerSignChangeChecks(
474 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
481 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
482 QualType dstType, mlir::Type srcTy,
483 mlir::Type dstTy, ScalarConversionOpts opts) {
485 "Internal error: matrix types not handled by this function.");
486 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
487 mlir::isa<mlir::IntegerType>(dstTy)) &&
488 "Obsolete code. Don't use mlir::IntegerType with CIR.");
490 mlir::Type fullDstTy = dstTy;
491 if (mlir::isa<cir::VectorType>(srcTy) &&
492 mlir::isa<cir::VectorType>(dstTy)) {
494 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
495 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
498 std::optional<cir::CastKind> castKind;
500 if (mlir::isa<cir::BoolType>(srcTy)) {
501 if (opts.treatBooleanAsSigned)
502 cgf.getCIRGenModule().errorNYI(
"signed bool");
503 if (cgf.getBuilder().isInt(dstTy))
504 castKind = cir::CastKind::bool_to_int;
505 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
506 castKind = cir::CastKind::bool_to_float;
508 llvm_unreachable(
"Internal error: Cast to unexpected type");
509 }
else if (cgf.getBuilder().isInt(srcTy)) {
510 if (cgf.getBuilder().isInt(dstTy))
511 castKind = cir::CastKind::integral;
512 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
513 castKind = cir::CastKind::int_to_float;
515 llvm_unreachable(
"Internal error: Cast to unexpected type");
516 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
517 if (cgf.getBuilder().isInt(dstTy)) {
521 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
522 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
524 castKind = cir::CastKind::float_to_int;
525 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
527 return builder.createFloatingCast(src, fullDstTy);
529 llvm_unreachable(
"Internal error: Cast to unexpected type");
532 llvm_unreachable(
"Internal error: Cast from unexpected type");
535 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
536 return cir::CastOp::create(builder, src.getLoc(), fullDstTy, *castKind,
541 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
545 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
550 "variably modified types in varargs");
553 return cgf.emitVAArg(ve);
556 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
560 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
562 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
565 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
567 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
569 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
571 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
573 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
575 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
577 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
579 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
581 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
582 cir::UnaryOpKind kind,
bool isPre) {
583 if (cgf.getLangOpts().OpenMP)
591 if (
type->getAs<AtomicType>()) {
595 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
598 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
611 if (kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
612 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
613 }
else if (
type->isIntegerType()) {
614 QualType promotedType;
615 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
616 if (cgf.getContext().isPromotableIntegerType(
type)) {
617 promotedType = cgf.getContext().getPromotedIntegerType(
type);
618 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
619 canPerformLossyDemotionCheck =
true;
620 canPerformLossyDemotionCheck &=
621 cgf.getContext().getCanonicalType(
type) !=
622 cgf.getContext().getCanonicalType(promotedType);
623 canPerformLossyDemotionCheck &=
630 (!canPerformLossyDemotionCheck ||
631 type->isSignedIntegerOrEnumerationType() ||
633 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
634 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
635 "The following check expects that if we do promotion to different "
636 "underlying canonical type, at least one of the types (either "
637 "base or promoted) will be signed, or the bitwidths will match.");
642 value = emitIncDecConsiderOverflowBehavior(e, value, kind);
644 cir::UnaryOpKind
kind =
645 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
647 value = emitUnaryOp(e, kind, input,
false);
649 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
650 QualType
type = ptr->getPointeeType();
651 if (cgf.getContext().getAsVariableArrayType(
type)) {
653 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
655 }
else if (
type->isFunctionType()) {
658 "Pointer arithmetic on function pointer");
663 CIRGenBuilderTy &builder = cgf.getBuilder();
664 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
665 mlir::Value amt = builder.getSInt32(amount, loc);
667 value = builder.createPtrStride(loc, value, amt);
669 }
else if (
type->isVectorType()) {
672 }
else if (
type->isRealFloatingType()) {
675 if (
type->isHalfType() &&
676 !cgf.getContext().getLangOpts().NativeHalfType) {
681 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
684 assert(kind == cir::UnaryOpKind::Inc ||
685 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
686 value = emitUnaryOp(e, kind, value);
688 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
691 }
else if (
type->isFixedPointType()) {
692 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
695 assert(
type->castAs<ObjCObjectPointerType>());
696 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
700 CIRGenFunction::SourceLocRAIIObject sourceloc{
705 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
707 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
711 return isPre ? value : input;
714 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
716 cir::UnaryOpKind kind) {
717 assert(kind == cir::UnaryOpKind::Inc ||
718 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
719 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
720 case LangOptions::SOB_Defined:
721 return emitUnaryOp(e, kind, inVal,
false);
722 case LangOptions::SOB_Undefined:
724 return emitUnaryOp(e, kind, inVal,
true);
725 case LangOptions::SOB_Trapping:
727 return emitUnaryOp(e, kind, inVal,
true);
728 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
731 llvm_unreachable(
"Unexpected signed overflow behavior kind");
734 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
735 if (llvm::isa<MemberPointerType>(e->
getType()))
736 return cgf.cgm.emitMemberPointerConstant(e);
738 return cgf.emitLValue(e->
getSubExpr()).getPointer();
741 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
744 return emitLoadOfLValue(e);
747 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
750 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
751 if (result && !promotionType.
isNull())
752 return emitUnPromotedValue(result, e->
getType());
756 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
759 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
760 if (result && !promotionType.
isNull())
761 return emitUnPromotedValue(result, e->
getType());
765 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
766 cir::UnaryOpKind kind,
767 QualType promotionType) {
768 ignoreResultAssign =
false;
770 if (!promotionType.
isNull())
771 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
780 return emitUnaryOp(e, kind, operand, nsw);
783 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind kind,
784 mlir::Value input,
bool nsw =
false) {
785 return cir::UnaryOp::create(builder,
787 input.getType(), kind, input, nsw);
790 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
791 ignoreResultAssign =
false;
793 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
796 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
798 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
799 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
800 mlir::Value VisitRealImag(
const UnaryOperator *e,
801 QualType promotionType = QualType());
803 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
808 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
810 "ScalarExprEmitter: materialize temporary");
813 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
814 ASTContext &ctx = cgf.getContext();
817 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
819 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
820 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
823 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
824 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
827 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
828 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
832 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
834 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
835 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
836 return cgf.emitCXXNewExpr(e);
838 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
839 cgf.emitCXXDeleteExpr(e);
842 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
843 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
847 "ScalarExprEmitter: TypeTraitExpr stored as int");
851 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
857 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
859 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
862 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
865 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
867 "ScalarExprEmitter: cxx pseudo destructor");
870 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
871 cgf.emitCXXThrowExpr(e);
875 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
884 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
886 ScalarConversionOpts opts = ScalarConversionOpts()) {
896 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
902 if (srcType == dstType) {
903 if (opts.emitImplicitIntegerSignChangeChecks)
904 cgf.getCIRGenModule().errorNYI(loc,
905 "implicit integer sign change checks");
912 mlir::Type mlirSrcType = src.getType();
917 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
919 mlir::Type mlirDstType = cgf.convertType(dstType);
922 !cgf.getContext().getLangOpts().NativeHalfType) {
924 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
925 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
926 cgf.getCIRGenModule().errorNYI(loc,
927 "cast via llvm.convert.from.fp16");
932 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
933 cgf.getCIRGenModule().errorNYI(loc,
934 "cast via llvm.convert.from.fp16");
937 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
939 srcType = cgf.getContext().FloatTy;
940 mlirSrcType = cgf.floatTy;
946 if (mlirSrcType == mlirDstType) {
947 if (opts.emitImplicitIntegerSignChangeChecks)
948 cgf.getCIRGenModule().errorNYI(loc,
949 "implicit integer sign change checks");
956 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
957 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
958 return builder.getNullPtr(dstPT, src.getLoc());
964 return builder.createPtrToInt(src, mlirDstType);
971 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
973 "Splatted expr doesn't match with vector element type?");
975 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
980 cgf.getCIRGenModule().errorNYI(loc,
981 "matrix type to matrix type conversion");
985 "Internal error: conversion between matrix type and scalar type");
988 mlir::Value res =
nullptr;
989 mlir::Type resTy = mlirDstType;
991 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
993 if (mlirDstType != resTy) {
994 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
995 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
999 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1003 if (opts.emitImplicitIntegerTruncationChecks)
1004 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1006 if (opts.emitImplicitIntegerSignChangeChecks)
1007 cgf.getCIRGenModule().errorNYI(loc,
1008 "implicit integer sign change checks");
1013 BinOpInfo emitBinOps(
const BinaryOperator *e,
1014 QualType promotionType = QualType()) {
1015 ignoreResultAssign =
false;
1017 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1018 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1019 if (!promotionType.
isNull())
1020 result.fullType = promotionType;
1022 result.fullType = e->
getType();
1023 result.compType = result.fullType;
1024 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1025 result.compType = vecType->getElementType();
1035 mlir::Value emitMul(
const BinOpInfo &ops);
1036 mlir::Value emitDiv(
const BinOpInfo &ops);
1037 mlir::Value emitRem(
const BinOpInfo &ops);
1038 mlir::Value emitAdd(
const BinOpInfo &ops);
1039 mlir::Value emitSub(
const BinOpInfo &ops);
1040 mlir::Value emitShl(
const BinOpInfo &ops);
1041 mlir::Value emitShr(
const BinOpInfo &ops);
1042 mlir::Value emitAnd(
const BinOpInfo &ops);
1043 mlir::Value emitXor(
const BinOpInfo &ops);
1044 mlir::Value emitOr(
const BinOpInfo &ops);
1046 LValue emitCompoundAssignLValue(
1047 const CompoundAssignOperator *e,
1048 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1049 mlir::Value &result);
1051 emitCompoundAssign(
const CompoundAssignOperator *e,
1052 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1056 QualType getPromotionType(QualType ty) {
1057 const clang::ASTContext &ctx = cgf.getContext();
1058 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1059 QualType elementTy = complexTy->getElementType();
1065 if (
auto *vt = ty->
getAs<VectorType>()) {
1066 unsigned numElements = vt->getNumElements();
1069 return cgf.getContext().FloatTy;
1076#define HANDLEBINOP(OP) \
1077 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1078 QualType promotionTy = getPromotionType(e->getType()); \
1079 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1080 if (result && !promotionTy.isNull()) \
1081 result = emitUnPromotedValue(result, e->getType()); \
1084 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1085 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1101 ignoreResultAssign =
false;
1107 auto clangCmpToCIRCmp =
1111 return cir::CmpOpKind::lt;
1113 return cir::CmpOpKind::gt;
1115 return cir::CmpOpKind::le;
1117 return cir::CmpOpKind::ge;
1119 return cir::CmpOpKind::eq;
1121 return cir::CmpOpKind::ne;
1123 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1127 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1135 BinOpInfo boInfo = emitBinOps(e);
1136 mlir::Value lhs = boInfo.lhs;
1137 mlir::Value rhs = boInfo.rhs;
1147 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1149 boInfo.lhs, boInfo.rhs);
1151 }
else if (boInfo.isFixedPointOp()) {
1154 result = builder.
getBool(
false, loc);
1158 mlir::isa<cir::PointerType>(lhs.getType()) &&
1159 mlir::isa<cir::PointerType>(rhs.getType())) {
1160 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1163 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1170 BinOpInfo boInfo = emitBinOps(e);
1171 result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);
1179#define VISITCOMP(CODE) \
1180 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1190 const bool ignore = std::exchange(ignoreResultAssign,
false);
1205 rhs = Visit(e->
getRHS());
1215 if (lhs.isBitField()) {
1235 if (!lhs.isVolatile())
1239 return emitLoadOfLValue(lhs, e->
getExprLoc());
1242 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1243 cgf.emitIgnoredExpr(e->
getLHS());
1245 return Visit(e->
getRHS());
1248 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1250 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1251 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1252 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1253 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1254 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1256 mlir::Value lhs = Visit(e->
getLHS());
1257 mlir::Value rhs = Visit(e->
getRHS());
1259 auto cmpOpKind = cir::CmpOpKind::ne;
1260 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1261 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1262 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1263 return builder.createIntCast(vecOr, vecTy);
1267 mlir::Type resTy = cgf.convertType(e->
getType());
1268 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1270 CIRGenFunction::ConditionalEvaluation eval(cgf);
1272 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1273 auto resOp = cir::TernaryOp::create(
1274 builder, loc, lhsCondV,
1275 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1276 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1277 b.getInsertionBlock()};
1278 cgf.curLexScope->setAsTernary();
1279 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1281 cir::YieldOp::create(
b, loc, res);
1284 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1285 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1286 b.getInsertionBlock()};
1288 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1289 cir::YieldOp::create(
b, loc, res.getRes());
1291 return maybePromoteBoolResult(resOp.getResult(), resTy);
1294 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1296 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1297 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1298 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1299 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1300 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1302 mlir::Value lhs = Visit(e->
getLHS());
1303 mlir::Value rhs = Visit(e->
getRHS());
1305 auto cmpOpKind = cir::CmpOpKind::ne;
1306 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1307 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1308 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1309 return builder.createIntCast(vecOr, vecTy);
1313 mlir::Type resTy = cgf.convertType(e->
getType());
1314 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1316 CIRGenFunction::ConditionalEvaluation eval(cgf);
1318 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1319 auto resOp = cir::TernaryOp::create(
1320 builder, loc, lhsCondV,
1321 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1322 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1323 b.getInsertionBlock()};
1325 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1326 cir::YieldOp::create(
b, loc, res.getRes());
1329 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1330 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1331 b.getInsertionBlock()};
1333 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1335 cir::YieldOp::create(
b, loc, res);
1338 return maybePromoteBoolResult(resOp.getResult(), resTy);
1341 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1342 return emitLoadOfLValue(e);
1345 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1346 return emitLoadOfLValue(e);
1350 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1351 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1355 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1359 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1361 "ScalarExprEmitter: objc string literal");
1364 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1365 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1368 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1370 "ScalarExprEmitter: objc array literal");
1373 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1375 "ScalarExprEmitter: objc dictionary literal");
1379 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1380 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1384 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1385 return cgf.emitAtomicExpr(e).getValue();
1389LValue ScalarExprEmitter::emitCompoundAssignLValue(
1391 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1392 mlir::Value &result) {
1403 if (promotionTypeCR.
isNull())
1407 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1409 if (!promotionTypeRHS.
isNull())
1412 opInfo.rhs = Visit(e->
getRHS());
1414 opInfo.fullType = promotionTypeCR;
1415 opInfo.compType = opInfo.fullType;
1416 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1417 opInfo.compType = vecType->getElementType();
1426 if (lhsTy->
getAs<AtomicType>()) {
1427 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1431 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1433 CIRGenFunction::SourceLocRAIIObject sourceloc{
1436 if (!promotionTypeLHS.
isNull())
1437 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1439 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1443 result = (this->*func)(opInfo);
1447 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1448 ScalarConversionOpts(cgf.
sanOpts));
1454 if (lhsLV.isBitField())
1465mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1469 cir::CastKind castOpKind;
1471 case CK_FloatingComplexToReal:
1472 castOpKind = cir::CastKind::float_complex_to_real;
1474 case CK_IntegralComplexToReal:
1475 castOpKind = cir::CastKind::int_complex_to_real;
1477 case CK_FloatingComplexToBoolean:
1478 castOpKind = cir::CastKind::float_complex_to_bool;
1480 case CK_IntegralComplexToBoolean:
1481 castOpKind = cir::CastKind::int_complex_to_bool;
1484 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1490mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1491 QualType promotionType) {
1493 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1494 switch (bo->getOpcode()) {
1495#define HANDLE_BINOP(OP) \
1497 return emit##OP(emitBinOps(bo, promotionType));
1506 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1507 switch (uo->getOpcode()) {
1510 return VisitRealImag(uo, promotionType);
1512 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1514 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1519 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1521 if (!promotionType.
isNull())
1522 return emitPromotedValue(result, promotionType);
1523 return emitUnPromotedValue(result, e->
getType());
1528mlir::Value ScalarExprEmitter::emitCompoundAssign(
1529 const CompoundAssignOperator *e,
1530 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1532 bool ignore = std::exchange(ignoreResultAssign,
false);
1534 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1545 if (!lhs.isVolatile())
1549 return emitLoadOfLValue(lhs, e->
getExprLoc());
1552mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1554 mlir::OpBuilder &builder = cgf.builder;
1556 auto scope = cir::ScopeOp::create(
1559 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1560 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1561 builder.getInsertionBlock()};
1562 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1563 if (scopeYieldVal) {
1567 cir::YieldOp::create(builder, loc, scopeYieldVal);
1568 yieldTy = scopeYieldVal.getType();
1572 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1582#define COMPOUND_OP(Op) \
1583 case BO_##Op##Assign: \
1584 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1621 llvm_unreachable(
"Not valid compound assignment operators");
1623 llvm_unreachable(
"Unhandled compound assignment operator");
1628 bool ignoreResultAssign) {
1630 "Invalid scalar expression to emit");
1633 .Visit(
const_cast<Expr *
>(e));
1638 if (!promotionType.
isNull())
1653static std::optional<QualType>
1657 return std::nullopt;
1662 return std::nullopt;
1675 const BinOpInfo &op) {
1677 "Expected a unary or binary operator");
1681 if (!op.mayHaveIntegerOverflow())
1685 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1686 return !uo->canOverflow();
1691 std::optional<QualType> optionalLHSTy =
1696 std::optional<QualType> optionalRHSTy =
1706 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1713 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1714 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1719 const BinOpInfo &op,
1720 bool isSubtraction) {
1725 mlir::Value pointer = op.lhs;
1726 Expr *pointerOperand =
expr->getLHS();
1727 mlir::Value
index = op.rhs;
1728 Expr *indexOperand =
expr->getRHS();
1734 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1735 std::swap(pointer,
index);
1736 std::swap(pointerOperand, indexOperand);
1738 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1739 "Need a pointer operand");
1740 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1775 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1786 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1791 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1793 pointer.getType(), pointer,
index);
1796mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1797 const mlir::Location loc = cgf.
getLoc(ops.loc);
1799 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1800 case LangOptions::SOB_Defined:
1801 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1802 return builder.createMul(loc, ops.lhs, ops.rhs);
1804 case LangOptions::SOB_Undefined:
1805 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1806 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1808 case LangOptions::SOB_Trapping:
1810 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1820 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1822 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1824 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1826 return builder.createFMul(loc, ops.lhs, ops.rhs);
1829 if (ops.isFixedPointOp()) {
1835 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1836 cgf.
convertType(ops.fullType), cir::BinOpKind::Mul,
1839mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1840 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1841 cgf.
convertType(ops.fullType), cir::BinOpKind::Div,
1844mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1845 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1846 cgf.
convertType(ops.fullType), cir::BinOpKind::Rem,
1850mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1851 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1852 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1855 const mlir::Location loc = cgf.
getLoc(ops.loc);
1857 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1858 case LangOptions::SOB_Defined:
1859 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1860 return builder.createAdd(loc, ops.lhs, ops.rhs);
1862 case LangOptions::SOB_Undefined:
1863 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1864 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1866 case LangOptions::SOB_Trapping:
1868 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1879 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1881 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1883 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1885 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1888 if (ops.isFixedPointOp()) {
1894 return cir::BinOp::create(builder, loc, cgf.
convertType(ops.fullType),
1895 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1898mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1899 const mlir::Location loc = cgf.
getLoc(ops.loc);
1901 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1903 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1904 case LangOptions::SOB_Defined: {
1905 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1906 return builder.createSub(loc, ops.lhs, ops.rhs);
1909 case LangOptions::SOB_Undefined:
1910 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1911 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1913 case LangOptions::SOB_Trapping:
1915 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1927 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1929 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1931 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1933 return builder.createFSub(loc, ops.lhs, ops.rhs);
1936 if (ops.isFixedPointOp()) {
1942 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1944 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1949 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1961 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1965mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1967 if (ops.isFixedPointOp()) {
1977 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
1981 bool sanitizeUnsignedBase =
1982 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
1984 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1985 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
1990 else if ((sanitizeBase || sanitizeExponent) &&
1991 mlir::isa<cir::IntType>(ops.lhs.getType()))
1994 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
1997mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
1999 if (ops.isFixedPointOp()) {
2012 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2013 mlir::isa<cir::IntType>(ops.lhs.getType()))
2018 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2021mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2022 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2023 cgf.
convertType(ops.fullType), cir::BinOpKind::And,
2026mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2027 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2028 cgf.
convertType(ops.fullType), cir::BinOpKind::Xor,
2031mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2032 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2033 cgf.
convertType(ops.fullType), cir::BinOpKind::Or,
2041mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2043 QualType destTy = ce->
getType();
2048 ignoreResultAssign =
false;
2051 case clang::CK_Dependent:
2052 llvm_unreachable(
"dependent cast kind in CIR gen!");
2053 case clang::CK_BuiltinFnToFnPtr:
2054 llvm_unreachable(
"builtin functions are handled elsewhere");
2056 case CK_CPointerToObjCPointerCast:
2057 case CK_BlockPointerToObjCPointerCast:
2058 case CK_AnyPointerToBlockPointerCast:
2060 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2065 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2067 "sanitizer support");
2071 "strict vtable pointers");
2097 case CK_AddressSpaceConversion: {
2098 Expr::EvalResult result;
2115 cir::TargetAddressSpaceAttr subExprAS;
2120 "non-target address space conversion");
2124 cgf, Visit(subExpr), subExprAS, convertType(destTy));
2127 case CK_AtomicToNonAtomic: {
2133 case CK_NonAtomicToAtomic:
2134 case CK_UserDefinedConversion:
2135 return Visit(
const_cast<Expr *
>(subExpr));
2137 auto v = Visit(
const_cast<Expr *
>(subExpr));
2143 if (t != v.getType())
2148 case CK_IntegralToPointer: {
2150 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2157 mlir::Value middleVal = builder.createCast(
2159 : cir::CastKind::integral,
2164 "IntegralToPointer: strict vtable pointers");
2168 return builder.createIntToPtr(middleVal, destCIRTy);
2171 case CK_BaseToDerived: {
2173 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2185 case CK_UncheckedDerivedToBase:
2186 case CK_DerivedToBase: {
2197 case CK_ArrayToPointerDecay:
2200 case CK_NullToPointer: {
2210 case CK_LValueToRValue:
2212 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2213 return Visit(
const_cast<Expr *
>(subExpr));
2215 case CK_IntegralCast: {
2216 ScalarConversionOpts opts;
2217 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2218 if (!ice->isPartOfExplicitCast())
2219 opts = ScalarConversionOpts(cgf.
sanOpts);
2221 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2225 case CK_FloatingComplexToReal:
2226 case CK_IntegralComplexToReal:
2227 case CK_FloatingComplexToBoolean:
2228 case CK_IntegralComplexToBoolean: {
2234 case CK_FloatingRealToComplex:
2235 case CK_FloatingComplexCast:
2236 case CK_IntegralRealToComplex:
2237 case CK_IntegralComplexCast:
2238 case CK_IntegralComplexToFloatingComplex:
2239 case CK_FloatingComplexToIntegralComplex:
2240 llvm_unreachable(
"scalar cast to non-scalar value");
2242 case CK_PointerToIntegral: {
2243 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2246 "strict vtable pointers");
2247 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
2253 case CK_IntegralToFloating:
2254 case CK_FloatingToIntegral:
2255 case CK_FloatingCast:
2256 case CK_FixedPointToFloating:
2257 case CK_FloatingToFixedPoint: {
2258 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
2260 "fixed point casts");
2264 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2268 case CK_IntegralToBoolean:
2269 return emitIntToBoolConversion(Visit(subExpr),
2272 case CK_PointerToBoolean:
2273 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2274 case CK_FloatingToBoolean:
2275 return emitFloatToBoolConversion(Visit(subExpr),
2277 case CK_MemberPointerToBoolean: {
2278 mlir::Value memPtr = Visit(subExpr);
2280 cir::CastKind::member_ptr_to_bool, memPtr,
2284 case CK_VectorSplat: {
2286 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2287 return cir::VecSplatOp::create(builder,
2291 case CK_FunctionToPointerDecay:
2301mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2303 return emitLoadOfLValue(e);
2310mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2315 Expr::EvalResult result;
2317 llvm::APSInt value = result.
Val.
getInt();
2321 return emitLoadOfLValue(e);
2324mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2325 const unsigned numInitElements = e->
getNumInits();
2327 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2328 assert((ignore ==
false ||
2330 "init list ignored");
2338 const auto vectorType =
2341 SmallVector<mlir::Value, 16> elements;
2342 for (Expr *init : e->
inits()) {
2343 elements.push_back(Visit(init));
2347 if (numInitElements < vectorType.getSize()) {
2350 std::fill_n(std::back_inserter(elements),
2351 vectorType.getSize() - numInitElements, zeroValue);
2354 return cir::VecCreateOp::create(cgf.
getBuilder(),
2360 if (numInitElements == 0)
2371 "Invalid scalar expression to emit");
2373 .emitScalarConversion(src, srcTy, dstTy, loc);
2381 "Invalid complex -> scalar conversion");
2386 ? cir::CastKind::float_complex_to_bool
2387 : cir::CastKind::int_complex_to_bool;
2392 ? cir::CastKind::float_complex_to_real
2393 : cir::CastKind::int_complex_to_real;
2399mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2406 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2408 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2409 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2417 boolVal = builder.createNot(boolVal);
2423mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2428 llvm::APSInt value = evalResult.
Val.
getInt();
2434 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2438mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2440 mlir::Value result = VisitRealImag(e, promotionTy);
2441 if (result && !promotionTy.
isNull())
2442 result = emitUnPromotedValue(result, e->
getType());
2446mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2448 mlir::Value result = VisitRealImag(e, promotionTy);
2449 if (result && !promotionTy.
isNull())
2450 result = emitUnPromotedValue(result, e->
getType());
2454mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2455 QualType promotionTy) {
2456 assert(e->
getOpcode() == clang::UO_Real ||
2458 "Invalid UnaryOp kind for ComplexType Real or Imag");
2475 ? builder.createComplexReal(loc, complex)
2476 : builder.createComplexImag(loc, complex);
2480 mlir::Value operand = promotionTy.
isNull()
2482 : cgf.emitPromotedScalarExpr(op, promotionTy);
2483 return builder.createComplexReal(loc, operand);
2488 mlir::Value operand;
2491 operand = cir::LoadOp::create(builder, loc, operand);
2492 }
else if (!promotionTy.
isNull()) {
2497 return builder.createComplexImag(loc, operand);
2502mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2503 const UnaryExprOrTypeTraitExpr *e) {
2507 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
2508 if (
const VariableArrayType *vat =
2513 bool evaluateExtent =
true;
2514 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2516 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2519 if (evaluateExtent) {
2530 if (kind == UETT_CountOf)
2535 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2536 mlir::Value numElts = vlaSize.
numElts;
2540 if (!eltSize.
isOne()) {
2542 mlir::Value eltSizeValue =
2543 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
2545 return builder.createMul(loc, eltSizeValue, numElts,
2552 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2554 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2556 return builder.getConstant(
2558 llvm::APSInt(llvm::APInt(64, 1),
true)));
2561 return builder.getConstant(
2583mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2584 const AbstractConditionalOperator *e) {
2587 ignoreResultAssign =
false;
2590 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2592 Expr *condExpr = e->
getCond();
2600 Expr *live = lhsExpr, *dead = rhsExpr;
2602 std::swap(live, dead);
2608 mlir::Value result = Visit(live);
2615 loc, cir::PoisonAttr::get(builder.getContext(),
2623 QualType condType = condExpr->
getType();
2636 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2640 mlir::Value condValue = Visit(condExpr);
2641 mlir::Value lhsValue = Visit(lhsExpr);
2642 mlir::Value rhsValue = Visit(rhsExpr);
2643 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2652 bool lhsIsVoid =
false;
2656 mlir::Value lhs = Visit(lhsExpr);
2662 mlir::Value rhs = Visit(rhsExpr);
2664 assert(!rhs &&
"lhs and rhs types must match");
2672 CIRGenFunction::ConditionalEvaluation eval(cgf);
2673 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2674 mlir::Type yieldTy{};
2676 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2677 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2681 eval.beginEvaluation();
2682 mlir::Value branch = Visit(
expr);
2683 eval.endEvaluation();
2686 yieldTy = branch.getType();
2687 cir::YieldOp::create(
b, loc, branch);
2691 insertPoints.push_back(
b.saveInsertionPoint());
2695 mlir::Value result = cir::TernaryOp::create(
2696 builder, loc, condV,
2698 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2699 emitBranch(
b, loc, lhsExpr);
2702 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2703 emitBranch(
b, loc, rhsExpr);
2707 if (!insertPoints.empty()) {
2713 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2714 mlir::OpBuilder::InsertionGuard guard(builder);
2715 builder.restoreInsertionPoint(toInsert);
2718 if (mlir::isa<cir::VoidType>(yieldTy)) {
2719 cir::YieldOp::create(builder, loc);
2722 cir::YieldOp::create(builder, loc, op0);
2732 cir::UnaryOpKind kind,
2735 .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.
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 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.