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) {
267 auto it = e->
begin();
268 llvm::APInt value = (*it)->getValue();
269 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
272 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
274 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
278 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
281 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
282 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
285 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
286 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
289 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
290 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
293 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
294 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
297 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
298 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
301 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
303 "ScalarExprEmitter: objc availability check");
307 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
309 "ScalarExprEmitter: matrix subscript");
313 mlir::Value VisitCastExpr(
CastExpr *e);
314 mlir::Value VisitCallExpr(
const CallExpr *e);
316 mlir::Value VisitStmtExpr(StmtExpr *e) {
317 CIRGenFunction::StmtExprEvaluation eval(cgf);
325 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
327 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
331 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
332 ignoreResultAssign =
false;
338 const mlir::Value vecValue = Visit(e->
getBase());
339 const mlir::Value indexValue = Visit(e->
getIdx());
340 return cir::VecExtractOp::create(cgf.builder, loc, vecValue, indexValue);
343 return emitLoadOfLValue(e);
346 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
349 mlir::Value inputVec = Visit(e->
getExpr(0));
350 mlir::Value indexVec = Visit(e->
getExpr(1));
351 return cir::VecShuffleDynamicOp::create(
352 cgf.builder, cgf.getLoc(e->
getSourceRange()), inputVec, indexVec);
355 mlir::Value vec1 = Visit(e->
getExpr(0));
356 mlir::Value vec2 = Visit(e->
getExpr(1));
361 SmallVector<mlir::Attribute, 8> indices;
364 cir::IntAttr::get(cgf.builder.getSInt64Ty(),
370 return cir::VecShuffleOp::create(cgf.builder,
372 cgf.convertType(e->
getType()), vec1, vec2,
373 cgf.builder.getArrayAttr(indices));
376 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
379 return emitScalarConversion(Visit(e->
getSrcExpr()),
384 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
386 mlir::Value VisitMemberExpr(MemberExpr *e);
388 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
389 return emitLoadOfLValue(e);
392 mlir::Value VisitInitListExpr(InitListExpr *e);
394 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
396 "ScalarExprEmitter: array init index");
400 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
402 "ScalarExprEmitter: implicit value init");
406 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
407 return VisitCastExpr(e);
410 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
411 return cgf.cgm.emitNullConstant(e->
getType(),
416 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
419 return cgf.getBuilder().createPtrToBoolCast(v);
422 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
423 cir::BoolType boolTy = builder.getBoolTy();
424 return cir::CastOp::create(builder, loc, boolTy,
425 cir::CastKind::float_to_bool, src);
428 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
434 cir::BoolType boolTy = builder.getBoolTy();
435 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
441 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
442 mlir::Location loc) {
443 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
446 return emitFloatToBoolConversion(src, loc);
448 if (llvm::isa<MemberPointerType>(srcType)) {
449 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
450 return builder.getFalse(loc);
454 return emitIntToBoolConversion(src, loc);
456 assert(::mlir::isa<cir::PointerType>(src.getType()));
457 return emitPointerToBoolConversion(src, srcType);
462 struct ScalarConversionOpts {
463 bool treatBooleanAsSigned;
464 bool emitImplicitIntegerTruncationChecks;
465 bool emitImplicitIntegerSignChangeChecks;
467 ScalarConversionOpts()
468 : treatBooleanAsSigned(
false),
469 emitImplicitIntegerTruncationChecks(
false),
470 emitImplicitIntegerSignChangeChecks(
false) {}
472 ScalarConversionOpts(clang::SanitizerSet sanOpts)
473 : treatBooleanAsSigned(
false),
474 emitImplicitIntegerTruncationChecks(
475 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
476 emitImplicitIntegerSignChangeChecks(
477 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
484 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
485 QualType dstType, mlir::Type srcTy,
486 mlir::Type dstTy, ScalarConversionOpts opts) {
488 "Internal error: matrix types not handled by this function.");
489 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
490 mlir::isa<mlir::IntegerType>(dstTy)) &&
491 "Obsolete code. Don't use mlir::IntegerType with CIR.");
493 mlir::Type fullDstTy = dstTy;
494 if (mlir::isa<cir::VectorType>(srcTy) &&
495 mlir::isa<cir::VectorType>(dstTy)) {
497 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
498 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
501 std::optional<cir::CastKind> castKind;
503 if (mlir::isa<cir::BoolType>(srcTy)) {
504 if (opts.treatBooleanAsSigned)
505 cgf.getCIRGenModule().errorNYI(
"signed bool");
506 if (cgf.getBuilder().isInt(dstTy))
507 castKind = cir::CastKind::bool_to_int;
508 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
509 castKind = cir::CastKind::bool_to_float;
511 llvm_unreachable(
"Internal error: Cast to unexpected type");
512 }
else if (cgf.getBuilder().isInt(srcTy)) {
513 if (cgf.getBuilder().isInt(dstTy))
514 castKind = cir::CastKind::integral;
515 else if (mlir::isa<cir::FPTypeInterface>(dstTy))
516 castKind = cir::CastKind::int_to_float;
518 llvm_unreachable(
"Internal error: Cast to unexpected type");
519 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
520 if (cgf.getBuilder().isInt(dstTy)) {
524 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
525 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
527 castKind = cir::CastKind::float_to_int;
528 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
530 return builder.createFloatingCast(src, fullDstTy);
532 llvm_unreachable(
"Internal error: Cast to unexpected type");
535 llvm_unreachable(
"Internal error: Cast from unexpected type");
538 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
539 return cir::CastOp::create(builder, src.getLoc(), fullDstTy, *castKind,
544 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
548 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
553 "variably modified types in varargs");
556 return cgf.emitVAArg(ve);
559 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
563 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
565 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
568 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
570 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
false);
572 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
574 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
false);
576 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
578 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Dec,
true);
580 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
582 return emitScalarPrePostIncDec(e, lv, cir::UnaryOpKind::Inc,
true);
584 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv,
585 cir::UnaryOpKind kind,
bool isPre) {
586 if (cgf.getLangOpts().OpenMP)
594 if (
type->getAs<AtomicType>()) {
598 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
601 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
614 if (kind == cir::UnaryOpKind::Inc &&
type->isBooleanType()) {
615 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
616 }
else if (
type->isIntegerType()) {
617 QualType promotedType;
618 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
619 if (cgf.getContext().isPromotableIntegerType(
type)) {
620 promotedType = cgf.getContext().getPromotedIntegerType(
type);
621 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
622 canPerformLossyDemotionCheck =
true;
623 canPerformLossyDemotionCheck &=
624 cgf.getContext().getCanonicalType(
type) !=
625 cgf.getContext().getCanonicalType(promotedType);
626 canPerformLossyDemotionCheck &=
633 (!canPerformLossyDemotionCheck ||
634 type->isSignedIntegerOrEnumerationType() ||
636 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
637 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
638 "The following check expects that if we do promotion to different "
639 "underlying canonical type, at least one of the types (either "
640 "base or promoted) will be signed, or the bitwidths will match.");
645 value = emitIncDecConsiderOverflowBehavior(e, value, kind);
647 cir::UnaryOpKind
kind =
648 e->
isIncrementOp() ? cir::UnaryOpKind::Inc : cir::UnaryOpKind::Dec;
650 value = emitUnaryOp(e, kind, input,
false);
652 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
653 QualType
type = ptr->getPointeeType();
654 if (cgf.getContext().getAsVariableArrayType(
type)) {
656 cgf.cgm.errorNYI(e->
getSourceRange(),
"Pointer arithmetic on VLA");
658 }
else if (
type->isFunctionType()) {
661 "Pointer arithmetic on function pointer");
666 CIRGenBuilderTy &builder = cgf.getBuilder();
667 int amount =
kind == cir::UnaryOpKind::Inc ? 1 : -1;
668 mlir::Value amt = builder.getSInt32(amount, loc);
670 value = builder.createPtrStride(loc, value, amt);
672 }
else if (
type->isVectorType()) {
675 }
else if (
type->isRealFloatingType()) {
678 if (
type->isHalfType() &&
679 !cgf.getContext().getLangOpts().NativeHalfType) {
684 if (mlir::isa<cir::SingleType, cir::DoubleType>(value.getType())) {
687 assert(kind == cir::UnaryOpKind::Inc ||
688 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
689 value = emitUnaryOp(e, kind, value);
691 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fp type");
694 }
else if (
type->isFixedPointType()) {
695 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec other fixed point");
698 assert(
type->castAs<ObjCObjectPointerType>());
699 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
703 CIRGenFunction::SourceLocRAIIObject sourceloc{
708 return cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
710 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
714 return isPre ? value : input;
717 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
719 cir::UnaryOpKind kind) {
720 assert(kind == cir::UnaryOpKind::Inc ||
721 kind == cir::UnaryOpKind::Dec &&
"Invalid UnaryOp kind");
722 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
723 case LangOptions::SOB_Defined:
724 return emitUnaryOp(e, kind, inVal,
false);
725 case LangOptions::SOB_Undefined:
727 return emitUnaryOp(e, kind, inVal,
true);
728 case LangOptions::SOB_Trapping:
730 return emitUnaryOp(e, kind, inVal,
true);
731 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
734 llvm_unreachable(
"Unexpected signed overflow behavior kind");
737 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
738 if (llvm::isa<MemberPointerType>(e->
getType()))
739 return cgf.cgm.emitMemberPointerConstant(e);
741 return cgf.emitLValue(e->
getSubExpr()).getPointer();
744 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
747 return emitLoadOfLValue(e);
750 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
753 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus, promotionType);
754 if (result && !promotionType.
isNull())
755 return emitUnPromotedValue(result, e->
getType());
759 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
762 emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus, promotionType);
763 if (result && !promotionType.
isNull())
764 return emitUnPromotedValue(result, e->
getType());
768 mlir::Value emitUnaryPlusOrMinus(
const UnaryOperator *e,
769 cir::UnaryOpKind kind,
770 QualType promotionType) {
771 ignoreResultAssign =
false;
773 if (!promotionType.
isNull())
774 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
783 return emitUnaryOp(e, kind, operand, nsw);
786 mlir::Value emitUnaryOp(
const UnaryOperator *e, cir::UnaryOpKind kind,
787 mlir::Value input,
bool nsw =
false) {
788 return cir::UnaryOp::create(builder,
790 input.getType(), kind, input, nsw);
793 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
794 ignoreResultAssign =
false;
796 return emitUnaryOp(e, cir::UnaryOpKind::Not, op);
799 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
801 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
802 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
803 mlir::Value VisitRealImag(
const UnaryOperator *e,
804 QualType promotionType = QualType());
806 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
811 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
813 "ScalarExprEmitter: materialize temporary");
816 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
817 ASTContext &ctx = cgf.getContext();
820 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
822 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
823 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
826 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
827 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
830 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
831 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
835 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
837 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
838 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
839 return cgf.emitCXXNewExpr(e);
841 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
842 cgf.emitCXXDeleteExpr(e);
845 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
846 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
850 "ScalarExprEmitter: TypeTraitExpr stored as int");
854 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
860 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
862 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
865 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
868 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
870 "ScalarExprEmitter: cxx pseudo destructor");
873 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
874 cgf.emitCXXThrowExpr(e);
878 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
887 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
889 ScalarConversionOpts opts = ScalarConversionOpts()) {
899 cgf.getCIRGenModule().errorNYI(loc,
"fixed point conversions");
905 if (srcType == dstType) {
906 if (opts.emitImplicitIntegerSignChangeChecks)
907 cgf.getCIRGenModule().errorNYI(loc,
908 "implicit integer sign change checks");
915 mlir::Type mlirSrcType = src.getType();
920 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
922 mlir::Type mlirDstType = cgf.convertType(dstType);
925 !cgf.getContext().getLangOpts().NativeHalfType) {
927 if (mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
928 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
929 cgf.getCIRGenModule().errorNYI(loc,
930 "cast via llvm.convert.from.fp16");
935 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics())
936 cgf.getCIRGenModule().errorNYI(loc,
937 "cast via llvm.convert.from.fp16");
940 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
942 srcType = cgf.getContext().FloatTy;
943 mlirSrcType = cgf.floatTy;
949 if (mlirSrcType == mlirDstType) {
950 if (opts.emitImplicitIntegerSignChangeChecks)
951 cgf.getCIRGenModule().errorNYI(loc,
952 "implicit integer sign change checks");
959 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
960 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
961 return builder.getNullPtr(dstPT, src.getLoc());
967 return builder.createPtrToInt(src, mlirDstType);
974 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
976 "Splatted expr doesn't match with vector element type?");
978 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
983 cgf.getCIRGenModule().errorNYI(loc,
984 "matrix type to matrix type conversion");
988 "Internal error: conversion between matrix type and scalar type");
991 mlir::Value res =
nullptr;
992 mlir::Type resTy = mlirDstType;
994 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
996 if (mlirDstType != resTy) {
997 if (cgf.getContext().getTargetInfo().useFP16ConversionIntrinsics()) {
998 cgf.getCIRGenModule().errorNYI(loc,
"cast via llvm.convert.to.fp16");
1002 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1006 if (opts.emitImplicitIntegerTruncationChecks)
1007 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1009 if (opts.emitImplicitIntegerSignChangeChecks)
1010 cgf.getCIRGenModule().errorNYI(loc,
1011 "implicit integer sign change checks");
1016 BinOpInfo emitBinOps(
const BinaryOperator *e,
1017 QualType promotionType = QualType()) {
1018 ignoreResultAssign =
false;
1020 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1021 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1022 if (!promotionType.
isNull())
1023 result.fullType = promotionType;
1025 result.fullType = e->
getType();
1026 result.compType = result.fullType;
1027 if (
const auto *vecType = dyn_cast_or_null<VectorType>(result.fullType)) {
1028 result.compType = vecType->getElementType();
1038 mlir::Value emitMul(
const BinOpInfo &ops);
1039 mlir::Value emitDiv(
const BinOpInfo &ops);
1040 mlir::Value emitRem(
const BinOpInfo &ops);
1041 mlir::Value emitAdd(
const BinOpInfo &ops);
1042 mlir::Value emitSub(
const BinOpInfo &ops);
1043 mlir::Value emitShl(
const BinOpInfo &ops);
1044 mlir::Value emitShr(
const BinOpInfo &ops);
1045 mlir::Value emitAnd(
const BinOpInfo &ops);
1046 mlir::Value emitXor(
const BinOpInfo &ops);
1047 mlir::Value emitOr(
const BinOpInfo &ops);
1049 LValue emitCompoundAssignLValue(
1050 const CompoundAssignOperator *e,
1051 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1052 mlir::Value &result);
1054 emitCompoundAssign(
const CompoundAssignOperator *e,
1055 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1059 QualType getPromotionType(QualType ty) {
1060 const clang::ASTContext &ctx = cgf.getContext();
1061 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1062 QualType elementTy = complexTy->getElementType();
1068 if (
auto *vt = ty->
getAs<VectorType>()) {
1069 unsigned numElements = vt->getNumElements();
1072 return cgf.getContext().FloatTy;
1079#define HANDLEBINOP(OP) \
1080 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1081 QualType promotionTy = getPromotionType(e->getType()); \
1082 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1083 if (result && !promotionTy.isNull()) \
1084 result = emitUnPromotedValue(result, e->getType()); \
1087 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1088 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1104 ignoreResultAssign =
false;
1110 auto clangCmpToCIRCmp =
1114 return cir::CmpOpKind::lt;
1116 return cir::CmpOpKind::gt;
1118 return cir::CmpOpKind::le;
1120 return cir::CmpOpKind::ge;
1122 return cir::CmpOpKind::eq;
1124 return cir::CmpOpKind::ne;
1126 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1130 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1138 BinOpInfo boInfo = emitBinOps(e);
1139 mlir::Value lhs = boInfo.lhs;
1140 mlir::Value rhs = boInfo.rhs;
1150 result = cir::VecCmpOp::create(builder, cgf.
getLoc(boInfo.loc),
1152 boInfo.lhs, boInfo.rhs);
1154 }
else if (boInfo.isFixedPointOp()) {
1157 result = builder.
getBool(
false, loc);
1161 mlir::isa<cir::PointerType>(lhs.getType()) &&
1162 mlir::isa<cir::PointerType>(rhs.getType())) {
1163 cgf.
cgm.
errorNYI(loc,
"strict vtable pointer comparisons");
1166 cir::CmpOpKind kind = clangCmpToCIRCmp(e->
getOpcode());
1173 BinOpInfo boInfo = emitBinOps(e);
1174 result = cir::CmpOp::create(builder, loc, kind, boInfo.lhs, boInfo.rhs);
1182#define VISITCOMP(CODE) \
1183 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1193 const bool ignore = std::exchange(ignoreResultAssign,
false);
1208 rhs = Visit(e->
getRHS());
1218 if (lhs.isBitField()) {
1238 if (!lhs.isVolatile())
1242 return emitLoadOfLValue(lhs, e->
getExprLoc());
1245 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1246 cgf.emitIgnoredExpr(e->
getLHS());
1248 return Visit(e->
getRHS());
1251 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1253 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1254 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1255 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1256 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1257 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1259 mlir::Value lhs = Visit(e->
getLHS());
1260 mlir::Value rhs = Visit(e->
getRHS());
1262 auto cmpOpKind = cir::CmpOpKind::ne;
1263 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1264 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1265 mlir::Value vecOr = builder.createAnd(loc, lhs, rhs);
1266 return builder.createIntCast(vecOr, vecTy);
1270 mlir::Type resTy = cgf.convertType(e->
getType());
1271 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1273 CIRGenFunction::ConditionalEvaluation eval(cgf);
1275 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1276 auto resOp = cir::TernaryOp::create(
1277 builder, loc, lhsCondV,
1278 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1279 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1280 b.getInsertionBlock()};
1281 cgf.curLexScope->setAsTernary();
1282 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1284 cir::YieldOp::create(
b, loc, res);
1287 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1288 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1289 b.getInsertionBlock()};
1291 auto res = cir::ConstantOp::create(
b, loc, builder.getFalseAttr());
1292 cir::YieldOp::create(
b, loc, res.getRes());
1294 return maybePromoteBoolResult(resOp.getResult(), resTy);
1297 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1299 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1300 auto vecTy = mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1301 mlir::Value zeroValue = builder.getNullValue(vecTy.getElementType(), loc);
1302 SmallVector<mlir::Value, 16> elements(vecTy.getSize(), zeroValue);
1303 auto zeroVec = cir::VecCreateOp::create(builder, loc, vecTy, elements);
1305 mlir::Value lhs = Visit(e->
getLHS());
1306 mlir::Value rhs = Visit(e->
getRHS());
1308 auto cmpOpKind = cir::CmpOpKind::ne;
1309 lhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, lhs, zeroVec);
1310 rhs = cir::VecCmpOp::create(builder, loc, vecTy, cmpOpKind, rhs, zeroVec);
1311 mlir::Value vecOr = builder.createOr(loc, lhs, rhs);
1312 return builder.createIntCast(vecOr, vecTy);
1316 mlir::Type resTy = cgf.convertType(e->
getType());
1317 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1319 CIRGenFunction::ConditionalEvaluation eval(cgf);
1321 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1322 auto resOp = cir::TernaryOp::create(
1323 builder, loc, lhsCondV,
1324 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1325 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1326 b.getInsertionBlock()};
1328 auto res = cir::ConstantOp::create(
b, loc, builder.getTrueAttr());
1329 cir::YieldOp::create(
b, loc, res.getRes());
1332 [&](mlir::OpBuilder &
b, mlir::Location loc) {
1333 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1334 b.getInsertionBlock()};
1336 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1338 cir::YieldOp::create(
b, loc, res);
1341 return maybePromoteBoolResult(resOp.getResult(), resTy);
1344 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1345 return emitLoadOfLValue(e);
1348 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1349 return emitLoadOfLValue(e);
1353 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1354 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1358 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1362 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1364 "ScalarExprEmitter: objc string literal");
1367 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1368 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1371 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1373 "ScalarExprEmitter: objc array literal");
1376 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1378 "ScalarExprEmitter: objc dictionary literal");
1382 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1383 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: as type");
1387 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1388 return cgf.emitAtomicExpr(e).getValue();
1392LValue ScalarExprEmitter::emitCompoundAssignLValue(
1394 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1395 mlir::Value &result) {
1406 if (promotionTypeCR.
isNull())
1410 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1412 if (!promotionTypeRHS.
isNull())
1415 opInfo.rhs = Visit(e->
getRHS());
1417 opInfo.fullType = promotionTypeCR;
1418 opInfo.compType = opInfo.fullType;
1419 if (
const auto *vecType = dyn_cast_or_null<VectorType>(opInfo.fullType))
1420 opInfo.compType = vecType->getElementType();
1429 if (lhsTy->
getAs<AtomicType>()) {
1430 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1434 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1436 CIRGenFunction::SourceLocRAIIObject sourceloc{
1439 if (!promotionTypeLHS.
isNull())
1440 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1442 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1446 result = (this->*func)(opInfo);
1450 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1451 ScalarConversionOpts(cgf.
sanOpts));
1457 if (lhsLV.isBitField())
1468mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1472 cir::CastKind castOpKind;
1474 case CK_FloatingComplexToReal:
1475 castOpKind = cir::CastKind::float_complex_to_real;
1477 case CK_IntegralComplexToReal:
1478 castOpKind = cir::CastKind::int_complex_to_real;
1480 case CK_FloatingComplexToBoolean:
1481 castOpKind = cir::CastKind::float_complex_to_bool;
1483 case CK_IntegralComplexToBoolean:
1484 castOpKind = cir::CastKind::int_complex_to_bool;
1487 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1493mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1494 QualType promotionType) {
1496 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1497 switch (bo->getOpcode()) {
1498#define HANDLE_BINOP(OP) \
1500 return emit##OP(emitBinOps(bo, promotionType));
1509 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1510 switch (uo->getOpcode()) {
1513 return VisitRealImag(uo, promotionType);
1515 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Minus, promotionType);
1517 return emitUnaryPlusOrMinus(uo, cir::UnaryOpKind::Plus, promotionType);
1522 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1524 if (!promotionType.
isNull())
1525 return emitPromotedValue(result, promotionType);
1526 return emitUnPromotedValue(result, e->
getType());
1531mlir::Value ScalarExprEmitter::emitCompoundAssign(
1532 const CompoundAssignOperator *e,
1533 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1535 bool ignore = std::exchange(ignoreResultAssign,
false);
1537 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1548 if (!lhs.isVolatile())
1552 return emitLoadOfLValue(lhs, e->
getExprLoc());
1555mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1557 mlir::OpBuilder &builder = cgf.builder;
1559 auto scope = cir::ScopeOp::create(
1562 [&](mlir::OpBuilder &
b, mlir::Type &yieldTy, mlir::Location loc) {
1563 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1564 builder.getInsertionBlock()};
1565 mlir::Value scopeYieldVal = Visit(e->
getSubExpr());
1566 if (scopeYieldVal) {
1570 cir::YieldOp::create(builder, loc, scopeYieldVal);
1571 yieldTy = scopeYieldVal.getType();
1575 return scope.getNumResults() > 0 ? scope->getResult(0) :
nullptr;
1585#define COMPOUND_OP(Op) \
1586 case BO_##Op##Assign: \
1587 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1624 llvm_unreachable(
"Not valid compound assignment operators");
1626 llvm_unreachable(
"Unhandled compound assignment operator");
1631 bool ignoreResultAssign) {
1633 "Invalid scalar expression to emit");
1636 .Visit(
const_cast<Expr *
>(e));
1641 if (!promotionType.
isNull())
1656static std::optional<QualType>
1660 return std::nullopt;
1665 return std::nullopt;
1678 const BinOpInfo &op) {
1680 "Expected a unary or binary operator");
1684 if (!op.mayHaveIntegerOverflow())
1688 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1689 return !uo->canOverflow();
1694 std::optional<QualType> optionalLHSTy =
1699 std::optional<QualType> optionalRHSTy =
1709 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1716 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1717 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
1722 const BinOpInfo &op,
1723 bool isSubtraction) {
1728 mlir::Value pointer = op.lhs;
1729 Expr *pointerOperand =
expr->getLHS();
1730 mlir::Value
index = op.rhs;
1731 Expr *indexOperand =
expr->getRHS();
1737 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
1738 std::swap(pointer,
index);
1739 std::swap(pointerOperand, indexOperand);
1741 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
1742 "Need a pointer operand");
1743 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
1778 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
1789 cgf.
cgm.
errorNYI(
"void* or function pointer arithmetic");
1794 return cir::PtrStrideOp::create(cgf.
getBuilder(),
1796 pointer.getType(), pointer,
index);
1799mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
1800 const mlir::Location loc = cgf.
getLoc(ops.loc);
1802 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1803 case LangOptions::SOB_Defined:
1804 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1805 return builder.createMul(loc, ops.lhs, ops.rhs);
1807 case LangOptions::SOB_Undefined:
1808 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1809 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1811 case LangOptions::SOB_Trapping:
1813 return builder.createNSWMul(loc, ops.lhs, ops.rhs);
1823 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1825 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1827 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1829 return builder.createFMul(loc, ops.lhs, ops.rhs);
1832 if (ops.isFixedPointOp()) {
1838 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1839 cgf.
convertType(ops.fullType), cir::BinOpKind::Mul,
1842mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
1843 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1844 cgf.
convertType(ops.fullType), cir::BinOpKind::Div,
1847mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
1848 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1849 cgf.
convertType(ops.fullType), cir::BinOpKind::Rem,
1853mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
1854 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
1855 mlir::isa<cir::PointerType>(ops.rhs.getType()))
1858 const mlir::Location loc = cgf.
getLoc(ops.loc);
1860 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1861 case LangOptions::SOB_Defined:
1862 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1863 return builder.createAdd(loc, ops.lhs, ops.rhs);
1865 case LangOptions::SOB_Undefined:
1866 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1867 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1869 case LangOptions::SOB_Trapping:
1871 return builder.createNSWAdd(loc, ops.lhs, ops.rhs);
1882 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1884 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1886 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1888 return builder.createFAdd(loc, ops.lhs, ops.rhs);
1891 if (ops.isFixedPointOp()) {
1897 return cir::BinOp::create(builder, loc, cgf.
convertType(ops.fullType),
1898 cir::BinOpKind::Add, ops.lhs, ops.rhs);
1901mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
1902 const mlir::Location loc = cgf.
getLoc(ops.loc);
1904 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
1906 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
1907 case LangOptions::SOB_Defined: {
1908 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1909 return builder.createSub(loc, ops.lhs, ops.rhs);
1912 case LangOptions::SOB_Undefined:
1913 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
1914 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1916 case LangOptions::SOB_Trapping:
1918 return builder.createNSWSub(loc, ops.lhs, ops.rhs);
1930 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
1932 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
1934 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
1936 return builder.createFSub(loc, ops.lhs, ops.rhs);
1939 if (ops.isFixedPointOp()) {
1945 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
1947 cir::BinOpKind::Sub, ops.lhs, ops.rhs);
1952 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
1964 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
1968mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
1970 if (ops.isFixedPointOp()) {
1980 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
1984 bool sanitizeUnsignedBase =
1985 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
1987 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
1988 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
1993 else if ((sanitizeBase || sanitizeExponent) &&
1994 mlir::isa<cir::IntType>(ops.lhs.getType()))
1997 return builder.createShiftLeft(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2000mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2002 if (ops.isFixedPointOp()) {
2015 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2016 mlir::isa<cir::IntType>(ops.lhs.getType()))
2021 return builder.createShiftRight(cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2024mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2025 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2026 cgf.
convertType(ops.fullType), cir::BinOpKind::And,
2029mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2030 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2031 cgf.
convertType(ops.fullType), cir::BinOpKind::Xor,
2034mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2035 return cir::BinOp::create(builder, cgf.
getLoc(ops.loc),
2036 cgf.
convertType(ops.fullType), cir::BinOpKind::Or,
2044mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2046 QualType destTy = ce->
getType();
2051 ignoreResultAssign =
false;
2054 case clang::CK_Dependent:
2055 llvm_unreachable(
"dependent cast kind in CIR gen!");
2056 case clang::CK_BuiltinFnToFnPtr:
2057 llvm_unreachable(
"builtin functions are handled elsewhere");
2059 case CK_CPointerToObjCPointerCast:
2060 case CK_BlockPointerToObjCPointerCast:
2061 case CK_AnyPointerToBlockPointerCast:
2063 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2068 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2070 "sanitizer support");
2074 "strict vtable pointers");
2100 case CK_AddressSpaceConversion: {
2101 Expr::EvalResult result;
2118 cir::TargetAddressSpaceAttr subExprAS;
2123 "non-target address space conversion");
2127 cgf, Visit(subExpr), subExprAS, convertType(destTy));
2130 case CK_AtomicToNonAtomic: {
2136 case CK_NonAtomicToAtomic:
2137 case CK_UserDefinedConversion:
2138 return Visit(
const_cast<Expr *
>(subExpr));
2140 auto v = Visit(
const_cast<Expr *
>(subExpr));
2146 if (t != v.getType())
2151 case CK_IntegralToPointer: {
2153 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2160 mlir::Value middleVal = builder.createCast(
2162 : cir::CastKind::integral,
2167 "IntegralToPointer: strict vtable pointers");
2171 return builder.createIntToPtr(middleVal, destCIRTy);
2174 case CK_BaseToDerived: {
2176 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2188 case CK_UncheckedDerivedToBase:
2189 case CK_DerivedToBase: {
2200 case CK_ArrayToPointerDecay:
2203 case CK_NullToPointer: {
2213 case CK_LValueToRValue:
2215 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2216 return Visit(
const_cast<Expr *
>(subExpr));
2218 case CK_IntegralCast: {
2219 ScalarConversionOpts opts;
2220 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2221 if (!ice->isPartOfExplicitCast())
2222 opts = ScalarConversionOpts(cgf.
sanOpts);
2224 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2228 case CK_FloatingComplexToReal:
2229 case CK_IntegralComplexToReal:
2230 case CK_FloatingComplexToBoolean:
2231 case CK_IntegralComplexToBoolean: {
2237 case CK_FloatingRealToComplex:
2238 case CK_FloatingComplexCast:
2239 case CK_IntegralRealToComplex:
2240 case CK_IntegralComplexCast:
2241 case CK_IntegralComplexToFloatingComplex:
2242 case CK_FloatingComplexToIntegralComplex:
2243 llvm_unreachable(
"scalar cast to non-scalar value");
2245 case CK_PointerToIntegral: {
2246 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2249 "strict vtable pointers");
2250 return builder.createPtrToInt(Visit(subExpr), cgf.
convertType(destTy));
2256 case CK_IntegralToFloating:
2257 case CK_FloatingToIntegral:
2258 case CK_FloatingCast:
2259 case CK_FixedPointToFloating:
2260 case CK_FloatingToFixedPoint: {
2261 if (kind == CK_FixedPointToFloating || kind == CK_FloatingToFixedPoint) {
2263 "fixed point casts");
2267 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2271 case CK_IntegralToBoolean:
2272 return emitIntToBoolConversion(Visit(subExpr),
2275 case CK_PointerToBoolean:
2276 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2277 case CK_FloatingToBoolean:
2278 return emitFloatToBoolConversion(Visit(subExpr),
2280 case CK_MemberPointerToBoolean: {
2281 mlir::Value memPtr = Visit(subExpr);
2283 cir::CastKind::member_ptr_to_bool, memPtr,
2287 case CK_VectorSplat: {
2289 assert(destTy->
isVectorType() &&
"CK_VectorSplat to non-vector type");
2290 return cir::VecSplatOp::create(builder,
2294 case CK_FunctionToPointerDecay:
2304mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2306 return emitLoadOfLValue(e);
2313mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2318 Expr::EvalResult result;
2320 llvm::APSInt value = result.
Val.
getInt();
2324 return emitLoadOfLValue(e);
2327mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
2328 const unsigned numInitElements = e->
getNumInits();
2330 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
2331 assert((ignore ==
false ||
2333 "init list ignored");
2341 const auto vectorType =
2344 SmallVector<mlir::Value, 16> elements;
2345 for (Expr *init : e->
inits()) {
2346 elements.push_back(Visit(init));
2350 if (numInitElements < vectorType.getSize()) {
2353 std::fill_n(std::back_inserter(elements),
2354 vectorType.getSize() - numInitElements, zeroValue);
2357 return cir::VecCreateOp::create(cgf.
getBuilder(),
2363 if (numInitElements == 0)
2374 "Invalid scalar expression to emit");
2376 .emitScalarConversion(src, srcTy, dstTy, loc);
2384 "Invalid complex -> scalar conversion");
2389 ? cir::CastKind::float_complex_to_bool
2390 : cir::CastKind::int_complex_to_bool;
2395 ? cir::CastKind::float_complex_to_real
2396 : cir::CastKind::int_complex_to_real;
2402mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
2409 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
2411 mlir::Value zeroVec = builder.getNullValue(operVecTy, loc);
2412 return cir::VecCmpOp::create(builder, loc, exprVecTy, cir::CmpOpKind::eq,
2420 boolVal = builder.createNot(boolVal);
2426mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
2431 llvm::APSInt value = evalResult.
Val.
getInt();
2437 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
2441mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
2443 mlir::Value result = VisitRealImag(e, promotionTy);
2444 if (result && !promotionTy.
isNull())
2445 result = emitUnPromotedValue(result, e->
getType());
2449mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
2451 mlir::Value result = VisitRealImag(e, promotionTy);
2452 if (result && !promotionTy.
isNull())
2453 result = emitUnPromotedValue(result, e->
getType());
2457mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
2458 QualType promotionTy) {
2459 assert(e->
getOpcode() == clang::UO_Real ||
2461 "Invalid UnaryOp kind for ComplexType Real or Imag");
2478 ? builder.createComplexReal(loc, complex)
2479 : builder.createComplexImag(loc, complex);
2483 mlir::Value operand = promotionTy.
isNull()
2485 : cgf.emitPromotedScalarExpr(op, promotionTy);
2486 return builder.createComplexReal(loc, operand);
2491 mlir::Value operand;
2494 operand = cir::LoadOp::create(builder, loc, operand);
2495 }
else if (!promotionTy.
isNull()) {
2500 return builder.createComplexImag(loc, operand);
2505mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
2506 const UnaryExprOrTypeTraitExpr *e) {
2510 kind == UETT_SizeOf || kind == UETT_DataSizeOf || kind == UETT_CountOf) {
2511 if (
const VariableArrayType *vat =
2516 bool evaluateExtent =
true;
2517 if (kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
2519 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
2522 if (evaluateExtent) {
2533 if (kind == UETT_CountOf)
2538 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
2539 mlir::Value numElts = vlaSize.
numElts;
2543 if (!eltSize.
isOne()) {
2545 mlir::Value eltSizeValue =
2546 builder.getConstAPInt(numElts.getLoc(), numElts.getType(),
2548 return builder.createMul(loc, eltSizeValue, numElts,
2555 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
2557 e->
getSourceRange(),
"sizeof operator for OpenMpRequiredSimdAlign",
2559 return builder.getConstant(
2561 llvm::APSInt(llvm::APInt(64, 1),
true)));
2564 return builder.getConstant(
2586mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
2587 const AbstractConditionalOperator *e) {
2590 ignoreResultAssign =
false;
2593 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
2595 Expr *condExpr = e->
getCond();
2603 Expr *live = lhsExpr, *dead = rhsExpr;
2605 std::swap(live, dead);
2611 mlir::Value result = Visit(live);
2618 loc, cir::PoisonAttr::get(builder.getContext(),
2626 QualType condType = condExpr->
getType();
2639 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
2643 mlir::Value condValue = Visit(condExpr);
2644 mlir::Value lhsValue = Visit(lhsExpr);
2645 mlir::Value rhsValue = Visit(rhsExpr);
2646 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
2655 bool lhsIsVoid =
false;
2659 mlir::Value lhs = Visit(lhsExpr);
2665 mlir::Value rhs = Visit(rhsExpr);
2667 assert(!rhs &&
"lhs and rhs types must match");
2675 CIRGenFunction::ConditionalEvaluation eval(cgf);
2676 SmallVector<mlir::OpBuilder::InsertPoint, 2> insertPoints{};
2677 mlir::Type yieldTy{};
2679 auto emitBranch = [&](mlir::OpBuilder &
b, mlir::Location loc, Expr *
expr) {
2680 CIRGenFunction::LexicalScope lexScope{cgf, loc,
b.getInsertionBlock()};
2684 eval.beginEvaluation();
2685 mlir::Value branch = Visit(
expr);
2686 eval.endEvaluation();
2689 yieldTy = branch.getType();
2690 cir::YieldOp::create(
b, loc, branch);
2694 insertPoints.push_back(
b.saveInsertionPoint());
2698 mlir::Value result = cir::TernaryOp::create(
2699 builder, loc, condV,
2701 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2702 emitBranch(
b, loc, lhsExpr);
2705 [&](mlir::OpBuilder &
b, mlir::Location loc) {
2706 emitBranch(
b, loc, rhsExpr);
2710 if (!insertPoints.empty()) {
2716 for (mlir::OpBuilder::InsertPoint &toInsert : insertPoints) {
2717 mlir::OpBuilder::InsertionGuard guard(builder);
2718 builder.restoreInsertionPoint(toInsert);
2721 if (mlir::isa<cir::VoidType>(yieldTy)) {
2722 cir::YieldOp::create(builder, loc);
2725 cir::YieldOp::create(builder, loc, op0);
2735 cir::UnaryOpKind kind,
2738 .emitScalarPrePostIncDec(e, lv, kind, isPre);
static bool mustVisitNullValue(const Expr *e)
static bool isWidenedIntegerOp(const ASTContext &astContext, const Expr *e)
Check if e is a widened promoted integer.
static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, const BinOpInfo &op, bool isSubtraction)
Emit pointer + index arithmetic.
static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e, CIRGenFunction &cgf)
Return true if the specified expression is cheap enough and side-effect-free enough to evaluate uncon...
static bool canElideOverflowCheck(const ASTContext &astContext, const BinOpInfo &op)
Check if we can skip the overflow check for Op.
static std::optional< QualType > getUnwidenedIntegerType(const ASTContext &astContext, const Expr *e)
If e is a widened promoted integer, get its base (unpromoted) type.
__device__ __2f16 float __ockl_bool s
cir::ConstantOp getBool(bool state, mlir::Location loc)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
bool isNullPointer() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Expr * getCond() const
getCond - Return the expression representing the condition for the ?
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
LabelDecl * getLabel() const
uint64_t getValue() const
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, const Expr *LHS, const Expr *RHS)
Return true if a binary operator using the specified opcode and operands would match the 'p = (i8*)nu...
BinaryOperatorKind Opcode
mlir::Value getPointer() const
mlir::Value createNeg(mlir::Value value)
void forceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv, cir::UnaryOpKind kind, bool isPre)
friend class ::ScalarExprEmitter
mlir::Value emitScalarConversion(mlir::Value src, clang::QualType srcType, clang::QualType dstType, clang::SourceLocation loc)
Emit a conversion from the specified type to the specified destination type, both of which are CIR sc...
Address getAddressOfDerivedClass(mlir::Location loc, Address baseAddr, const CXXRecordDecl *derived, llvm::iterator_range< CastExpr::path_const_iterator > path, bool nullCheckValue)
clang::SanitizerSet sanOpts
Sanitizers enabled for this function.
mlir::Value createDummyValue(mlir::Location loc, clang::QualType qt)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::MLIRContext & getMLIRContext()
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
Address emitArrayToPointerDecay(const Expr *e, LValueBaseInfo *baseInfo=nullptr)
LexicalScope * curLexScope
mlir::Value emitStoreThroughBitfieldLValue(RValue src, LValue dstresult)
clang::ASTContext & getContext() const
void emitNullabilityCheck(LValue lhs, mlir::Value rhs, clang::SourceLocation loc)
Given an assignment *lhs = rhs, emit a test that checks if rhs is nonnull, if 1LHS is marked _Nonnull...
void emitStoreThroughLValue(RValue src, LValue dst, bool isInit=false)
Store the specified rvalue into the specified lvalue, where both are guaranteed to the have the same ...
void emitIgnoredExpr(const clang::Expr *e)
Emit code to compute the specified expression, ignoring the result.
mlir::Value emitDynamicCast(Address thisAddr, const CXXDynamicCastExpr *dce)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
mlir::IntegerAttr getSize(CharUnits size)
const cir::CIRDataLayout getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
const TargetCIRGenInfo & getTargetCIRGenInfo()
mlir::Value emitNullConstant(QualType t, mlir::Location loc)
Return the result of value-initializing the given type, i.e.
mlir::Value getPointer() const
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
virtual mlir::Value performAddrSpaceCast(CIRGenFunction &cgf, mlir::Value v, cir::TargetAddressSpaceAttr srcAddr, mlir::Type destTy, bool isNonNull=false) const
Perform address space cast of an expression of pointer type.
Expr * getExpr()
Get the initialization expression that will be used.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
static const char * getCastKindName(CastKind CK)
bool isOne() const
isOne - Test whether the quantity equals one.
unsigned getValue() const
Expr * getChosenSubExpr() const
getChosenSubExpr - Return the subexpression chosen according to the condition.
Complex values, per C99 6.2.5p11.
CompoundAssignOperator - For compound assignments (e.g.
QualType getComputationLHSType() const
QualType getComputationResultType() const
SourceLocation getExprLoc() const LLVM_READONLY
bool isSatisfied() const
Whether or not the concept with the given arguments was satisfied when the expression was created.
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
ChildElementIter< false > begin()
size_t getDataElementCount() const
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
llvm::APFloat getValue() const
const Expr * getSubExpr() const
Expr * getResultExpr()
Return the result expression of this controlling expression.
unsigned getNumInits() const
bool hadArrayRangeDesignator() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits()
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
A pointer to member type per C++ 8.3.3 - Pointers to members.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
SourceLocation getExprLoc() const LLVM_READONLY
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getCanonicalType() const
bool UseExcessPrecision(const ASTContext &Ctx)
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
bool isSatisfied() const
Whether or not the requires clause is satisfied.
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
SourceLocation getLocation() const
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
Expr * getReplacement() const
bool getBoolValue() const
bool isStoredAsBoolean() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isConstantMatrixType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isExtVectorType() const
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() const
bool 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.