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();
185 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
186 return cgf.emitCoyieldExpr(*e).getValue();
189 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
190 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
194 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
195 return cgf.emitLoadOfLValue(lv, loc).getValue();
199 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
200 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
201 return cgf.emitScalarConstant(constant, e);
203 return emitLoadOfLValue(e);
206 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
208 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
210 cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
213 cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
214 if (!resolvedLabel) {
215 cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
218 cgf.cgm.mapResolvedBlockAddress(blockAddressOp,
nullptr);
220 cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
222 cgf.instantiateIndirectGotoBlock();
223 return blockAddressOp;
226 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
228 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
232 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
234 "ScalarExprEmitter: fixed point literal");
238 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
240 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
241 "expect floating-point type");
242 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
246 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
247 mlir::Type ty = cgf.convertType(e->
getType());
248 auto init = cir::IntAttr::get(ty, e->
getValue());
249 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()), init);
252 mlir::Value VisitCXXBoolLiteralExpr(
const CXXBoolLiteralExpr *e) {
256 mlir::Value VisitCXXScalarValueInitExpr(
const CXXScalarValueInitExpr *e) {
263 mlir::Value VisitGNUNullExpr(
const GNUNullExpr *e) {
267 mlir::Value VisitOffsetOfExpr(OffsetOfExpr *e);
269 mlir::Value VisitSizeOfPackExpr(SizeOfPackExpr *e) {
270 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: size of pack");
273 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
274 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: pseudo object");
277 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
279 "ScalarExprEmitter: sycl unique stable name");
282 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
284 auto it = e->
begin();
285 llvm::APInt value = (*it)->getValue();
286 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
289 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
291 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
295 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
298 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
299 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
302 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
303 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
306 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
307 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
310 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
311 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
314 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
315 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
318 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
320 "ScalarExprEmitter: objc availability check");
324 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
326 "ScalarExprEmitter: matrix subscript");
330 mlir::Value VisitCastExpr(
CastExpr *e);
331 mlir::Value VisitCallExpr(
const CallExpr *e);
333 mlir::Value VisitStmtExpr(StmtExpr *e) {
334 CIRGenFunction::StmtExprEvaluation eval(cgf);
342 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
344 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
348 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
349 ignoreResultAssign =
false;
355 const mlir::Value vecValue = Visit(e->
getBase());
356 const mlir::Value indexValue = Visit(e->
getIdx());
357 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
360 return emitLoadOfLValue(e);
363 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
366 mlir::Value inputVec = Visit(e->
getExpr(0));
367 mlir::Value indexVec = Visit(e->
getExpr(1));
368 return cir::VecShuffleDynamicOp::create(
369 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
372 mlir::Value vec1 = Visit(e->
getExpr(0));
373 mlir::Value vec2 = Visit(e->
getExpr(1));
378 SmallVector<mlir::Attribute, 8> indices;
381 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
387 return cir::VecShuffleOp::create(cgf.builder,
389 cgf.convertType(e->
getType()), vec1, vec2,
390 cgf.builder.getArrayAttr(indices));
393 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
396 return emitScalarConversion(Visit(e->
getSrcExpr()),
401 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
403 mlir::Value VisitMemberExpr(MemberExpr *e);
405 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
406 return emitLoadOfLValue(e);
409 mlir::Value VisitInitListExpr(InitListExpr *e);
411 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
413 "ScalarExprEmitter: array init index");
417 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
419 "ScalarExprEmitter: implicit value init");
423 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
424 return VisitCastExpr(e);
427 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
428 return cgf.cgm.emitNullConstant(e->
getType(),
433 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
436 return cgf.getBuilder().createPtrToBoolCast(v);
439 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
440 cir::BoolType boolTy = builder.getBoolTy();
441 return cir::CastOp::create(builder, loc, boolTy,
442 cir::CastKind::float_to_bool, src);
445 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
451 cir::BoolType boolTy = builder.getBoolTy();
452 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
458 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
459 mlir::Location loc) {
460 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
463 return emitFloatToBoolConversion(src, loc);
465 if (llvm::isa<MemberPointerType>(srcType)) {
466 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
467 return builder.getFalse(loc);
471 return emitIntToBoolConversion(src, loc);
473 assert(::mlir::isa<cir::PointerType>(src.getType()));
474 return emitPointerToBoolConversion(src, srcType);
479 struct ScalarConversionOpts {
480 bool treatBooleanAsSigned;
481 bool emitImplicitIntegerTruncationChecks;
482 bool emitImplicitIntegerSignChangeChecks;
484 ScalarConversionOpts()
485 : treatBooleanAsSigned(
false),
486 emitImplicitIntegerTruncationChecks(
false),
487 emitImplicitIntegerSignChangeChecks(
false) {}
489 ScalarConversionOpts(clang::SanitizerSet sanOpts)
490 : treatBooleanAsSigned(
false),
491 emitImplicitIntegerTruncationChecks(
492 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
493 emitImplicitIntegerSignChangeChecks(
494 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
501 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
502 QualType dstType, mlir::Type srcTy,
503 mlir::Type dstTy, ScalarConversionOpts opts) {
505 "Internal error: matrix types not handled by this function.");
506 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
507 mlir::isa<mlir::IntegerType>(dstTy)) &&
508 "Obsolete code. Don't use mlir::IntegerType with CIR.");
510 mlir::Type fullDstTy = dstTy;
511 if (mlir::isa<cir::VectorType>(srcTy) &&
512 mlir::isa<cir::VectorType>(dstTy)) {
514 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
515 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
518 std::optional<cir::CastKind> castKind;
520 if (mlir::isa<cir::BoolType>(srcTy)) {
521 if (opts.treatBooleanAsSigned)
522 cgf.getCIRGenModule().errorNYI(
"signed bool");
523 if (cgf.getBuilder().isInt(dstTy))
524 castKind = cir::CastKind::bool_to_int;
525 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
526 castKind = cir::CastKind::bool_to_float;
528 llvm_unreachable(
"Internal error: Cast to unexpected type");
529 }
else if (cgf.getBuilder().isInt(srcTy)) {
530 if (cgf.getBuilder().isInt(dstTy))
531 castKind = cir::CastKind::integral;
532 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
533 castKind = cir::CastKind::int_to_float;
535 llvm_unreachable(
"Internal error: Cast to unexpected type");
536 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
537 if (cgf.getBuilder().isInt(dstTy)) {
541 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
542 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
544 castKind = cir::CastKind::float_to_int;
545 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
547 return builder.createFloatingCast(src, fullDstTy);
549 llvm_unreachable(
"Internal error: Cast to unexpected type");
552 llvm_unreachable(
"Internal error: Cast from unexpected type");
555 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
556 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
561 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
565 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
570 "variably modified types in varargs");
573 return cgf.emitVAArg(ve);
576 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
580 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
582 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
585 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
587 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
589 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
591 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
593 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
595 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
597 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
599 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
601 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
602 cir::UnaryOpKind
kind,
bool isPre) {
603 if (cgf.getLangOpts().OpenMP)
611 if (
type->getAs<AtomicType>()) {
615 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
618 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
631 if (
kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
632 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
633 }
else if (
type->isIntegerType()) {
634 QualType promotedType;
635 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
636 if (cgf.getContext().isPromotableIntegerType(
type)) {
637 promotedType = cgf.getContext().getPromotedIntegerType(
type);
638 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
639 canPerformLossyDemotionCheck =
true;
640 canPerformLossyDemotionCheck &=
641 cgf.getContext().getCanonicalType(
type) !=
642 cgf.getContext().getCanonicalType(promotedType);
643 canPerformLossyDemotionCheck &=
650 (!canPerformLossyDemotionCheck ||
651 type->isSignedIntegerOrEnumerationType() ||
653 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
654 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
655 "The following check expects that if we do promotion to different "
656 "underlying canonical type, at least one of the types (either "
657 "base or promoted) will be signed, or the bitwidths will match.");
662 value = emitIncDecConsiderOverflowBehavior(e, value,
kind);
664 cir::UnaryOpKind
kind =
665 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
667 value = emitUnaryOp(e,
kind, input,
false);
669 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
670 QualType
type = ptr->getPointeeType();
671 if (cgf.getContext().getAsVariableArrayType(
type)) {
673 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
675 }
else if (
type->isFunctionType()) {
678 "Pointer arithmetic on function pointer");
683 CIRGenBuilderTy &builder = cgf.getBuilder();
684 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
685 mlir::Value amt = builder.getSInt32(amount, loc);
687 value = builder.createPtrStride(loc, value, amt);
689 }
else if (
type->isVectorType()) {
692 }
else if (
type->isRealFloatingType()) {
695 if (
type->isHalfType() &&
696 !cgf.getContext().getLangOpts().NativeHalfType) {
701 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
704 assert(
kind == cir::UnaryOpKind::Inc ||
705 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
706 value = emitUnaryOp(e,
kind, value);
708 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
711 }
else if (
type->isFixedPointType()) {
712 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
715 assert(
type->castAs<ObjCObjectPointerType>());
716 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
720 CIRGenFunction::SourceLocRAIIObject sourceloc{
725 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
727 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
731 return isPre ? value : input;
734 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
736 cir::UnaryOpKind
kind) {
737 assert(
kind == cir::UnaryOpKind::Inc ||
738 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
739 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
740 case LangOptions::SOB_Defined:
741 return emitUnaryOp(e,
kind, inVal,
false);
742 case LangOptions::SOB_Undefined:
744 return emitUnaryOp(e,
kind, inVal,
true);
745 case LangOptions::SOB_Trapping:
747 return emitUnaryOp(e,
kind, inVal,
true);
748 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
751 llvm_unreachable(
"Unexpected signed overflow behavior kind");
754 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
755 if (llvm::isa<MemberPointerType>(e->
getType()))
756 return cgf.cgm.emitMemberPointerConstant(e);
758 return cgf.emitLValue(e->
getSubExpr()).getPointer();
761 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
764 return emitLoadOfLValue(e);
767 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
770 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
771 if (result && !promotionType.
isNull())
772 return emitUnPromotedValue(result, e->
getType());
776 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
779 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
780 if (result && !promotionType.
isNull())
781 return emitUnPromotedValue(result, e->
getType());
785 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
786 cir::UnaryOpKind
kind,
787 QualType promotionType) {
788 ignoreResultAssign =
false;
790 if (!promotionType.
isNull())
791 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
800 return emitUnaryOp(e,
kind, operand, nsw);
803 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind
kind,
804 mlir::Value input,
bool nsw =
false) {
805 return builder.createOrFold<cir::UnaryOp>(
810 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
811 ignoreResultAssign =
false;
813 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
816 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
818 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
819 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
820 mlir::Value VisitRealImag(
const UnaryOperator *e,
821 QualType promotionType = QualType());
823 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
828 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
830 "ScalarExprEmitter: materialize temporary");
833 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
834 ASTContext &ctx = cgf.getContext();
837 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
839 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
840 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
843 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
844 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
847 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
848 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
852 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
854 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
855 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
856 return cgf.emitCXXNewExpr(e);
858 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
859 cgf.emitCXXDeleteExpr(e);
862 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
863 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
867 "ScalarExprEmitter: TypeTraitExpr stored as int");
871 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
877 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
879 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
882 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
885 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
887 "ScalarExprEmitter: cxx pseudo destructor");
890 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
891 cgf.emitCXXThrowExpr(e);
895 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
904 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
906 ScalarConversionOpts opts = ScalarConversionOpts()) {
916 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
922 if (srcType == dstType) {
923 if (opts.emitImplicitIntegerSignChangeChecks)
924 cgf.getCIRGenModule().errorNYI(loc,
925 "implicit integer sign change checks");
932 mlir::Type mlirSrcType = src.getType();
937 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
939 mlir::Type mlirDstType = cgf.convertType(dstType);
942 !cgf.getContext().getLangOpts().NativeHalfType) {
944 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
945 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
946 cgf.getCIRGenModule().errorNYI(loc,
947 "cast via llvm.convert.from.fp16");
952 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
953 cgf.getCIRGenModule().errorNYI(loc,
954 "cast via llvm.convert.from.fp16");
957 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
959 srcType = cgf.getContext().FloatTy;
960 mlirSrcType = cgf.floatTy;
966 if (mlirSrcType == mlirDstType) {
967 if (opts.emitImplicitIntegerSignChangeChecks)
968 cgf.getCIRGenModule().errorNYI(loc,
969 "implicit integer sign change checks");
976 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
977 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
978 return builder.getNullPtr(dstPT, src.getLoc());
984 return builder.createPtrToInt(src, mlirDstType);
991 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
993 "Splatted expr doesn't match with vector element type?");
995 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1000 cgf.getCIRGenModule().errorNYI(loc,
1001 "matrix type to matrix type conversion");
1005 "Internal error: conversion between matrix type and scalar type");
1008 mlir::Value res =
nullptr;
1009 mlir::Type resTy = mlirDstType;
1011 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1013 if (mlirDstType != resTy) {
1014 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
1015 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1019 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1023 if (opts.emitImplicitIntegerTruncationChecks)
1024 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1026 if (opts.emitImplicitIntegerSignChangeChecks)
1027 cgf.getCIRGenModule().errorNYI(loc,
1028 "implicit integer sign change checks");
1033 BinOpInfo emitBinOps(
const BinaryOperator *e,
1034 QualType promotionType = QualType()) {
1035 ignoreResultAssign =
false;
1037 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1038 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1039 if (!promotionType.
isNull())
1040 result.fullType = promotionType;
1042 result.fullType = e->
getType();
1043 result.compType = result.fullType;
1044 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1045 result.compType = vecType->getElementType();
1055 mlir::Value emitMul(
const BinOpInfo &ops);
1056 mlir::Value emitDiv(
const BinOpInfo &ops);
1057 mlir::Value emitRem(
const BinOpInfo &ops);
1058 mlir::Value emitAdd(
const BinOpInfo &ops);
1059 mlir::Value emitSub(
const BinOpInfo &ops);
1060 mlir::Value emitShl(
const BinOpInfo &ops);
1061 mlir::Value emitShr(
const BinOpInfo &ops);
1062 mlir::Value emitAnd(
const BinOpInfo &ops);
1063 mlir::Value emitXor(
const BinOpInfo &ops);
1064 mlir::Value emitOr(
const BinOpInfo &ops);
1066 LValue emitCompoundAssignLValue(
1067 const CompoundAssignOperator *e,
1068 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1069 mlir::Value &result);
1071 emitCompoundAssign(
const CompoundAssignOperator *e,
1072 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1076 QualType getPromotionType(QualType ty) {
1077 const clang::ASTContext &ctx = cgf.getContext();
1078 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1079 QualType elementTy = complexTy->getElementType();
1085 if (
auto *vt = ty->
getAs<VectorType>()) {
1086 unsigned numElements = vt->getNumElements();
1089 return cgf.getContext().FloatTy;
1096#define HANDLEBINOP(OP) \
1097 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1098 QualType promotionTy = getPromotionType(e->getType()); \
1099 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1100 if (result && !promotionTy.isNull()) \
1101 result = emitUnPromotedValue(result, e->getType()); \
1104 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1105 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1121 ignoreResultAssign =
false;
1127 auto clangCmpToCIRCmp =
1131 return cir::CmpOpKind::lt;
1133 return cir::CmpOpKind::gt;
1135 return cir::CmpOpKind::le;
1137 return cir::CmpOpKind::ge;
1139 return cir::CmpOpKind::eq;
1141 return cir::CmpOpKind::ne;
1143 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1155 BinOpInfo boInfo = emitBinOps(e);
1156 mlir::Value lhs = boInfo.lhs;
1157 mlir::Value rhs = boInfo.rhs;
1167 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1169 boInfo.lhs, boInfo.rhs);
1171 }
else if (boInfo.isFixedPointOp()) {
1174 result = builder.
getBool(
false, loc);
1178 mlir::isa<cir::PointerType>(lhs.getType()) &&
1179 mlir::isa<cir::PointerType>(rhs.getType())) {
1180 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1190 BinOpInfo boInfo = emitBinOps(e);
1191 result = cir::CmpOp::create(builder, loc,
kind, boInfo.lhs, boInfo.rhs);
1199#define VISITCOMP(CODE) \
1200 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1210 const bool ignore = std::exchange(ignoreResultAssign,
false);
1225 rhs = Visit(e->
getRHS());
1235 if (lhs.isBitField()) {
1255 if (!lhs.isVolatile())
1259 return emitLoadOfLValue(lhs, e->
getExprLoc());
1262 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1263 cgf.emitIgnoredExpr(e->
getLHS());
1265 return Visit(e->
getRHS());
1268 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1270 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1271 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1272 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1273 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1274 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1276 mlir::Value lhs = Visit(e->
getLHS());
1277 mlir::Value rhs = Visit(e->
getRHS());
1279 auto cmpOpKind = cir::CmpOpKind::ne;
1280 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1281 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1282 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1283 return builder.createIntCast(vecOr, vecTy);
1287 mlir::Type resTy = cgf.convertType(e->
getType());
1288 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1290 CIRGenFunction::ConditionalEvaluation eval(cgf);
1292 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1293 auto resOp = cir::TernaryOp::create(
1294 builder, loc, lhsCondV,
1295 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1296 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1297 b.getInsertionBlock()};
1298 cgf.curLexScope->setAsTernary();
1299 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1301 cir::YieldOp::create(
b, loc, res);
1304 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1305 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1306 b.getInsertionBlock()};
1308 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1309 cir::YieldOp::create(
b, loc, res.getRes());
1311 return maybePromoteBoolResult(resOp.getResult(), resTy);
1314 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1316 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1317 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1318 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1319 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1320 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1322 mlir::Value lhs = Visit(e->
getLHS());
1323 mlir::Value rhs = Visit(e->
getRHS());
1325 auto cmpOpKind = cir::CmpOpKind::ne;
1326 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1327 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1328 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1329 return builder.createIntCast(vecOr, vecTy);
1333 mlir::Type resTy = cgf.convertType(e->
getType());
1334 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1336 CIRGenFunction::ConditionalEvaluation eval(cgf);
1338 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1339 auto resOp = cir::TernaryOp::create(
1340 builder, loc, lhsCondV,
1341 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1342 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1343 b.getInsertionBlock()};
1345 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1346 cir::YieldOp::create(
b, loc, res.getRes());
1349 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1350 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1351 b.getInsertionBlock()};
1353 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1355 cir::YieldOp::create(
b, loc, res);
1358 return maybePromoteBoolResult(resOp.getResult(), resTy);
1361 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1362 return emitLoadOfLValue(e);
1365 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1366 return emitLoadOfLValue(e);
1370 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1371 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1375 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1379 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1381 "ScalarExprEmitter: objc string literal");
1384 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1385 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1388 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1390 "ScalarExprEmitter: objc array literal");
1393 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1395 "ScalarExprEmitter: objc dictionary literal");
1399 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1400 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1404 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1405 return cgf.emitAtomicExpr(e).getValue();
1409LValue ScalarExprEmitter::emitCompoundAssignLValue(
1411 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1412 mlir::Value &result) {
1423 if (promotionTypeCR.
isNull())
1427 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1429 if (!promotionTypeRHS.
isNull())
1432 opInfo.rhs = Visit(e->
getRHS());
1434 opInfo.fullType = promotionTypeCR;
1435 opInfo.compType = opInfo.fullType;
1436 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1437 opInfo.compType = vecType->getElementType();
1446 if (lhsTy->
getAs<AtomicType>()) {
1447 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1451 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1453 CIRGenFunction::SourceLocRAIIObject sourceloc{
1456 if (!promotionTypeLHS.
isNull())
1457 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1459 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1463 result = (this->*func)(opInfo);
1467 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1468 ScalarConversionOpts(cgf.
sanOpts));
1474 if (lhsLV.isBitField())
1485mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1489 cir::CastKind castOpKind;
1491 case CK_FloatingComplexToReal:
1492 castOpKind = cir::CastKind::float_complex_to_real;
1494 case CK_IntegralComplexToReal:
1495 castOpKind = cir::CastKind::int_complex_to_real;
1497 case CK_FloatingComplexToBoolean:
1498 castOpKind = cir::CastKind::float_complex_to_bool;
1500 case CK_IntegralComplexToBoolean:
1501 castOpKind = cir::CastKind::int_complex_to_bool;
1504 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1510mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1511 QualType promotionType) {
1513 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1514 switch (bo->getOpcode()) {
1515#define HANDLE_BINOP(OP) \
1517 return emit##OP(emitBinOps(bo, promotionType));
1526 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1527 switch (uo->getOpcode()) {
1530 return VisitRealImag(uo, promotionType);
1532 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1534 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1539 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1541 if (!promotionType.
isNull())
1542 return emitPromotedValue(result, promotionType);
1543 return emitUnPromotedValue(result, e->
getType());
1548mlir::Value ScalarExprEmitter::emitCompoundAssign(
1549 const CompoundAssignOperator *e,
1550 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1552 bool ignore = std::exchange(ignoreResultAssign,
false);
1554 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1565 if (!lhs.isVolatile())
1569 return emitLoadOfLValue(lhs, e->
getExprLoc());
1572mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1574 mlir::OpBuilder &builder = cgf.builder;
1576 auto scope = cir::ScopeOp::create(
1579 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1580 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1581 builder.getInsertionBlock()};
1582 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1583 if (scopeYieldVal) {
1587 cir::YieldOp::create(builder, loc, scopeYieldVal);
1588 yieldTy = scopeYieldVal.getType();
1592 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1602#define COMPOUND_OP(Op) \
1603 case BO_##Op##Assign: \
1604 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1641 llvm_unreachable(
"Not valid compound assignment operators");
1643 llvm_unreachable(
"Unhandled compound assignment operator");
1648 bool ignoreResultAssign) {
1650 "Invalid scalar expression to emit");
1653 .Visit(
const_cast<Expr *
>(e));
1658 if (!promotionType.
isNull())
1673static std::optional<QualType>
1677 return std::nullopt;
1682 return std::nullopt;
1695 const BinOpInfo &op) {
1697 "Expected a unary or binary operator");
1701 if (!op.mayHaveIntegerOverflow())
1705 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1706 return !uo->canOverflow();
1711 std::optional<QualType> optionalLHSTy =
1716 std::optional<QualType> optionalRHSTy =
1726 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1733 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1734 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1739 const BinOpInfo &op,
1740 bool isSubtraction) {
1745 mlir::Value pointer = op.lhs;
1746 Expr *pointerOperand =
expr->getLHS();
1747 mlir::Value
index = op.rhs;
1748 Expr *indexOperand =
expr->getRHS();
1754 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1755 std::swap(pointer,
index);
1756 std::swap(pointerOperand, indexOperand);
1758 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1759 "Need a pointer operand");
1760 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1795 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1806 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1811 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1813 pointer.getType(), pointer,
index);
1816mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1817 const mlir::Location loc = cgf.
getLoc(ops.loc);
1819 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1820 case LangOptions::SOB_Defined:
1821 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1822 return builder.createMul(loc, ops.lhs, ops.rhs);
1824 case LangOptions::SOB_Undefined:
1825 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1826 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1828 case LangOptions::SOB_Trapping:
1830 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1840 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1842 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1844 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1846 return builder.createFMul(loc, ops.lhs, ops.rhs);
1849 if (ops.isFixedPointOp()) {
1855 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1856 cgf.
convertType(ops.fullType), cir::BinOpKind::Mul,
1859mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1860 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1861 cgf.
convertType(ops.fullType), cir::BinOpKind::Div,
1864mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1865 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1866 cgf.
convertType(ops.fullType), cir::BinOpKind::Rem,
1870mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1871 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1872 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1875 const mlir::Location loc = cgf.
getLoc(ops.loc);
1877 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1878 case LangOptions::SOB_Defined:
1879 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1880 return builder.createAdd(loc, ops.lhs, ops.rhs);
1882 case LangOptions::SOB_Undefined:
1883 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1884 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1886 case LangOptions::SOB_Trapping:
1888 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1899 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1901 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1903 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1905 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1908 if (ops.isFixedPointOp()) {
1914 return cir::BinOp::create(builder, loc, cgf.
convertType(ops.fullType),
1915 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1918mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1919 const mlir::Location loc = cgf.
getLoc(ops.loc);
1921 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1923 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1924 case LangOptions::SOB_Defined: {
1925 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1926 return builder.createSub(loc, ops.lhs, ops.rhs);
1929 case LangOptions::SOB_Undefined:
1930 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1931 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1933 case LangOptions::SOB_Trapping:
1935 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1947 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1949 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1951 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1953 return builder.createFSub(loc, ops.lhs, ops.rhs);
1956 if (ops.isFixedPointOp()) {
1962 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1964 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1969 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1981 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1985mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1987 if (ops.isFixedPointOp()) {
1997 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2001 bool sanitizeUnsignedBase =
2002 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2004 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2005 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2010 else if ((sanitizeBase || sanitizeExponent) &&
2011 mlir::isa<cir::IntType>(ops.lhs.getType()))
2014 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2017mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2019 if (ops.isFixedPointOp()) {
2032 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2033 mlir::isa<cir::IntType>(ops.lhs.getType()))
2038 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2041mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2042 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2043 cgf.
convertType(ops.fullType), cir::BinOpKind::And,
2046mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2047 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2048 cgf.
convertType(ops.fullType), cir::BinOpKind::Xor,
2051mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2052 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2053 cgf.
convertType(ops.fullType), cir::BinOpKind::Or,
2061mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2063 QualType destTy = ce->
getType();
2068 ignoreResultAssign =
false;
2071 case clang::CK_Dependent:
2072 llvm_unreachable(
"dependent cast kind in CIR gen!");
2073 case clang::CK_BuiltinFnToFnPtr:
2074 llvm_unreachable(
"builtin functions are handled elsewhere");
2075 case CK_LValueBitCast:
2076 case CK_LValueToRValueBitCast: {
2078 Address sourceAddr = sourceLVal.getAddress();
2084 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2087 case CK_CPointerToObjCPointerCast:
2088 case CK_BlockPointerToObjCPointerCast:
2089 case CK_AnyPointerToBlockPointerCast:
2091 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2096 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2098 "sanitizer support");
2102 "strict vtable pointers");
2128 case CK_AddressSpaceConversion: {
2129 Expr::EvalResult result;
2146 cir::TargetAddressSpaceAttr subExprAS;
2151 "non-target address space conversion");
2155 cgf, Visit(subExpr), subExprAS, convertType(destTy));
2158 case CK_AtomicToNonAtomic: {
2164 case CK_NonAtomicToAtomic:
2165 case CK_UserDefinedConversion:
2166 return Visit(
const_cast<Expr *
>(subExpr));
2168 auto v = Visit(
const_cast<Expr *
>(subExpr));
2174 if (t != v.getType())
2179 case CK_IntegralToPointer: {
2181 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2188 mlir::Value middleVal = builder.createCast(
2190 : cir::CastKind::integral,
2195 "IntegralToPointer: strict vtable pointers");
2199 return builder.createIntToPtr(middleVal, destCIRTy);
2202 case CK_BaseToDerived: {
2204 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2216 case CK_UncheckedDerivedToBase:
2217 case CK_DerivedToBase: {
2228 case CK_ArrayToPointerDecay:
2231 case CK_NullToPointer: {
2241 case CK_NullToMemberPointer: {
2247 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2249 auto ty = mlir::cast<cir::MethodType>(cgf.
convertType(destTy));
2253 auto ty = mlir::cast<cir::DataMemberType>(cgf.
convertType(destTy));
2254 return builder.getNullDataMemberPtr(ty, cgf.
getLoc(subExpr->
getExprLoc()));
2257 case CK_ReinterpretMemberPointer: {
2258 mlir::Value src = Visit(subExpr);
2262 case CK_BaseToDerivedMemberPointer:
2263 case CK_DerivedToBaseMemberPointer: {
2264 mlir::Value src = Visit(subExpr);
2268 QualType derivedTy =
2269 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2270 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2271 NestedNameSpecifier qualifier = mpType->getQualifier();
2272 assert(qualifier &&
"member pointer without class qualifier");
2273 const Type *qualifierType = qualifier.getAsType();
2274 assert(qualifierType &&
"member pointer qualifier is not a type");
2281 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2284 if (
kind == CK_BaseToDerivedMemberPointer)
2285 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2287 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2290 if (
kind == CK_BaseToDerivedMemberPointer)
2291 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2293 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2297 case CK_LValueToRValue:
2299 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2300 return Visit(
const_cast<Expr *
>(subExpr));
2302 case CK_IntegralCast: {
2303 ScalarConversionOpts opts;
2304 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2305 if (!ice->isPartOfExplicitCast())
2306 opts = ScalarConversionOpts(cgf.
sanOpts);
2308 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2312 case CK_FloatingComplexToReal:
2313 case CK_IntegralComplexToReal:
2314 case CK_FloatingComplexToBoolean:
2315 case CK_IntegralComplexToBoolean: {
2321 case CK_FloatingRealToComplex:
2322 case CK_FloatingComplexCast:
2323 case CK_IntegralRealToComplex:
2324 case CK_IntegralComplexCast:
2325 case CK_IntegralComplexToFloatingComplex:
2326 case CK_FloatingComplexToIntegralComplex:
2327 llvm_unreachable(
"scalar cast to non-scalar value");
2329 case CK_PointerToIntegral: {
2330 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2333 "strict vtable pointers");
2334 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
2340 case CK_IntegralToFloating:
2341 case CK_FloatingToIntegral:
2342 case CK_FloatingCast:
2343 case CK_FixedPointToFloating:
2344 case CK_FloatingToFixedPoint: {
2345 if (
kind == CK_FixedPointToFloating ||
kind == CK_FloatingToFixedPoint) {
2347 "fixed point casts");
2351 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2355 case CK_IntegralToBoolean:
2356 return emitIntToBoolConversion(Visit(subExpr),
2359 case CK_PointerToBoolean:
2360 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2361 case CK_FloatingToBoolean:
2362 return emitFloatToBoolConversion(Visit(subExpr),
2364 case CK_MemberPointerToBoolean: {
2365 mlir::Value memPtr = Visit(subExpr);
2367 cir::CastKind::member_ptr_to_bool, memPtr,
2371 case CK_VectorSplat: {
2373 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2374 return cir::VecSplatOp::create(builder,
2378 case CK_FunctionToPointerDecay:
2388mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2390 return emitLoadOfLValue(e);
2397mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2402 Expr::EvalResult result;
2404 llvm::APSInt value = result.
Val.
getInt();
2408 return emitLoadOfLValue(e);
2411mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2412 const unsigned numInitElements = e->
getNumInits();
2414 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2415 assert((ignore ==
false ||
2417 "init list ignored");
2425 const auto vectorType =
2428 SmallVector<mlir::Value, 16> elements;
2429 for (Expr *init : e->
inits()) {
2430 elements.push_back(Visit(init));
2434 if (numInitElements < vectorType.getSize()) {
2437 std::fill_n(std::back_inserter(elements),
2438 vectorType.getSize() - numInitElements, zeroValue);
2441 return cir::VecCreateOp::create(cgf.
getBuilder(),
2447 if (numInitElements == 0)
2458 "Invalid scalar expression to emit");
2460 .emitScalarConversion(src, srcTy, dstTy, loc);
2468 "Invalid complex -> scalar conversion");
2473 ? cir::CastKind::float_complex_to_bool
2474 : cir::CastKind::int_complex_to_bool;
2479 ? cir::CastKind::float_complex_to_real
2480 : cir::CastKind::int_complex_to_real;
2486mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2493 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2495 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2496 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2504 boolVal = builder.createNot(boolVal);
2510mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2515 llvm::APSInt value = evalResult.
Val.
getInt();
2521 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2525mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2527 mlir::Value result = VisitRealImag(e, promotionTy);
2528 if (result && !promotionTy.
isNull())
2529 result = emitUnPromotedValue(result, e->
getType());
2533mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2535 mlir::Value result = VisitRealImag(e, promotionTy);
2536 if (result && !promotionTy.
isNull())
2537 result = emitUnPromotedValue(result, e->
getType());
2541mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2542 QualType promotionTy) {
2543 assert(e->
getOpcode() == clang::UO_Real ||
2545 "Invalid UnaryOp kind for ComplexType Real or Imag");
2562 ? builder.createComplexReal(loc, complex)
2563 : builder.createComplexImag(loc, complex);
2567 mlir::Value operand = promotionTy.
isNull()
2569 : cgf.emitPromotedScalarExpr(op, promotionTy);
2570 return builder.createComplexReal(loc, operand);
2575 mlir::Value operand;
2578 operand = cir::LoadOp::create(builder, loc, operand);
2579 }
else if (!promotionTy.
isNull()) {
2584 return builder.createComplexImag(loc, operand);
2589mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2590 const UnaryExprOrTypeTraitExpr *e) {
2594 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
2595 if (
const VariableArrayType *vat =
2600 bool evaluateExtent =
true;
2601 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2603 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2606 if (evaluateExtent) {
2617 if (
kind == UETT_CountOf)
2622 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2623 mlir::Value numElts = vlaSize.
numElts;
2627 if (!eltSize.
isOne()) {
2629 mlir::Value eltSizeValue =
2630 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
2632 return builder.createMul(loc, eltSizeValue, numElts,
2639 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2641 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2643 return builder.getConstant(
2645 llvm::APSInt(llvm::APInt(64, 1),
true)));
2646 }
else if (e->
getKind() == UETT_VectorElements) {
2648 if (vecTy.getIsScalable()) {
2651 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
2652 return builder.getConstant(
2657 return builder.getConstant(
2658 loc, cir::IntAttr::get(cgf.
cgm.
uInt64Ty, vecTy.getSize()));
2661 return builder.getConstant(
2683mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2684 const AbstractConditionalOperator *e) {
2687 ignoreResultAssign =
false;
2690 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2692 Expr *condExpr = e->
getCond();
2700 Expr *live = lhsExpr, *dead = rhsExpr;
2702 std::swap(live, dead);
2708 mlir::Value result = Visit(live);
2715 loc, cir::PoisonAttr::get(builder.getContext(),
2723 QualType condType = condExpr->
getType();
2736 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2740 mlir::Value condValue = Visit(condExpr);
2741 mlir::Value lhsValue = Visit(lhsExpr);
2742 mlir::Value rhsValue = Visit(rhsExpr);
2743 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2752 bool lhsIsVoid =
false;
2756 mlir::Value lhs = Visit(lhsExpr);
2762 mlir::Value rhs = Visit(rhsExpr);
2764 assert(!rhs &&
"lhs and rhs types must match");
2772 CIRGenFunction::ConditionalEvaluation eval(cgf);
2773 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2774 mlir::Type yieldTy{};
2776 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2777 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2781 eval.beginEvaluation();
2782 mlir::Value branch = Visit(
expr);
2783 eval.endEvaluation();
2786 yieldTy = branch.getType();
2787 cir::YieldOp::create(
b, loc, branch);
2791 insertPoints.push_back(
b.saveInsertionPoint());
2795 mlir::Value result = cir::TernaryOp::create(
2796 builder, loc, condV,
2798 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2799 emitBranch(
b, loc, lhsExpr);
2802 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2803 emitBranch(
b, loc, rhsExpr);
2807 if (!insertPoints.empty()) {
2813 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2814 mlir::OpBuilder::InsertionGuard guard(builder);
2815 builder.restoreInsertionPoint(toInsert);
2818 if (mlir::isa<cir::VoidType>(yieldTy)) {
2819 cir::YieldOp::create(builder, loc);
2822 cir::YieldOp::create(builder, loc, op0);
2832 cir::UnaryOpKind
kind,
2835 .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.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
__device__ __2f16 float __ockl_bool s
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
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
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::Type convertTypeForMem(QualType t)
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::MLIRContext & getMLIRContext()
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
LexicalScope * curLexScope
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
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)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
bool isOne() const
isOne - Test whether the quantity equals one.
unsigned getValue() const
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
ChildElementIter< false > begin()
size_t getDataElementCount() const
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
A pointer to member type per C++ 8.3.3 - Pointers to members.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
SourceLocation getExprLoc() const LLVM_READONLY
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
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,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
bool isTargetAddressSpace(LangAS AS)
@ Type
The name was classified as a type.
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 memberFuncPtrAuthInfo()
static bool emitLValueAlignmentAssumption()
static bool incrementProfileCounter()
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool HasSideEffects
Whether the evaluated expression has side effects.
bool has(SanitizerMask K) const
Check if a certain (single) sanitizer is enabled.