24#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
25#include "mlir/IR/Location.h"
26#include "mlir/IR/Value.h"
49 bool isDivRemOp()
const {
50 return opcode == BO_Div || opcode == BO_Rem || opcode == BO_DivAssign ||
51 opcode == BO_RemAssign;
55 bool mayHaveIntegerOverflow()
const {
57 auto lhsci = lhs.getDefiningOp<cir::ConstantOp>();
58 auto rhsci = rhs.getDefiningOp<cir::ConstantOp>();
70 bool isFixedPointOp()
const {
73 if (
const auto *binOp = llvm::dyn_cast<BinaryOperator>(e)) {
74 QualType lhstype = binOp->getLHS()->getType();
75 QualType rhstype = binOp->getRHS()->getType();
78 if (
const auto *unop = llvm::dyn_cast<UnaryOperator>(e))
79 return unop->getSubExpr()->getType()->isFixedPointType();
84class ScalarExprEmitter :
public StmtVisitor<ScalarExprEmitter, mlir::Value> {
86 CIRGenBuilderTy &builder;
90 bool ignoreResultAssign;
93 ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
94 bool ignoreResultAssign =
false)
95 : cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}
100 mlir::Type convertType(QualType ty) {
return cgf.convertType(ty); }
102 mlir::Value emitComplexToScalarConversion(mlir::Location loc,
106 mlir::Value emitNullValue(QualType ty, mlir::Location loc) {
107 return cgf.cgm.emitNullConstant(ty, loc);
110 mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
111 return builder.createFloatingCast(result, cgf.convertType(promotionType));
114 mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
115 return builder.createFloatingCast(result, cgf.convertType(exprType));
118 mlir::Value emitPromoted(
const Expr *e, QualType promotionType);
120 mlir::Value maybePromoteBoolResult(mlir::Value value,
121 mlir::Type dstTy)
const {
122 if (mlir::isa<cir::IntType>(dstTy))
123 return builder.createBoolToInt(value, dstTy);
124 if (mlir::isa<cir::BoolType>(dstTy))
126 llvm_unreachable(
"Can only promote integer or boolean types");
133 mlir::Value Visit(Expr *e) {
134 return StmtVisitor<ScalarExprEmitter, mlir::Value>::Visit(e);
137 mlir::Value VisitStmt(Stmt *s) {
138 llvm_unreachable(
"Statement passed to ScalarExprEmitter");
141 mlir::Value VisitExpr(Expr *e) {
142 cgf.getCIRGenModule().errorNYI(
147 mlir::Value VisitConstantExpr(ConstantExpr *e) {
153 if (mlir::Attribute result = ConstantEmitter(cgf).tryEmitConstantExpr(e)) {
156 "ScalarExprEmitter: constant expr GL Value");
161 mlir::cast<mlir::TypedAttr>(result));
164 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: constant expr");
168 mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) {
172 mlir::Value VisitParenExpr(ParenExpr *pe) {
return Visit(pe->
getSubExpr()); }
174 mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) {
179 mlir::Value emitLoadOfLValue(
const Expr *e) {
180 LValue lv = cgf.emitLValue(e);
182 return cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
185 mlir::Value VisitCoawaitExpr(CoawaitExpr *s) {
186 return cgf.emitCoawaitExpr(*s).getValue();
189 mlir::Value VisitCoyieldExpr(CoyieldExpr *e) {
190 return cgf.emitCoyieldExpr(*e).getValue();
193 mlir::Value VisitUnaryCoawait(
const UnaryOperator *e) {
194 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: unary coawait");
198 mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc) {
199 return cgf.emitLoadOfLValue(lv, loc).getValue();
203 mlir::Value VisitDeclRefExpr(DeclRefExpr *e) {
204 if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
205 return cgf.emitScalarConstant(constant, e);
207 return emitLoadOfLValue(e);
210 mlir::Value VisitAddrLabelExpr(
const AddrLabelExpr *e) {
212 cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
216 return cir::BlockAddressOp::create(builder, cgf.getLoc(e->
getSourceRange()),
221 mlir::Value VisitIntegerLiteral(
const IntegerLiteral *e) {
223 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
227 mlir::Value VisitFixedPointLiteral(
const FixedPointLiteral *e) {
229 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
233 mlir::Value VisitFloatingLiteral(
const FloatingLiteral *e) {
235 assert(mlir::isa<cir::FPTypeInterface>(
type) &&
236 "expect floating-point type");
237 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
241 mlir::Value VisitCharacterLiteral(
const CharacterLiteral *e) {
242 mlir::Type ty = cgf.convertType(e->
getType());
245 auto intTy = mlir::cast<cir::IntTypeInterface>(ty);
246 llvm::APInt apValue(intTy.getWidth(), e->
getValue(),
248 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
249 cir::IntAttr::get(ty, apValue));
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 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()),
273 mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) {
274 return cgf.emitPseudoObjectRValue(e).getValue();
276 mlir::Value VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e);
277 mlir::Value VisitEmbedExpr(EmbedExpr *e) {
279 auto it = e->
begin();
280 llvm::APInt value = (*it)->getValue();
281 return builder.getConstInt(cgf.getLoc(e->
getExprLoc()), value,
284 mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) {
286 return emitLoadOfLValue(cgf.getOrCreateOpaqueLValueMapping(e),
290 return cgf.getOrCreateOpaqueRValueMapping(e).getValue();
293 mlir::Value VisitObjCSelectorExpr(ObjCSelectorExpr *e) {
294 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc selector");
297 mlir::Value VisitObjCProtocolExpr(ObjCProtocolExpr *e) {
298 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc protocol");
301 mlir::Value VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {
302 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc ivar ref");
305 mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) {
306 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc message");
309 mlir::Value VisitObjCIsaExpr(ObjCIsaExpr *e) {
310 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc isa");
313 mlir::Value VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *e) {
315 "ScalarExprEmitter: objc availability check");
319 mlir::Value VisitMatrixSubscriptExpr(MatrixSubscriptExpr *e) {
320 mlir::Value rowIdx = cgf.emitScalarExpr(e->
getRowIdx());
321 mlir::Value columnIdx = cgf.emitScalarExpr(e->
getColumnIdx());
322 mlir::Value matrix = Visit(e->
getBase());
325 return builder.createMatrixExtract(loc, matrix, rowIdx, columnIdx);
328 mlir::Value VisitMatrixSingleSubscriptExpr(MatrixSingleSubscriptExpr *e) {
329 mlir::Value rowIdx = cgf.emitScalarExpr(e->
getRowIdx());
331 mlir::Value matrix = Visit(e->
getBase());
333 return builder.createMatrixExtractRow(loc, matrix, rowIdx);
336 mlir::Value VisitCastExpr(
CastExpr *e);
337 mlir::Value VisitCallExpr(
const CallExpr *e);
339 mlir::Value VisitStmtExpr(StmtExpr *e) {
340 CIRGenFunction::StmtExprEvaluation eval(cgf);
348 (void)cgf.emitCompoundStmt(*e->
getSubStmt(), &retAlloca);
350 return cgf.emitLoadOfScalar(cgf.makeAddrLValue(retAlloca, e->
getType()),
354 mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
355 ignoreResultAssign =
false;
361 const mlir::Value vecValue = Visit(e->
getBase());
362 const mlir::Value indexValue = Visit(e->
getIdx());
363 return cir::VecExtractOp::create(cgf.getBuilder(), loc, vecValue,
367 return emitLoadOfLValue(e);
370 mlir::Value VisitShuffleVectorExpr(ShuffleVectorExpr *e) {
373 mlir::Value inputVec = Visit(e->
getExpr(0));
374 mlir::Value indexVec = Visit(e->
getExpr(1));
375 return cir::VecShuffleDynamicOp::create(cgf.getBuilder(),
380 mlir::Value vec1 = Visit(e->
getExpr(0));
381 mlir::Value vec2 = Visit(e->
getExpr(1));
386 SmallVector<mlir::Attribute, 8> indices;
389 cir::IntAttr::get(cgf.getBuilder().getSInt64Ty(),
395 return cir::VecShuffleOp::create(cgf.getBuilder(),
397 cgf.convertType(e->
getType()), vec1, vec2,
398 cgf.getBuilder().getArrayAttr(indices));
401 mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
404 return emitScalarConversion(Visit(e->
getSrcExpr()),
409 mlir::Value VisitExtVectorElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
411 mlir::Value VisitMatrixElementExpr(Expr *e) {
return emitLoadOfLValue(e); }
413 mlir::Value VisitMemberExpr(MemberExpr *e);
415 mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {
416 return emitLoadOfLValue(e);
419 mlir::Value VisitInitListExpr(InitListExpr *e);
420 mlir::Value emitVectorInitWithSubvectors(mlir::Location loc,
421 cir::VectorType vectorType,
422 ArrayRef<mlir::Value>
inits);
424 mlir::Value VisitArrayInitIndexExpr(ArrayInitIndexExpr *e) {
425 assert(cgf.getArrayInitIndex() &&
426 "ArrayInitIndexExpr not inside an ArrayInitLoopExpr?");
427 return cgf.getArrayInitIndex();
430 mlir::Value VisitImplicitValueInitExpr(
const ImplicitValueInitExpr *e) {
434 mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) {
435 return VisitCastExpr(e);
438 mlir::Value VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *e) {
439 return cgf.cgm.emitNullConstant(e->
getType(),
444 mlir::Value emitPointerToBoolConversion(mlir::Value v, QualType qt) {
447 return cgf.getBuilder().createPtrToBoolCast(v);
450 mlir::Value emitFloatToBoolConversion(mlir::Value src, mlir::Location loc) {
451 cir::BoolType boolTy = builder.getBoolTy();
452 return cir::CastOp::create(builder, loc, boolTy,
453 cir::CastKind::float_to_bool, src);
456 mlir::Value emitIntToBoolConversion(mlir::Value srcVal, mlir::Location loc) {
460 if (mlir::isa<cir::BoolType>(srcVal.getType()))
468 cir::BoolType boolTy = builder.getBoolTy();
469 return cir::CastOp::create(builder, loc, boolTy, cir::CastKind::int_to_bool,
475 mlir::Value emitConversionToBool(mlir::Value src, QualType srcType,
476 mlir::Location loc) {
477 assert(srcType.
isCanonical() &&
"EmitScalarConversion strips typedefs");
480 return emitFloatToBoolConversion(src, loc);
482 if (llvm::isa<MemberPointerType>(srcType)) {
483 cgf.getCIRGenModule().errorNYI(loc,
"member pointer to bool conversion");
484 return builder.getFalse(loc);
488 return emitIntToBoolConversion(src, loc);
490 assert(::mlir::isa<cir::PointerType>(src.getType()));
491 return emitPointerToBoolConversion(src, srcType);
496 struct ScalarConversionOpts {
497 bool treatBooleanAsSigned;
498 bool emitImplicitIntegerTruncationChecks;
499 bool emitImplicitIntegerSignChangeChecks;
501 ScalarConversionOpts()
502 : treatBooleanAsSigned(
false),
503 emitImplicitIntegerTruncationChecks(
false),
504 emitImplicitIntegerSignChangeChecks(
false) {}
506 ScalarConversionOpts(clang::SanitizerSet sanOpts)
507 : treatBooleanAsSigned(
false),
508 emitImplicitIntegerTruncationChecks(
509 sanOpts.hasOneOf(SanitizerKind::ImplicitIntegerTruncation)),
510 emitImplicitIntegerSignChangeChecks(
511 sanOpts.
has(SanitizerKind::ImplicitIntegerSignChange)) {}
518 mlir::Value emitScalarCast(mlir::Value src, QualType srcType,
519 QualType dstType, mlir::Type srcTy,
520 mlir::Type dstTy, ScalarConversionOpts opts) {
522 "Internal error: matrix types not handled by this function.");
523 assert(!(mlir::isa<mlir::IntegerType>(srcTy) ||
524 mlir::isa<mlir::IntegerType>(dstTy)) &&
525 "Obsolete code. Don't use mlir::IntegerType with CIR.");
527 mlir::Type fullDstTy = dstTy;
528 if (mlir::isa<cir::VectorType>(srcTy) &&
529 mlir::isa<cir::VectorType>(dstTy)) {
531 srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
532 dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
535 std::optional<cir::CastKind> castKind;
539 cir::FenvAttr fenvAttr;
541 if (mlir::isa<cir::BoolType>(srcTy)) {
542 if (opts.treatBooleanAsSigned)
543 cgf.getCIRGenModule().errorNYI(
"signed bool");
544 if (cgf.getBuilder().isInt(dstTy)) {
545 castKind = cir::CastKind::bool_to_int;
546 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
547 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
548 castKind = cir::CastKind::bool_to_float;
550 llvm_unreachable(
"Internal error: Cast to unexpected type");
552 }
else if (cgf.getBuilder().isInt(srcTy)) {
553 if (cgf.getBuilder().isInt(dstTy)) {
554 castKind = cir::CastKind::integral;
555 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
556 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
557 castKind = cir::CastKind::int_to_float;
558 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
559 castKind = cir::CastKind::int_to_bool;
561 llvm_unreachable(
"Internal error: Cast to unexpected type");
563 }
else if (mlir::isa<cir::FPTypeInterface>(srcTy)) {
564 fenvAttr = cgf.getBuilder().getConstrainedFPAttr();
565 if (cgf.getBuilder().isInt(dstTy)) {
569 if (!cgf.cgm.getCodeGenOpts().StrictFloatCastOverflow)
570 cgf.getCIRGenModule().errorNYI(
"strict float cast overflow");
571 castKind = cir::CastKind::float_to_int;
572 }
else if (mlir::isa<cir::FPTypeInterface>(dstTy)) {
574 return builder.createFloatingCast(src, fullDstTy);
575 }
else if (mlir::isa<cir::BoolType>(dstTy)) {
576 castKind = cir::CastKind::float_to_bool;
578 llvm_unreachable(
"Internal error: Cast to unexpected type");
581 llvm_unreachable(
"Internal error: Cast from unexpected type");
584 assert(castKind.has_value() &&
"Internal error: CastKind not set.");
585 return builder.createOrFold<cir::CastOp>(src.getLoc(), fullDstTy, *castKind,
590 VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {
594 mlir::Value VisitVAArgExpr(VAArgExpr *ve) {
599 "variably modified types in varargs");
602 return cgf.emitVAArg(ve);
605 mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {
609 mlir::Value VisitUnaryExprOrTypeTraitExpr(
const UnaryExprOrTypeTraitExpr *e);
611 VisitAbstractConditionalOperator(
const AbstractConditionalOperator *e);
614 mlir::Value VisitUnaryPrePostIncDec(
const UnaryOperator *e) {
616 return emitScalarPrePostIncDec(e, lv);
618 mlir::Value VisitUnaryPostDec(
const UnaryOperator *e) {
619 return VisitUnaryPrePostIncDec(e);
621 mlir::Value VisitUnaryPostInc(
const UnaryOperator *e) {
622 return VisitUnaryPrePostIncDec(e);
624 mlir::Value VisitUnaryPreDec(
const UnaryOperator *e) {
625 return VisitUnaryPrePostIncDec(e);
627 mlir::Value VisitUnaryPreInc(
const UnaryOperator *e) {
628 return VisitUnaryPrePostIncDec(e);
631 mlir::Value emitFixedPointIncDec(
const UnaryOperator *e, mlir::Value value,
633 mlir::Value emitScalarPrePostIncDec(
const UnaryOperator *e, LValue lv) {
641 if (
const AtomicType *atomicTy =
type->getAs<AtomicType>()) {
642 QualType valType = atomicTy->getValueType();
652 cir::IntType intTy = builder.getBoolMemoryTy();
653 mlir::Value one = builder.getConstInt(loc, intTy, 1);
654 Address intAddr = lv.getAddress().withElementType(builder, intTy);
658 cir::StoreOp store = builder.createStore(loc, one, intAddr);
659 store.setMemOrder(cir::MemOrder::SequentiallyConsistent);
660 if (lv.isVolatileQualified())
661 store.setIsVolatile(
true);
662 return builder.getTrue(loc);
665 auto xchg = cir::AtomicXchgOp::create(
667 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
668 lv.isVolatileQualified());
669 return builder.createCast(cir::CastKind::int_to_bool, xchg.getResult(),
670 builder.getBoolTy());
678 cgf.sanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) &&
679 cgf.getLangOpts().getSignedOverflowBehavior() !=
680 LangOptions::SOB_Trapping) {
681 mlir::Type intTy = cgf.convertType(valType);
682 mlir::Value one = builder.getConstInt(loc, intTy, 1);
683 cir::AtomicFetchKind
kind =
684 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
685 auto rmw = cir::AtomicFetchOp::create(
686 builder, loc, lv.getPointer(), one,
kind,
687 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
688 lv.isVolatileQualified(),
true);
689 mlir::Value oldVal = rmw->getResult(0);
691 return isPre ? emitIntIncOrDec(e, oldVal) : oldVal;
697 mlir::Type fpTy = cgf.convertType(valType);
698 auto fpType = mlir::cast<cir::FPTypeInterface>(fpTy);
700 if (llvm::has_single_bit(fpType.getWidth())) {
701 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
702 mlir::Value amt = builder.getConstFP(
703 loc, fpTy, llvm::APFloat(fpType.getFloatSemantics(), 1));
704 cir::AtomicFetchKind
kind =
705 isInc ? cir::AtomicFetchKind::Add : cir::AtomicFetchKind::Sub;
706 auto rmw = cir::AtomicFetchOp::create(
707 builder, loc, lv.getPointer(), amt,
kind,
708 cir::MemOrder::SequentiallyConsistent, cir::SyncScopeKind::System,
709 lv.isVolatileQualified(),
true);
710 mlir::Value oldVal = rmw->getResult(0);
712 return isInc ? builder.createFAdd(loc, oldVal, amt)
713 : builder.createFSub(loc, oldVal, amt);
717 "Atomic inc/dec of non-power-of-2 float");
723 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
726 value = cgf.emitLoadOfLValue(lv, e->
getExprLoc()).getValue();
740 value = builder.getTrue(cgf.getLoc(e->
getExprLoc()));
741 }
else if (
type->isIntegerType()) {
742 QualType promotedType;
743 [[maybe_unused]]
bool canPerformLossyDemotionCheck =
false;
744 if (cgf.getContext().isPromotableIntegerType(
type)) {
745 promotedType = cgf.getContext().getPromotedIntegerType(
type);
746 assert(promotedType !=
type &&
"Shouldn't promote to the same type.");
747 canPerformLossyDemotionCheck =
true;
748 canPerformLossyDemotionCheck &=
749 cgf.getContext().getCanonicalType(
type) !=
750 cgf.getContext().getCanonicalType(promotedType);
751 canPerformLossyDemotionCheck &=
758 (!canPerformLossyDemotionCheck ||
759 type->isSignedIntegerOrEnumerationType() ||
761 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth() ==
762 mlir::cast<cir::IntType>(cgf.convertType(
type)).getWidth()) &&
763 "The following check expects that if we do promotion to different "
764 "underlying canonical type, at least one of the types (either "
765 "base or promoted) will be signed, or the bitwidths will match.");
770 value = emitIncDecConsiderOverflowBehavior(e, value);
773 value = emitIntIncOrDec(e, input,
false);
775 }
else if (
const PointerType *ptr =
type->getAs<PointerType>()) {
776 QualType
type = ptr->getPointeeType();
777 if (
const VariableArrayType *vla =
778 cgf.getContext().getAsVariableArrayType(
type)) {
780 mlir::Value numElts = cgf.getVLASize(vla).numElts;
782 numElts = cgf.getBuilder().createNeg(loc, numElts,
true);
784 value = cgf.getBuilder().createPtrStride(loc, value, numElts);
789 mlir::Value amt = builder.getSInt32(amount, loc);
791 value = builder.createPtrStride(loc, value, amt);
793 }
else if (
type->isVectorType()) {
794 if (
type->hasIntegerRepresentation()) {
795 value = emitIntIncOrDec(e, input,
false);
797 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
798 value = emitFloatIncOrDec(e, input);
800 }
else if (
type->isRealFloatingType()) {
801 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
802 value = emitFloatIncOrDec(e, input);
803 }
else if (
type->isFixedPointType()) {
804 value = emitFixedPointIncDec(e, value,
type);
806 assert(
type->castAs<ObjCObjectPointerType>());
807 cgf.cgm.errorNYI(e->
getSourceRange(),
"Unary inc/dec ObjectiveC pointer");
811 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
815 value = cgf.emitStoreThroughBitfieldLValue(
RValue::get(value), lv);
817 cgf.emitStoreThroughLValue(
RValue::get(value), lv);
821 return e->
isPrefix() ? value : input;
824 mlir::Value emitIncDecConsiderOverflowBehavior(
const UnaryOperator *e,
826 switch (cgf.getLangOpts().getSignedOverflowBehavior()) {
827 case LangOptions::SOB_Defined:
828 return emitIntIncOrDec(e, inVal,
false);
829 case LangOptions::SOB_Undefined:
831 return emitIntIncOrDec(e, inVal,
true);
832 case LangOptions::SOB_Trapping:
834 return emitIntIncOrDec(e, inVal,
true);
835 cgf.cgm.errorNYI(e->
getSourceRange(),
"inc/def overflow SOB_Trapping");
838 llvm_unreachable(
"Unexpected signed overflow behavior kind");
841 mlir::Value VisitUnaryAddrOf(
const UnaryOperator *e) {
842 if (llvm::isa<MemberPointerType>(e->
getType()))
843 return cgf.cgm.emitMemberPointerConstant(e);
845 return cgf.emitLValue(e->
getSubExpr()).getPointer();
848 mlir::Value VisitUnaryDeref(
const UnaryOperator *e) {
851 return emitLoadOfLValue(e);
854 mlir::Value VisitUnaryPlus(
const UnaryOperator *e) {
856 mlir::Value result = VisitUnaryPlus(e, promotionType);
857 if (result && !promotionType.
isNull())
858 return emitUnPromotedValue(result, e->
getType());
862 mlir::Value VisitUnaryPlus(
const UnaryOperator *e, QualType promotionType) {
863 ignoreResultAssign =
false;
864 if (!promotionType.
isNull())
865 return cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
869 mlir::Value VisitUnaryMinus(
const UnaryOperator *e) {
871 mlir::Value result = VisitUnaryMinus(e, promotionType);
872 if (result && !promotionType.
isNull())
873 return emitUnPromotedValue(result, e->
getType());
877 mlir::Value VisitUnaryMinus(
const UnaryOperator *e, QualType promotionType) {
878 ignoreResultAssign =
false;
880 if (!promotionType.
isNull())
881 operand = cgf.emitPromotedScalarExpr(e->
getSubExpr(), promotionType);
887 if (cir::isFPOrVectorOfFPType(operand.getType()))
888 return builder.createOrFold<cir::FNegOp>(loc, operand);
894 cgf.getLangOpts().getSignedOverflowBehavior() !=
895 LangOptions::SOB_Defined;
897 return builder.createOrFold<cir::MinusOp>(loc, operand, nsw);
900 mlir::Value emitIntIncOrDec(
const UnaryOperator *e, mlir::Value input,
904 ? builder.createOrFold<cir::IncOp>(loc, input, nsw)
905 : builder.createOrFold<cir::DecOp>(loc, input, nsw);
908 mlir::Value emitFloatIncOrDec(
const UnaryOperator *e, mlir::Value input) {
909 assert(cir::isFPOrVectorOfFPType(input.getType()) &&
910 "Expect floating-point operand");
913 if (
auto vecType = mlir::dyn_cast<cir::VectorType>(input.getType())) {
914 mlir::Type fpScalarType = vecType.getElementType();
915 auto fpInterface = mlir::cast<cir::FPTypeInterface>(fpScalarType);
916 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
918 mlir::Value amtValue = builder.getConstFP(loc, fpScalarType, amount);
919 amtValue = cir::VecSplatOp::create(builder, loc, vecType, amtValue);
920 return builder.createFAdd(loc, input, amtValue);
925 if (
type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
926 input = builder.createFloatingCast(input, builder.getSingleTy());
928 auto fpInterface = mlir::cast<cir::FPTypeInterface>(input.getType());
929 auto amount = llvm::APFloat::getOne(fpInterface.getFloatSemantics(),
931 mlir::Value amtValue = builder.getConstFP(loc, input.getType(), amount);
932 mlir::Value output = builder.createFAdd(loc, input, amtValue);
934 if (
type->isHalfType() && !cgf.getContext().getLangOpts().NativeHalfType)
935 output = builder.createFloatingCast(output, builder.getFp16Ty());
940 mlir::Value VisitUnaryNot(
const UnaryOperator *e) {
941 ignoreResultAssign =
false;
943 return builder.createOrFold<cir::NotOp>(
947 mlir::Value VisitUnaryLNot(
const UnaryOperator *e);
949 mlir::Value VisitUnaryReal(
const UnaryOperator *e);
950 mlir::Value VisitUnaryImag(
const UnaryOperator *e);
951 mlir::Value VisitRealImag(
const UnaryOperator *e,
952 QualType promotionType = QualType());
954 mlir::Value VisitUnaryExtension(
const UnaryOperator *e) {
959 mlir::Value VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *e) {
960 return emitLoadOfLValue(e);
962 mlir::Value VisitSourceLocExpr(SourceLocExpr *e) {
963 ASTContext &ctx = cgf.getContext();
966 mlir::Attribute attribute = ConstantEmitter(cgf).emitAbstract(
968 mlir::TypedAttr typedAttr = mlir::cast<mlir::TypedAttr>(attribute);
969 return cir::ConstantOp::create(builder, cgf.getLoc(e->
getExprLoc()),
972 mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {
973 CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);
976 mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {
977 CIRGenFunction::CXXDefaultInitExprScope scope(cgf, die);
981 mlir::Value VisitCXXThisExpr(CXXThisExpr *te) {
return cgf.loadCXXThis(); }
983 mlir::Value VisitExprWithCleanups(ExprWithCleanups *e);
984 mlir::Value VisitCXXNewExpr(
const CXXNewExpr *e) {
985 return cgf.emitCXXNewExpr(e);
987 mlir::Value VisitCXXDeleteExpr(
const CXXDeleteExpr *e) {
988 cgf.emitCXXDeleteExpr(e);
991 mlir::Value VisitTypeTraitExpr(
const TypeTraitExpr *e) {
997 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1002 "Expected int type for TypeTraitExpr");
1003 return builder.getConstInt(loc, cgf.convertType(e->
getType()),
1010 VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *e) {
1016 mlir::Value VisitArrayTypeTraitExpr(
const ArrayTypeTraitExpr *e) {
1018 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1021 mlir::Value VisitExpressionTraitExpr(
const ExpressionTraitExpr *e) {
1024 mlir::Value VisitCXXPseudoDestructorExpr(
const CXXPseudoDestructorExpr *e) {
1026 "ScalarExprEmitter: cxx pseudo destructor");
1029 mlir::Value VisitCXXThrowExpr(
const CXXThrowExpr *e) {
1030 cgf.emitCXXThrowExpr(e);
1034 mlir::Value VisitCXXNoexceptExpr(CXXNoexceptExpr *e) {
1038 mlir::Value emitFixedPointConversion(mlir::Value src, QualType srcTy,
1039 QualType dstTy, mlir::Location loc);
1046 emitScalarConversion(mlir::Value src, QualType srcType, QualType dstType,
1048 ScalarConversionOpts opts = ScalarConversionOpts()) {
1056 cir::BoolType boolTy = builder.getBoolTy();
1057 return cir::CastOp::create(builder, cgf.getLoc(loc), boolTy,
1058 cir::CastKind::int_to_bool, src);
1063 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1065 llvm_unreachable(
"Unhandled scalar conversion from a fixed point type to "
1071 return emitFixedPointConversion(src, srcType, dstType, cgf.getLoc(loc));
1074 llvm_unreachable(
"Unhandled scalar conversion to a fixed point type from "
1080 if (srcType == dstType) {
1081 if (opts.emitImplicitIntegerSignChangeChecks)
1082 cgf.getCIRGenModule().errorNYI(loc,
1083 "implicit integer sign change checks");
1090 mlir::Type mlirSrcType = src.getType();
1095 return emitConversionToBool(src, srcType, cgf.getLoc(loc));
1097 mlir::Type mlirDstType = cgf.convertType(dstType);
1100 !cgf.getContext().getLangOpts().NativeHalfType) {
1102 if (!mlir::isa<cir::FPTypeInterface>(mlirDstType)) {
1106 src = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, src,
1108 srcType = cgf.getContext().FloatTy;
1109 mlirSrcType = cgf.floatTy;
1115 if (mlirSrcType == mlirDstType) {
1116 if (opts.emitImplicitIntegerSignChangeChecks)
1117 cgf.getCIRGenModule().errorNYI(loc,
1118 "implicit integer sign change checks");
1125 if (
auto dstPT = dyn_cast<cir::PointerType>(mlirDstType)) {
1126 cgf.getCIRGenModule().errorNYI(loc,
"pointer casts");
1127 return builder.getNullPtr(dstPT, src.getLoc());
1133 return builder.createPtrToInt(src, mlirDstType);
1140 assert(dstType->
castAs<ExtVectorType>()->getElementType().getTypePtr() ==
1142 "Splatted expr doesn't match with vector element type?");
1144 cgf.getCIRGenModule().errorNYI(loc,
"vector splatting");
1149 cgf.getCIRGenModule().errorNYI(loc,
1150 "matrix type to matrix type conversion");
1154 "Internal error: conversion between matrix type and scalar type");
1157 mlir::Value res =
nullptr;
1158 mlir::Type resTy = mlirDstType;
1160 res = emitScalarCast(src, srcType, dstType, mlirSrcType, mlirDstType, opts);
1162 if (mlirDstType != resTy) {
1163 res = builder.createCast(cgf.getLoc(loc), cir::CastKind::floating, res,
1167 if (opts.emitImplicitIntegerTruncationChecks)
1168 cgf.getCIRGenModule().errorNYI(loc,
"implicit integer truncation checks");
1170 if (opts.emitImplicitIntegerSignChangeChecks)
1171 cgf.getCIRGenModule().errorNYI(loc,
1172 "implicit integer sign change checks");
1177 BinOpInfo emitBinOps(
const BinaryOperator *e,
1178 QualType promotionType = QualType()) {
1179 ignoreResultAssign =
false;
1181 result.lhs = cgf.emitPromotedScalarExpr(e->
getLHS(), promotionType);
1182 result.rhs = cgf.emitPromotedScalarExpr(e->
getRHS(), promotionType);
1183 if (!promotionType.
isNull())
1184 result.fullType = promotionType;
1186 result.fullType = e->
getType();
1187 result.compType = result.fullType;
1188 if (
const auto *vecType = result.fullType->
getAs<VectorType>())
1189 result.compType = vecType->getElementType();
1197 mlir::Value emitMul(
const BinOpInfo &ops);
1198 mlir::Value emitDiv(
const BinOpInfo &ops);
1199 mlir::Value emitRem(
const BinOpInfo &ops);
1200 mlir::Value emitAdd(
const BinOpInfo &ops);
1201 mlir::Value emitSub(
const BinOpInfo &ops);
1202 mlir::Value emitShl(
const BinOpInfo &ops);
1203 mlir::Value emitShr(
const BinOpInfo &ops);
1204 mlir::Value emitAnd(
const BinOpInfo &ops);
1205 mlir::Value emitXor(
const BinOpInfo &ops);
1206 mlir::Value emitOr(
const BinOpInfo &ops);
1208 mlir::Value emitFixedPointBinOp(
const BinOpInfo &ops);
1210 LValue emitCompoundAssignLValue(
1211 const CompoundAssignOperator *e,
1212 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &),
1213 mlir::Value &result);
1215 emitCompoundAssign(
const CompoundAssignOperator *e,
1216 mlir::Value (ScalarExprEmitter::*f)(
const BinOpInfo &));
1220 QualType getPromotionType(QualType ty) {
1221 const clang::ASTContext &ctx = cgf.getContext();
1222 if (
auto *complexTy = ty->
getAs<ComplexType>()) {
1223 QualType elementTy = complexTy->getElementType();
1229 if (
auto *vt = ty->
getAs<VectorType>()) {
1230 unsigned numElements = vt->getNumElements();
1233 return cgf.getContext().FloatTy;
1240#define HANDLEBINOP(OP) \
1241 mlir::Value VisitBin##OP(const BinaryOperator *e) { \
1242 QualType promotionTy = getPromotionType(e->getType()); \
1243 auto result = emit##OP(emitBinOps(e, promotionTy)); \
1244 if (result && !promotionTy.isNull()) \
1245 result = emitUnPromotedValue(result, e->getType()); \
1248 mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *e) { \
1249 return emitCompoundAssign(e, &ScalarExprEmitter::emit##OP); \
1267 return cir::CmpOpKind::lt;
1269 return cir::CmpOpKind::gt;
1271 return cir::CmpOpKind::le;
1273 return cir::CmpOpKind::ge;
1275 return cir::CmpOpKind::eq;
1277 return cir::CmpOpKind::ne;
1279 llvm_unreachable(
"unsupported comparison kind for cir.cmp");
1283 mlir::Value emitCmp(
const BinaryOperator *e) {
1284 ignoreResultAssign =
false;
1285 const mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1291 if (lhsTy->
getAs<MemberPointerType>()) {
1294 mlir::Value lhs = cgf.emitScalarExpr(e->
getLHS());
1295 mlir::Value rhs = cgf.emitScalarExpr(e->
getRHS());
1296 result = builder.createCompare(loc,
kind, lhs, rhs);
1298 BinOpInfo boInfo = emitBinOps(e);
1299 mlir::Value lhs = boInfo.lhs;
1300 mlir::Value rhs = boInfo.rhs;
1306 cgf.cgm.errorNYI(loc,
"AltiVec comparison");
1310 result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
1311 cgf.convertType(boInfo.fullType),
kind,
1312 boInfo.lhs, boInfo.rhs);
1314 }
else if (boInfo.isFixedPointOp()) {
1315 result = emitFixedPointBinOp(boInfo);
1318 if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
1319 mlir::isa<cir::PointerType>(lhs.getType()) &&
1320 mlir::isa<cir::PointerType>(rhs.getType())) {
1321 cgf.cgm.errorNYI(loc,
"strict vtable pointer comparisons");
1323 result = builder.createCompare(loc,
kind, lhs, rhs);
1327 "Complex Comparison: can only be an equality comparison");
1331 lhs = cgf.emitComplexExpr(e->
getLHS());
1333 mlir::Value lhsReal = Visit(e->
getLHS());
1334 mlir::Value lhsImag = builder.getNullValue(convertType(lhsTy), loc);
1335 lhs = builder.createComplexCreate(loc, lhsReal, lhsImag);
1340 rhs = cgf.emitComplexExpr(e->
getRHS());
1342 mlir::Value rhsReal = Visit(e->
getRHS());
1343 mlir::Value rhsImag = builder.getNullValue(convertType(rhsTy), loc);
1344 rhs = builder.createComplexCreate(loc, rhsReal, rhsImag);
1347 result = builder.createCompare(loc,
kind, lhs, rhs);
1350 return emitScalarConversion(result, cgf.getContext().BoolTy, e->
getType(),
1355#define VISITCOMP(CODE) \
1356 mlir::Value VisitBin##CODE(const BinaryOperator *E) { return emitCmp(E); }
1366 const bool ignore = std::exchange(ignoreResultAssign,
false);
1381 rhs = Visit(e->
getRHS());
1391 if (lhs.isBitField()) {
1411 if (!lhs.isVolatile())
1415 return emitLoadOfLValue(lhs, e->
getExprLoc());
1418 mlir::Value VisitBinComma(
const BinaryOperator *e) {
1419 cgf.emitIgnoredExpr(e->
getLHS());
1421 return Visit(e->
getRHS());
1424 mlir::Value VisitBinLAnd(
const clang::BinaryOperator *e) {
1426 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1428 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1430 mlir::Value lhs = Visit(e->
getLHS());
1431 mlir::Value rhs = Visit(e->
getRHS());
1433 auto cmpOpKind = cir::CmpOpKind::ne;
1435 mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1436 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1437 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1438 return builder.createAnd(loc, lhs, rhs);
1442 mlir::Type resTy = cgf.convertType(e->
getType());
1443 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1445 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1447 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1449 auto resOp = cir::TernaryOp::create(
1450 builder, loc, lhsCondV,
1451 [&](mlir::OpBuilder &b, mlir::Location loc) {
1452 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1453 b.getInsertionBlock()};
1454 cgf.curLexScope->setAsTernary();
1455 eval.beginEvaluation();
1456 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1457 eval.endEvaluation();
1459 cir::YieldOp::create(b, loc, res);
1462 [&](mlir::OpBuilder &b, mlir::Location loc) {
1463 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1464 b.getInsertionBlock()};
1466 auto res = cir::ConstantOp::create(b, loc, builder.getFalseAttr());
1467 cir::YieldOp::create(b, loc, res.getRes());
1469 return maybePromoteBoolResult(resOp.getResult(), resTy);
1472 mlir::Value VisitBinLOr(
const clang::BinaryOperator *e) {
1474 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1476 mlir::Value zeroVec = builder.getNullValue(lhsTy, loc);
1478 mlir::Value lhs = Visit(e->
getLHS());
1479 mlir::Value rhs = Visit(e->
getRHS());
1481 auto cmpOpKind = cir::CmpOpKind::ne;
1483 mlir::cast<cir::VectorType>(cgf.convertType(e->
getType()));
1484 lhs = builder.createVecCompare(loc, resultTy, cmpOpKind, lhs, zeroVec);
1485 rhs = builder.createVecCompare(loc, resultTy, cmpOpKind, rhs, zeroVec);
1486 return builder.createOr(loc, lhs, rhs);
1490 mlir::Type resTy = cgf.convertType(e->
getType());
1491 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1493 mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->
getLHS());
1495 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
1497 auto resOp = cir::TernaryOp::create(
1498 builder, loc, lhsCondV,
1499 [&](mlir::OpBuilder &b, mlir::Location loc) {
1500 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1501 b.getInsertionBlock()};
1503 auto res = cir::ConstantOp::create(b, loc, builder.getTrueAttr());
1504 cir::YieldOp::create(b, loc, res.getRes());
1507 [&](mlir::OpBuilder &b, mlir::Location loc) {
1508 CIRGenFunction::LexicalScope lexScope{cgf, loc,
1509 b.getInsertionBlock()};
1511 eval.beginEvaluation();
1512 mlir::Value res = cgf.evaluateExprAsBool(e->
getRHS());
1513 eval.endEvaluation();
1515 cir::YieldOp::create(b, loc, res);
1518 return maybePromoteBoolResult(resOp.getResult(), resTy);
1521 mlir::Value VisitBinPtrMemD(
const BinaryOperator *e) {
1522 return emitLoadOfLValue(e);
1525 mlir::Value VisitBinPtrMemI(
const BinaryOperator *e) {
1526 return emitLoadOfLValue(e);
1530 mlir::Value VisitBlockExpr(
const BlockExpr *e) {
1531 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: block");
1535 mlir::Value VisitChooseExpr(ChooseExpr *e) {
1539 mlir::Value VisitObjCStringLiteral(
const ObjCStringLiteral *e) {
1541 "ScalarExprEmitter: objc string literal");
1544 mlir::Value VisitObjCBoxedExpr(ObjCBoxedExpr *e) {
1545 cgf.cgm.errorNYI(e->
getSourceRange(),
"ScalarExprEmitter: objc boxed");
1548 mlir::Value VisitObjCArrayLiteral(ObjCArrayLiteral *e) {
1550 "ScalarExprEmitter: objc array literal");
1553 mlir::Value VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *e) {
1555 "ScalarExprEmitter: objc dictionary literal");
1559 mlir::Value convertVec3AndVec4(CIRGenBuilderTy &builder, mlir::Location loc,
1560 mlir::Value src,
unsigned numElementsDst) {
1561 static constexpr int64_t mask[] = {0, 1, 2, -1};
1562 return builder.createVecShuffle(
1563 loc, src, llvm::ArrayRef<int64_t>(mask, numElementsDst));
1585 mlir::Type srcTy = src.getType();
1589 return builder.createBitcast(src, dstTy);
1594 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 2");
1602 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a");
1606 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 3a and 3b");
1613 "ScalarExprEmitter: createCastsForTypeOfSameSize Case 4a");
1617 return builder.createIntToPtr(src, dstTy);
1620 mlir::Value VisitAsTypeExpr(AsTypeExpr *e) {
1621 mlir::Value src = cgf.emitScalarExpr(e->
getSrcExpr());
1622 mlir::Type srcTy = src.getType();
1623 mlir::Type dstTy = cgf.convertType(e->
getType());
1635 "ScalarExprEmitter: VisitAsTypeExpr ExtVectorBoolType");
1641 if (numElementsSrc == 3 && numElementsDst != 3) {
1643 "ScalarExprEmitter: VisitAsTypeExpr numElemsSrc = 3, "
1644 "numElemsDst != 3");
1651 if (numElementsSrc != 3 && numElementsDst == 3) {
1652 mlir::Location loc = cgf.getLoc(e->
getExprLoc());
1654 auto dstVec4Ty = cir::VectorType::getFixed(dstElemTy, 4);
1656 src = convertVec3AndVec4(builder, loc, src, 3);
1663 mlir::Value VisitAtomicExpr(AtomicExpr *e) {
1664 return cgf.emitAtomicExpr(e).getValue();
1668LValue ScalarExprEmitter::emitCompoundAssignLValue(
1670 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &),
1671 mlir::Value &result) {
1682 if (promotionTypeCR.
isNull())
1686 QualType promotionTypeRHS = getPromotionType(e->
getRHS()->
getType());
1688 if (!promotionTypeRHS.
isNull())
1691 opInfo.rhs = Visit(e->
getRHS());
1693 opInfo.fullType = promotionTypeCR;
1694 opInfo.compType = opInfo.fullType;
1695 if (
const auto *vecType = opInfo.fullType->
getAs<VectorType>())
1696 opInfo.compType = vecType->getElementType();
1705 if (lhsTy->
getAs<AtomicType>()) {
1706 cgf.
cgm.
errorNYI(result.getLoc(),
"atomic lvalue assign");
1710 opInfo.lhs = emitLoadOfLValue(lhsLV, e->
getExprLoc());
1712 CIRGenFunction::SourceLocRAIIObject sourceloc{cgf, e->
getSourceRange()};
1714 if (!promotionTypeLHS.
isNull())
1715 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy, promotionTypeLHS, loc);
1717 opInfo.lhs = emitScalarConversion(opInfo.lhs, lhsTy,
1721 result = (this->*func)(opInfo);
1725 result = emitScalarConversion(result, promotionTypeCR, lhsTy, loc,
1726 ScalarConversionOpts(cgf.
sanOpts));
1732 if (lhsLV.isBitField())
1742mlir::Value ScalarExprEmitter::emitComplexToScalarConversion(mlir::Location lov,
1746 cir::CastKind castOpKind;
1748 case CK_FloatingComplexToReal:
1749 castOpKind = cir::CastKind::float_complex_to_real;
1751 case CK_IntegralComplexToReal:
1752 castOpKind = cir::CastKind::int_complex_to_real;
1754 case CK_FloatingComplexToBoolean:
1755 castOpKind = cir::CastKind::float_complex_to_bool;
1757 case CK_IntegralComplexToBoolean:
1758 castOpKind = cir::CastKind::int_complex_to_bool;
1761 llvm_unreachable(
"invalid complex-to-scalar cast kind");
1767mlir::Value ScalarExprEmitter::emitPromoted(
const Expr *e,
1768 QualType promotionType) {
1770 if (
const auto *bo = dyn_cast<BinaryOperator>(e)) {
1771 switch (bo->getOpcode()) {
1772#define HANDLE_BINOP(OP) \
1774 return emit##OP(emitBinOps(bo, promotionType));
1783 }
else if (
const auto *uo = dyn_cast<UnaryOperator>(e)) {
1784 switch (uo->getOpcode()) {
1787 return VisitRealImag(uo, promotionType);
1789 return VisitUnaryMinus(uo, promotionType);
1791 return VisitUnaryPlus(uo, promotionType);
1796 mlir::Value result = Visit(
const_cast<Expr *
>(e));
1798 if (!promotionType.
isNull())
1799 return emitPromotedValue(result, promotionType);
1800 return emitUnPromotedValue(result, e->
getType());
1805mlir::Value ScalarExprEmitter::emitCompoundAssign(
1806 const CompoundAssignOperator *e,
1807 mlir::Value (ScalarExprEmitter::*func)(
const BinOpInfo &)) {
1809 bool ignore = std::exchange(ignoreResultAssign,
false);
1811 LValue lhs = emitCompoundAssignLValue(e, func, rhs);
1822 if (!lhs.isVolatile())
1826 return emitLoadOfLValue(lhs, e->
getExprLoc());
1830ScalarExprEmitter::VisitSYCLUniqueStableNameExpr(SYCLUniqueStableNameExpr *e) {
1833 cir::GlobalOp globalConstStr =
1839 auto exprTy = mlir::cast<cir::PointerType>(convertType(e->
getType()));
1840 auto addrTy = mlir::cast<cir::PointerType>(addr.getType());
1841 if (addrTy.getAddrSpace() != exprTy.getAddrSpace())
1843 addr, builder.
getPointerTo(addrTy.getPointee(), exprTy.getAddrSpace()));
1847mlir::Value ScalarExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {
1848 CIRGenFunction::FullExprCleanupScope scope(cgf, e->
getSubExpr());
1860 ScalarExprEmitter emitter(*
this, builder);
1863#define COMPOUND_OP(Op) \
1864 case BO_##Op##Assign: \
1865 return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1902 llvm_unreachable(
"Not valid compound assignment operators");
1904 llvm_unreachable(
"Unhandled compound assignment operator");
1909 bool ignoreResultAssign) {
1911 "Invalid scalar expression to emit");
1913 return ScalarExprEmitter(*
this, builder, ignoreResultAssign)
1914 .Visit(
const_cast<Expr *
>(e));
1919 if (!promotionType.
isNull())
1920 return ScalarExprEmitter(*
this, builder).emitPromoted(e, promotionType);
1921 return ScalarExprEmitter(*
this, builder).Visit(
const_cast<Expr *
>(e));
1934static std::optional<QualType>
1938 return std::nullopt;
1943 return std::nullopt;
1956 const BinOpInfo &op) {
1958 "Expected a unary or binary operator");
1962 if (!op.mayHaveIntegerOverflow())
1966 if (
const auto *uo = dyn_cast<UnaryOperator>(op.e))
1967 return !uo->canOverflow();
1972 std::optional<QualType> optionalLHSTy =
1977 std::optional<QualType> optionalRHSTy =
1987 if ((op.opcode != BO_Mul && op.opcode != BO_MulAssign) ||
1994 return (2 * astContext.
getTypeSize(lhsTy)) < promotedSize ||
1995 (2 * astContext.
getTypeSize(rhsTy)) < promotedSize;
2000 const BinOpInfo &op,
2001 bool isSubtraction) {
2006 mlir::Value pointer = op.lhs;
2007 Expr *pointerOperand =
expr->getLHS();
2008 mlir::Value
index = op.rhs;
2009 Expr *indexOperand =
expr->getRHS();
2015 if (!isSubtraction && !mlir::isa<cir::PointerType>(pointer.getType())) {
2016 std::swap(pointer,
index);
2017 std::swap(pointerOperand, indexOperand);
2019 assert(mlir::isa<cir::PointerType>(pointer.getType()) &&
2020 "Need a pointer operand");
2021 assert(mlir::isa<cir::IntType>(
index.getType()) &&
"Need an integer operand");
2056 cgf.
cgm.
errorNYI(
"Objective-C:pointer arithmetic with non-pointer type");
2066 numElements.getType());
2077 return cir::PtrStrideOp::create(cgf.
getBuilder(), loc, pointer.getType(),
2082 return cir::PtrStrideOp::create(cgf.
getBuilder(),
2084 pointer.getType(), pointer,
index);
2088 auto vecTy = mlir::dyn_cast<cir::VectorType>(ty);
2089 return vecTy && mlir::isa<cir::IntType>(vecTy.getElementType());
2099 bool negMul,
bool negAdd) {
2100 mlir::Location loc = builder.getFusedLoc({mulOp.getLoc(), addLoc});
2101 mlir::Value mulOp0 = mulOp.getLhs();
2102 mlir::Value mulOp1 = mulOp.getRhs();
2110 mlir::Value fmuladd =
2111 cir::FMulAddOp::create(builder, loc, addend.getType(), mulOp0, mulOp1,
2112 addend, mulOp.getFenvAttr());
2125 bool isSub =
false) {
2126 assert((op.opcode == BO_Add || op.opcode == BO_AddAssign ||
2127 op.opcode == BO_Sub || op.opcode == BO_SubAssign) &&
2128 "Only fadd/fsub can be the root of an fmuladd.");
2135 mlir::Value lhs = op.lhs;
2136 mlir::Value rhs = op.rhs;
2140 bool negLHS =
false;
2141 if (
auto lhsNeg = lhs.getDefiningOp<cir::FNegOp>()) {
2142 if (lhsNeg.getResult().use_empty() && lhsNeg.getInput().hasOneUse()) {
2143 lhs = lhsNeg.getInput();
2148 bool negRHS =
false;
2149 if (
auto rhsNeg = rhs.getDefiningOp<cir::FNegOp>()) {
2150 if (rhsNeg.getResult().use_empty() && rhsNeg.getInput().hasOneUse()) {
2151 rhs = rhsNeg.getInput();
2159 if (
auto lhsMul = lhs.getDefiningOp<cir::FMulOp>()) {
2160 if (lhsMul.getResult().use_empty() || negLHS) {
2163 op.lhs.getDefiningOp<cir::FNegOp>().erase();
2164 return buildFMulAdd(loc, lhsMul, op.rhs, builder, negLHS, isSub);
2167 if (
auto rhsMul = rhs.getDefiningOp<cir::FMulOp>()) {
2168 if (rhsMul.getResult().use_empty() || negRHS) {
2171 op.rhs.getDefiningOp<cir::FNegOp>().erase();
2172 return buildFMulAdd(loc, rhsMul, op.lhs, builder, isSub ^ negRHS,
false);
2179mlir::Value ScalarExprEmitter::emitFixedPointIncDec(
const UnaryOperator *e,
2198 if (
type->isSignedFixedPointType()) {
2205 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(
info.loc));
2208 fpbuilder.createIntegerToFixed(
info.rhs,
true, dstSema);
2209 return emitFixedPointBinOp(info);
2212mlir::Value ScalarExprEmitter::emitFixedPointConversion(mlir::Value src,
2215 mlir::Location loc) {
2218 CIRGenFixedPointBuilder fpBuilder(builder, loc);
2222 result = fpBuilder.createFloatingToFixed(
2226 result = fpBuilder.createFixedToFloating(
2230 llvm::FixedPointSemantics srcFPSema =
2232 llvm::FixedPointSemantics dstFPSema =
2236 result = fpBuilder.createFixedToInteger(
2237 src, srcFPSema, dstFPSema.getWidth(), dstFPSema.isSigned());
2240 fpBuilder.createIntegerToFixed(src, srcFPSema.isSigned(), dstFPSema);
2243 result = fpBuilder.createFixedToFixed(src, srcFPSema, dstFPSema);
2249mlir::Value ScalarExprEmitter::emitMul(
const BinOpInfo &ops) {
2250 const mlir::Location loc = cgf.
getLoc(ops.loc);
2253 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2254 case LangOptions::SOB_Defined:
2255 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2256 return builder.
createMul(loc, ops.lhs, ops.rhs);
2258 case LangOptions::SOB_Undefined:
2259 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2262 case LangOptions::SOB_Trapping:
2270 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2278 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2280 return builder.
createMul(loc, lhs, rhs);
2284 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2286 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2288 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2289 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2290 return builder.
createFMul(loc, ops.lhs, ops.rhs);
2293 if (ops.isFixedPointOp())
2294 return emitFixedPointBinOp(ops);
2296 return cir::MulOp::create(builder, cgf.
getLoc(ops.loc),
2299mlir::Value ScalarExprEmitter::emitDiv(
const BinOpInfo &ops) {
2300 const mlir::Location loc = cgf.
getLoc(ops.loc);
2301 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2302 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2303 return builder.
createFDiv(loc, ops.lhs, ops.rhs);
2307 assert(mlir::isa<cir::MatrixType>(ops.lhs.getType()) &&
2308 "first operand must be a matrix");
2309 assert(cir::isAnyIntegerOrFloatingPointType(ops.rhs.getType()) &&
2310 "second operand must be an arithmetic type");
2315 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2316 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2318 return builder.
createDiv(loc, lhs, rhs);
2321 if (ops.isFixedPointOp())
2322 return emitFixedPointBinOp(ops);
2324 return cir::DivOp::create(builder, loc, cgf.
convertType(ops.fullType),
2327mlir::Value ScalarExprEmitter::emitRem(
const BinOpInfo &ops) {
2328 const mlir::Location loc = cgf.
getLoc(ops.loc);
2329 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2330 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2331 return builder.
createFRem(loc, ops.lhs, ops.rhs);
2333 return cir::RemOp::create(builder, loc, cgf.
convertType(ops.fullType),
2337mlir::Value ScalarExprEmitter::emitFixedPointBinOp(
const BinOpInfo &ops) {
2342 QualType resultTy = ops.compType;
2343 QualType lhsTy, rhsTy;
2344 if (
const auto *binOp = dyn_cast<BinaryOperator>(ops.e)) {
2345 rhsTy = binOp->getRHS()->getType();
2346 if (
const auto *cao = dyn_cast<CompoundAssignOperator>(binOp)) {
2351 lhsTy = cao->getComputationLHSType();
2352 resultTy = cao->getComputationResultType();
2354 lhsTy = binOp->getLHS()->getType();
2356 }
else if (
const auto *unOp = dyn_cast<UnaryOperator>(ops.e)) {
2357 lhsTy = unOp->getSubExpr()->getType();
2358 rhsTy = unOp->getSubExpr()->getType();
2361 mlir::Value lhs = ops.lhs;
2362 mlir::Value rhs = ops.rhs;
2367 auto commonFixedSema = lhsFixedSema.getCommonSemantics(rhsFixedSema);
2371 CIRGenFixedPointBuilder fpbuilder(builder, cgf.
getLoc(ops.loc));
2372 switch (ops.opcode) {
2375 result = fpbuilder.createAdd(lhs, lhsFixedSema, rhs, rhsFixedSema);
2379 result = fpbuilder.createSub(lhs, lhsFixedSema, rhs, rhsFixedSema);
2383 result = fpbuilder.createMul(lhs, lhsFixedSema, rhs, rhsFixedSema);
2387 result = fpbuilder.createDiv(lhs, lhsFixedSema, rhs, rhsFixedSema);
2391 result = fpbuilder.createShl(lhs, lhsFixedSema, rhs);
2395 result = fpbuilder.createShr(lhs, rhs);
2403 return fpbuilder.createCmp(lhs, lhsFixedSema, rhs, rhsFixedSema,
2404 clangCmpToCIRCmp(ops.opcode));
2408 llvm_unreachable(
"Found unimplemented fixed point binary operation");
2422 "Found unsupported binary operation for fixed point types.");
2428 return fpbuilder.createFixedToFixed(
2429 result, isShift ? lhsFixedSema : commonFixedSema, resultFixedSema);
2432mlir::Value ScalarExprEmitter::emitAdd(
const BinOpInfo &ops) {
2433 if (mlir::isa<cir::PointerType>(ops.lhs.getType()) ||
2434 mlir::isa<cir::PointerType>(ops.rhs.getType()))
2438 const mlir::Location loc = cgf.
getLoc(ops.loc);
2441 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2442 case LangOptions::SOB_Defined:
2443 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2444 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2446 case LangOptions::SOB_Undefined:
2447 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2450 case LangOptions::SOB_Trapping:
2462 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2463 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2465 return builder.
createAdd(loc, lhs, rhs);
2469 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2471 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2473 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2474 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2478 return builder.
createFAdd(loc, ops.lhs, ops.rhs);
2481 if (ops.isFixedPointOp())
2482 return emitFixedPointBinOp(ops);
2484 return builder.
createAdd(loc, ops.lhs, ops.rhs);
2487mlir::Value ScalarExprEmitter::emitSub(
const BinOpInfo &ops) {
2488 const mlir::Location loc = cgf.
getLoc(ops.loc);
2490 if (!mlir::isa<cir::PointerType>(ops.lhs.getType())) {
2493 switch (cgf.
getLangOpts().getSignedOverflowBehavior()) {
2494 case LangOptions::SOB_Defined: {
2495 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2496 return builder.
createSub(loc, ops.lhs, ops.rhs);
2499 case LangOptions::SOB_Undefined:
2500 if (!cgf.
sanOpts.
has(SanitizerKind::SignedIntegerOverflow))
2503 case LangOptions::SOB_Trapping:
2516 CIRGenFunction::CIRGenFPOptionsRAII fpOptsRAII(cgf, ops.fpFeatures);
2517 if (cir::isFPOrVectorOrMatrixOfFPType(lhs.getType()))
2519 return builder.
createSub(loc, lhs, rhs);
2523 cgf.
sanOpts.
has(SanitizerKind::UnsignedIntegerOverflow) &&
2525 cgf.
cgm.
errorNYI(
"unsigned int overflow sanitizer");
2527 if (cir::isFPOrVectorOfFPType(ops.lhs.getType())) {
2528 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ops.fpFeatures);
2530 if (mlir::Value fmuladd =
2533 return builder.
createFSub(loc, ops.lhs, ops.rhs);
2536 if (ops.isFixedPointOp())
2537 return emitFixedPointBinOp(ops);
2539 return builder.
createSub(loc, ops.lhs, ops.rhs);
2544 if (!mlir::isa<cir::PointerType>(ops.rhs.getType()))
2556 return cir::PtrDiffOp::create(builder, cgf.
getLoc(ops.loc), cgf.
ptrDiffTy,
2560mlir::Value ScalarExprEmitter::emitShl(
const BinOpInfo &ops) {
2562 if (ops.isFixedPointOp())
2563 return emitFixedPointBinOp(ops);
2569 bool sanitizeSignedBase = cgf.
sanOpts.
has(SanitizerKind::ShiftBase) &&
2573 bool sanitizeUnsignedBase =
2574 cgf.
sanOpts.
has(SanitizerKind::UnsignedShiftBase) &&
2576 bool sanitizeBase = sanitizeSignedBase || sanitizeUnsignedBase;
2577 bool sanitizeExponent = cgf.
sanOpts.
has(SanitizerKind::ShiftExponent);
2582 else if ((sanitizeBase || sanitizeExponent) &&
2583 mlir::isa<cir::IntType>(ops.lhs.getType()))
2589mlir::Value ScalarExprEmitter::emitShr(
const BinOpInfo &ops) {
2591 if (ops.isFixedPointOp())
2592 return emitFixedPointBinOp(ops);
2601 else if (cgf.
sanOpts.
has(SanitizerKind::ShiftExponent) &&
2602 mlir::isa<cir::IntType>(ops.lhs.getType()))
2610mlir::Value ScalarExprEmitter::emitAnd(
const BinOpInfo &ops) {
2611 return cir::AndOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2613mlir::Value ScalarExprEmitter::emitXor(
const BinOpInfo &ops) {
2614 return cir::XorOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2616mlir::Value ScalarExprEmitter::emitOr(
const BinOpInfo &ops) {
2617 return cir::OrOp::create(builder, cgf.
getLoc(ops.loc), ops.lhs, ops.rhs);
2624mlir::Value ScalarExprEmitter::VisitCastExpr(
CastExpr *ce) {
2626 QualType destTy = ce->
getType();
2628 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2632 ignoreResultAssign =
false;
2635 case clang::CK_Dependent:
2636 llvm_unreachable(
"dependent cast kind in CIR gen!");
2637 case clang::CK_BuiltinFnToFnPtr:
2638 llvm_unreachable(
"builtin functions are handled elsewhere");
2639 case CK_LValueBitCast:
2640 case CK_LValueToRValueBitCast: {
2642 Address sourceAddr = sourceLVal.getAddress();
2648 return emitLoadOfLValue(destLVal, ce->
getExprLoc());
2651 case CK_CPointerToObjCPointerCast:
2652 case CK_BlockPointerToObjCPointerCast:
2653 case CK_AnyPointerToBlockPointerCast:
2655 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2659 auto srcPtrTy = mlir::dyn_cast<cir::PointerType>(src.getType());
2660 auto dstPtrTy = mlir::dyn_cast<cir::PointerType>(dstTy);
2661 if (srcPtrTy && dstPtrTy &&
2662 srcPtrTy.getAddrSpace() != dstPtrTy.getAddrSpace())
2665 builder.
getPointerTo(srcPtrTy.getPointee(), dstPtrTy.getAddrSpace()));
2667 if (cgf.
sanOpts.
has(SanitizerKind::CFIUnrelatedCast))
2669 "sanitizer support");
2673 "strict vtable pointers");
2699 case CK_AddressSpaceConversion: {
2700 Expr::EvalResult result;
2709 mlir::cast<cir::PointerType>(convertType(destTy)), destTy,
2715 case CK_AtomicToNonAtomic:
2716 case CK_NonAtomicToAtomic:
2717 case CK_UserDefinedConversion:
2718 return Visit(
const_cast<Expr *
>(subExpr));
2722 case CK_IntegralToPointer: {
2724 mlir::Value src = Visit(
const_cast<Expr *
>(subExpr));
2733 : cir::CastKind::integral,
2738 "IntegralToPointer: strict vtable pointers");
2745 case CK_BaseToDerived: {
2747 assert(derivedClassDecl &&
"BaseToDerived arg isn't a C++ object pointer!");
2759 case CK_UncheckedDerivedToBase:
2760 case CK_DerivedToBase: {
2771 case CK_ArrayToPointerDecay:
2774 case CK_NullToPointer: {
2780 auto ty = mlir::cast<cir::PointerType>(cgf.
convertType(destTy));
2785 case CK_NullToMemberPointer: {
2791 const MemberPointerType *mpt = ce->
getType()->
getAs<MemberPointerType>();
2797 case CK_ReinterpretMemberPointer: {
2798 mlir::Value src = Visit(subExpr);
2802 case CK_BaseToDerivedMemberPointer:
2803 case CK_DerivedToBaseMemberPointer: {
2804 mlir::Value src = Visit(subExpr);
2808 QualType derivedTy =
2809 kind == CK_DerivedToBaseMemberPointer ? subExpr->
getType() : destTy;
2810 const auto *mpType = derivedTy->
castAs<MemberPointerType>();
2811 NestedNameSpecifier qualifier = mpType->getQualifier();
2812 assert(qualifier &&
"member pointer without class qualifier");
2813 const Type *qualifierType = qualifier.getAsType();
2814 assert(qualifierType &&
"member pointer qualifier is not a type");
2821 mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.
getQuantity());
2824 if (
kind == CK_BaseToDerivedMemberPointer)
2825 return cir::DerivedMethodOp::create(builder, loc, resultTy, src,
2827 return cir::BaseMethodOp::create(builder, loc, resultTy, src, offsetAttr);
2830 if (
kind == CK_BaseToDerivedMemberPointer)
2831 return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src,
2833 return cir::BaseDataMemberOp::create(builder, loc, resultTy, src,
2837 case CK_LValueToRValue:
2839 assert(subExpr->
isGLValue() &&
"lvalue-to-rvalue applied to r-value!");
2840 return Visit(
const_cast<Expr *
>(subExpr));
2842 case CK_IntegralCast: {
2843 ScalarConversionOpts opts;
2844 if (
auto *ice = dyn_cast<ImplicitCastExpr>(ce)) {
2845 if (!ice->isPartOfExplicitCast())
2846 opts = ScalarConversionOpts(cgf.
sanOpts);
2848 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2852 case CK_FloatingComplexToReal:
2853 case CK_IntegralComplexToReal:
2854 case CK_FloatingComplexToBoolean:
2855 case CK_IntegralComplexToBoolean: {
2861 case CK_FloatingRealToComplex:
2862 case CK_FloatingComplexCast:
2863 case CK_IntegralRealToComplex:
2864 case CK_IntegralComplexCast:
2865 case CK_IntegralComplexToFloatingComplex:
2866 case CK_FloatingComplexToIntegralComplex:
2867 llvm_unreachable(
"scalar cast to non-scalar value");
2869 case CK_PointerToIntegral: {
2870 assert(!destTy->
isBooleanType() &&
"bool should use PointerToBool");
2873 "strict vtable pointers");
2880 case CK_FixedPointCast:
2881 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2884 case CK_FixedPointToBoolean:
2886 "Expected src type to be fixed point type");
2887 assert(destTy->
isBooleanType() &&
"Expected dest type to be boolean type");
2888 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2891 case CK_FixedPointToIntegral:
2893 "Expected src type to be fixed point type");
2894 assert(destTy->
isIntegerType() &&
"Expected dest type to be an integer");
2895 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2898 case CK_IntegralToFixedPoint:
2900 "Expected src type to be an integer");
2902 "Expected dest type to be fixed point type");
2903 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2906 case CK_IntegralToFloating:
2907 case CK_FloatingToIntegral:
2908 case CK_FloatingCast:
2909 case CK_FixedPointToFloating:
2910 case CK_FloatingToFixedPoint: {
2911 CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, ce);
2912 return emitScalarConversion(Visit(subExpr), subExpr->
getType(), destTy,
2916 case CK_IntegralToBoolean:
2917 return emitIntToBoolConversion(Visit(subExpr),
2920 case CK_PointerToBoolean:
2921 return emitPointerToBoolConversion(Visit(subExpr), subExpr->
getType());
2922 case CK_FloatingToBoolean:
2923 return emitFloatToBoolConversion(Visit(subExpr),
2925 case CK_MemberPointerToBoolean: {
2926 mlir::Value memPtr = Visit(subExpr);
2928 cir::CastKind::member_ptr_to_bool, memPtr,
2932 case CK_HLSLAggregateSplatCast:
2933 case CK_VectorSplat: {
2936 return cir::VecSplatOp::create(builder,
2938 destCIRTy, Visit(subExpr));
2940 case CK_FunctionToPointerDecay:
2943 case CK_HLSLVectorTruncation: {
2945 "Destination type must be a vector or builtin type.");
2946 mlir::Value vec = Visit(subExpr);
2948 if (
auto *vecTy = destTy->
getAs<VectorType>()) {
2949 unsigned numElts = vecTy->getNumElements();
2950 llvm::SmallVector<int64_t, 4> mask(numElts);
2951 std::iota(mask.begin(), mask.end(), 0);
2964mlir::Value ScalarExprEmitter::VisitCallExpr(
const CallExpr *e) {
2966 return emitLoadOfLValue(e);
2973mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
2978 Expr::EvalResult result;
2980 llvm::APSInt value = result.
Val.
getInt();
2990 return builder.
getBool(value.getBoolValue(), loc);
2995 return emitLoadOfLValue(e);
2999ScalarExprEmitter::emitVectorInitWithSubvectors(mlir::Location loc,
3000 cir::VectorType vectorType,
3001 ArrayRef<mlir::Value>
inits) {
3002 const unsigned resElts = vectorType.getFixedSize();
3003 mlir::Value result =
3004 builder.
getConstant(loc, cir::PoisonAttr::get(vectorType));
3005 unsigned curIdx = 0;
3006 for (mlir::Value init :
inits) {
3007 auto initType = mlir::dyn_cast<cir::VectorType>(init.getType());
3013 const unsigned initElts = initType.getFixedSize();
3014 assert(curIdx + initElts <= resElts &&
3015 "Sema should reject excess elements");
3016 SmallVector<int64_t, 16> mask(resElts, -1);
3017 std::iota(mask.begin(), mask.begin() + initElts, 0);
3021 const unsigned offset = curIdx == 0 ? 0 : resElts;
3022 std::iota(mask.begin(), mask.begin() + curIdx, 0);
3023 std::iota(mask.begin() + curIdx, mask.begin() + curIdx + initElts, offset);
3025 std::swap(result, ext);
3030 if (curIdx < resElts) {
3031 const mlir::Value zeroValue =
3032 builder.
getNullValue(vectorType.getElementType(), loc);
3033 for (; curIdx < resElts; ++curIdx)
3039mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
3040 const unsigned numInitElements = e->
getNumInits();
3042 [[maybe_unused]]
const bool ignore = std::exchange(ignoreResultAssign,
false);
3043 assert((ignore ==
false ||
3045 "init list ignored");
3053 const auto vectorType =
3056 SmallVector<mlir::Value, 16> elements;
3057 bool hasVectorInit =
false;
3058 for (Expr *init : e->
inits()) {
3059 elements.push_back(Visit(init));
3060 hasVectorInit |= mlir::isa<cir::VectorType>(elements.back().getType());
3065 vectorType, elements);
3068 const uint64_t vectorSize = vectorType.getFixedSize();
3069 if (numInitElements < vectorSize) {
3072 std::fill_n(std::back_inserter(elements), vectorSize - numInitElements,
3076 return cir::VecCreateOp::create(cgf.
getBuilder(),
3087 if (numInitElements == 0)
3098 "Invalid scalar expression to emit");
3099 return ScalarExprEmitter(*
this, builder)
3100 .emitScalarConversion(src, srcTy, dstTy, loc);
3108 "Invalid complex -> scalar conversion");
3113 ? cir::CastKind::float_complex_to_bool
3114 : cir::CastKind::int_complex_to_bool;
3119 ? cir::CastKind::float_complex_to_real
3120 : cir::CastKind::int_complex_to_real;
3126mlir::Value ScalarExprEmitter::VisitUnaryLNot(
const UnaryOperator *e) {
3133 auto operVecTy = mlir::cast<cir::VectorType>(oper.getType());
3134 mlir::Value zeroVec = builder.
getNullValue(operVecTy, loc);
3150mlir::Value ScalarExprEmitter::VisitOffsetOfExpr(
OffsetOfExpr *e) {
3155 llvm::APSInt value = evalResult.
Val.
getInt();
3161 "ScalarExprEmitter::VisitOffsetOfExpr Can't eval expr as int");
3165mlir::Value ScalarExprEmitter::VisitUnaryReal(
const UnaryOperator *e) {
3167 mlir::Value result = VisitRealImag(e, promotionTy);
3168 if (result && !promotionTy.
isNull())
3169 result = emitUnPromotedValue(result, e->
getType());
3173mlir::Value ScalarExprEmitter::VisitUnaryImag(
const UnaryOperator *e) {
3175 mlir::Value result = VisitRealImag(e, promotionTy);
3176 if (result && !promotionTy.
isNull())
3177 result = emitUnPromotedValue(result, e->
getType());
3181mlir::Value ScalarExprEmitter::VisitRealImag(
const UnaryOperator *e,
3182 QualType promotionTy) {
3185 "Invalid UnaryOp kind for ComplexType Real or Imag");
3207 mlir::Value operand = promotionTy.
isNull()
3209 : cgf.emitPromotedScalarExpr(op, promotionTy);
3215 mlir::Value operand;
3218 operand = cir::LoadOp::create(builder, loc, operand);
3219 }
else if (!promotionTy.
isNull()) {
3229mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
3230 const UnaryExprOrTypeTraitExpr *e) {
3234 kind == UETT_SizeOf ||
kind == UETT_DataSizeOf ||
kind == UETT_CountOf) {
3235 if (
const VariableArrayType *vat =
3240 bool evaluateExtent =
true;
3241 if (
kind == UETT_CountOf && vat->getElementType()->isArrayType()) {
3243 !vat->getSizeExpr()->isIntegerConstantExpr(cgf.
getContext());
3246 if (evaluateExtent) {
3257 if (
kind == UETT_CountOf)
3262 CIRGenFunction::VlaSizePair vlaSize = cgf.
getVLASize(vat);
3263 mlir::Value numElts = vlaSize.
numElts;
3267 if (!eltSize.
isOne()) {
3269 mlir::Value eltSizeValue =
3272 return builder.
createMul(loc, eltSizeValue, numElts,
3279 }
else if (e->
getKind() == UETT_OpenMPRequiredSimdAlign) {
3286 }
else if (e->
getKind() == UETT_VectorElements) {
3288 if (vecTy.isScalable()) {
3291 "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
3298 loc, cir::IntAttr::get(cgf.
cgm.
sizeTy, vecTy.getFixedSize()));
3308mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
3309 const AbstractConditionalOperator *e) {
3312 ignoreResultAssign =
false;
3315 CIRGenFunction::OpaqueValueMapping binding(cgf, e);
3317 Expr *condExpr = e->
getCond();
3325 Expr *live = lhsExpr, *dead = rhsExpr;
3327 std::swap(live, dead);
3333 mlir::Value result = Visit(live);
3340 loc, cir::PoisonAttr::get(builder.getContext(),
3348 QualType condType = condExpr->
getType();
3357 mlir::Value lhsValue = Visit(lhsExpr);
3358 mlir::Value rhsValue = Visit(rhsExpr);
3364 mlir::Value zeroVec = builder.
getNullValue(vecTy, loc);
3365 auto testMSB = cir::VecCmpOp::create(
3366 builder, loc, vecTy, cir::CmpOpKind::lt, condValue, zeroVec);
3368 mlir::Value tmp2 = builder.
createNot(tmp);
3371 mlir::Value rhsTmp = rhsValue;
3372 mlir::Value lhsTmp = lhsValue;
3373 bool wasCast =
false;
3374 if (rhsValue.getType() != vecTy) {
3380 mlir::Value tmp3 = builder.
createAnd(loc, rhsTmp, tmp2);
3381 mlir::Value tmp4 = builder.
createAnd(loc, lhsTmp, tmp);
3382 mlir::Value tmp5 = builder.
createOr(loc, tmp3, tmp4);
3391 cgf.
cgm.
errorNYI(loc,
"TernaryOp for SVE vector");
3395 mlir::Value condValue = Visit(condExpr);
3396 mlir::Value lhsValue = Visit(lhsExpr);
3397 mlir::Value rhsValue = Visit(rhsExpr);
3398 return cir::VecTernaryOp::create(builder, loc, condValue, lhsValue,
3412 mlir::Value lhs = Visit(lhsExpr);
3413 mlir::Value rhs = Visit(rhsExpr);
3416 assert(!rhs &&
"lhs and rhs types must match");
3424 CIRGenFunction::ConditionalEvaluation eval(cgf, loc);
3426 auto emitBranch = [&](mlir::OpBuilder &b, mlir::Location loc, Expr *
expr) {
3427 CIRGenFunction::LexicalScope lexScope{cgf, loc, b.getInsertionBlock()};
3434 CIRGenFunction::RunCleanupsScope branchCleanups(cgf);
3436 eval.beginEvaluation();
3437 branch = Visit(
expr);
3438 eval.endEvaluation();
3439 branchCleanups.forceCleanup({&branch});
3443 cir::YieldOp::create(b, loc, branch);
3446 cir::TernaryOp ternary = cir::TernaryOp::create(
3447 builder, loc, condV,
3449 [&](mlir::OpBuilder &b, mlir::Location loc) {
3450 emitBranch(b, loc, lhsExpr);
3453 [&](mlir::OpBuilder &b, mlir::Location loc) {
3454 emitBranch(b, loc, rhsExpr);
3459 for (mlir::Region *region :
3460 {&ternary.getTrueRegion(), &ternary.getFalseRegion()}) {
3461 mlir::Block &lastBlock = region->back();
3462 if (lastBlock.empty() ||
3463 !lastBlock.back().hasTrait<mlir::OpTrait::IsTerminator>()) {
3464 mlir::OpBuilder::InsertionGuard guard(builder);
3465 builder.setInsertionPointToEnd(&lastBlock);
3466 cir::YieldOp::create(builder, loc);
3470 return ternary.getResult();
3475 return ScalarExprEmitter(*
this, builder).emitScalarPrePostIncDec(e, lv);
static Value * createCastsForTypeOfSameSize(CGBuilderTy &Builder, const llvm::DataLayout &DL, Value *Src, llvm::Type *DstTy, StringRef Name="")
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 mlir::Value tryEmitFMulAdd(mlir::Location loc, const BinOpInfo &op, CIRGenBuilderTy &builder, bool isSub=false)
static mlir::Value buildFMulAdd(mlir::Location addLoc, cir::FMulOp mulOp, mlir::Value addend, CIRGenBuilderTy &builder, bool negMul, bool negAdd)
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.
static bool isIntegerVectorBinOp(mlir::Type ty)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
mlir::Value createNSWSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getBool(bool state, mlir::Location loc)
mlir::Value createDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
mlir::Value createSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
mlir::Value createNSWAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::ConstantOp getNullValue(mlir::Type ty, mlir::Location loc)
cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr)
mlir::Value createOr(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createCast(mlir::Location loc, cir::CastKind kind, mlir::Value src, mlir::Type newTy)
mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy)
mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand)
mlir::Value createNSWMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::GetGlobalOp createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal=false)
mlir::Value createShiftLeft(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createExtractElement(mlir::Location loc, mlir::Value vec, uint64_t idx)
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
Compares lhs and rhs element-wise.
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createInsertElement(mlir::Location loc, mlir::Value vec, mlir::Value newElt, uint64_t idx)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
mlir::Value createSelect(mlir::Location loc, mlir::Value condition, mlir::Value trueValue, mlir::Value falseValue)
mlir::Value createMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, OverflowBehavior ob=OverflowBehavior::None)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createShiftRight(mlir::Location loc, mlir::Value lhs, unsigned bits)
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand)
mlir::Type getIntPtrType(mlir::Type ty) const
llvm::APInt getValue() const
bool isNullPointer() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getVectorType(QualType VectorType, unsigned NumElts, VectorKind VecKind) const
Return the unique reference to a vector type of the specified element type and size.
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getComplexType(QualType T) const
Return the uniqued reference to the type for a complex number with the specified element type.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
QualType getCorrespondingSignedType(QualType T) const
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
Expr * getSrcExpr() const
getSrcExpr - Return the Expr to be converted.
A builtin binary operation expression such as "x + y" or "x <= y".
SourceLocation getExprLoc() const
bool isShiftAssignOp() 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.
std::pair< mlir::Value, mlir::Value > splatMatrixOpOperandsIfNecessary(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef< mlir::Attribute > maskAttrs)
mlir::Value createNeg(mlir::Location loc, mlir::Value value, bool nsw=false)
cir::MatrixMultiplyOp createMatrixMultiply(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
Multiply an MxK matrix by a KxN matrix, producing an MxN matrix.
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
static bool hasScalarEvaluationKind(clang::QualType type)
mlir::Value emitComplexToScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc)
Emit a conversion from the specified complex type to the specified destination type,...
mlir::Type convertType(clang::QualType t)
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType)
Address emitPointerWithAlignment(const clang::Expr *expr, LValueBaseInfo *baseInfo=nullptr)
Given an expression with a pointer type, emit the value and compute our best estimate of the alignmen...
void emitVariablyModifiedType(QualType ty)
const clang::LangOptions & getLangOpts() const
VlaSizePair getVLASize(const VariableArrayType *type)
Returns an MLIR::Value+QualType pair that corresponds to the size, in non-variably-sized elements,...
LValue emitScalarCompoundAssignWithComplex(const CompoundAssignOperator *e, mlir::Value &result)
mlir::Value emitComplexExpr(const Expr *e)
Emit the computation of the specified expression of complex type, returning the result.
RValue emitCallExpr(const clang::CallExpr *e, ReturnValueSlot returnValue=ReturnValueSlot())
LValue emitLValue(const clang::Expr *e)
Emit code to compute a designator that specifies the location of the expression.
mlir::Value evaluateExprAsBool(const clang::Expr *e)
Perform the usual unary conversions on the specified expression and compare the result against zero,...
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
bool constantFoldsToBool(const clang::Expr *cond, bool &resultBool, bool allowLabels=false)
If the specified expression does not fold to a constant, or if it does but contains a label,...
mlir::Value emitOpOnBoolExpr(mlir::Location loc, const clang::Expr *cond)
TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
VlaSizePair getVLAElements1D(const VariableArrayType *vla)
Return the number of elements for a single dimension for the given array type.
mlir::Value performAddrSpaceCast(mlir::Value v, mlir::Type destTy) const
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)
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e)
mlir::Value getAsNaturalPointerTo(Address addr, QualType pointeeType)
mlir::Value emitScalarExpr(const clang::Expr *e, bool ignoreResultAssign=false)
Emit the computation of the specified expression of scalar type.
mlir::Value emitPromotedScalarExpr(const Expr *e, QualType promotionType)
bool shouldNullCheckClassCastValue(const CastExpr *ce)
CIRGenBuilderTy & getBuilder()
CIRGenModule & getCIRGenModule()
mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv)
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts=false)
Return true if the statement contains a label in it.
ConstantEmission tryEmitAsConstant(const DeclRefExpr *refExpr)
Try to emit a reference to the given value without producing it as an l-value.
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
mlir::Value emitScalarConstant(const ConstantEmission &constant, Expr *e)
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)
mlir::Value getNullPointer(cir::PointerType ptrTy, QualType qt, mlir::Location loc)
Get target specific null pointer.
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)
cir::GlobalOp createGlobalString(mlir::Location loc, llvm::StringRef str, llvm::StringRef name)
Create a private constant global holding the null-terminated string str, mirroring llvm::IRBuilder::C...
const cir::CIRDataLayout & getDataLayout() const
const clang::CodeGenOptions & getCodeGenOpts() const
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Value getPointer() const
static RValue get(mlir::Value v)
mlir::Value getValue() const
Return the value of this scalar value.
Expr * getExpr()
Get the initialization expression that will be used.
Expr * getSemanticForm()
Get an equivalent semantic form for this expression.
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
CastKind getCastKind() const
llvm::iterator_range< path_iterator > path()
Path through the class hierarchy taken by casts between base and derived classes (see implementation ...
bool changesVolatileQualification() const
Return.
static const char * getCastKindName(CastKind CK)
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
bool isOne() const
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 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...
bool allowFPContractWithinStatement() const
llvm::APInt getValue() const
Returns an internal integer representation of the literal.
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() const
bool isSignedOverflowDefined() const
SourceLocation getExprLoc() const LLVM_READONLY
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const
SourceRange getSourceRange() const LLVM_READONLY
SourceRange getSourceRange() const LLVM_READONLY
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
SourceLocation getExprLoc() const LLVM_READONLY
Expr * getSelectedExpr() const
const Expr * getSubExpr() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
QualType getCanonicalType() const
bool UseExcessPrecision(const ASTContext &Ctx)
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
bool isSatisfied() const
Whether or not the requires clause is satisfied.
std::string ComputeName(ASTContext &Context) const
unsigned getNumSubExprs() const
getNumSubExprs - Return the size of the SubExprs array.
Expr * getExpr(unsigned Index)
getExpr - Return the Expr at the specified index.
unsigned getPackLength() const
Retrieve the length of the parameter pack.
APValue EvaluateInContext(const ASTContext &Ctx, const Expr *DefaultExpr) const
Return the result of evaluating this SourceLocExpr in the specified (and possibly null) default argum...
SourceLocation getLocation() const
Encodes a location in the source.
SourceLocation getBegin() const
CompoundStmt * getSubStmt()
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const char * getStmtClassName() const
Expr * getReplacement() const
bool getBoolValue() const
const APValue & getAPValue() const
bool isStoredAsBoolean() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isConstantMatrixType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
bool isSveVLSBuiltinType() const
Determines if this is a sizeless type supported by the 'arm_sve_vector_bits' type attribute,...
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
bool isExtVectorType() const
bool isExtVectorBoolType() const
bool isBuiltinType() const
Helper methods to distinguish type categories.
bool isAnyComplexType() const
bool isFixedPointType() const
Return true if this is a fixed point type according to ISO/IEC JTC1 SC22 WG14 N1169.
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isMatrixType() const
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isMemberFunctionPointerType() const
bool isVectorType() const
bool isRealFloatingType() const
Floating point categories.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
bool isArgumentType() const
UnaryExprOrTypeTrait getKind() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
SourceLocation getExprLoc() const
Expr * getSubExpr() const
static bool isIncrementOp(Opcode Op)
static bool isDecrementOp(Opcode Op)
FPOptions getFPFeaturesInEffect(const LangOptions &LO) const
Get the FP features status of this operator.
static bool isPrefix(Opcode Op)
isPrefix - Return true if this is a prefix operation, like –x.
bool canOverflow() const
Returns true if the unary operator can cause an overflow.
Represents a C array with a specified size that is not an integer-constant-expression.
Represents a GCC generic vector type.
VectorKind getVectorKind() const
bool isCheapEnoughToEvaluateUnconditionally(const Expr *E, const ASTContext &Ctx)
Check whether E is cheap enough and side-effect-free enough to evaluate unconditionally instead of co...
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::ArgumentAdaptingMatcherFunc< internal::HasMatcher > has
Matches AST nodes that have child AST nodes that match the provided matcher.
const AstTypeMatcher< PointerType > pointerType
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
@ Address
A pointer to a ValueDecl.
void info(bool Verbose, unsigned Level, const char *Fmt, Ts &&...Args)
Prints an indented note to stderr when Verbose is set.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
CastKind
CastKind - The kind of operation required for a conversion.
@ Generic
not a target-specific vector type
U cast(CodeGen::Address addr)
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 int64_t
static bool instrumentation()
static bool dataMemberType()
static bool objCLifetime()
static bool vecTernaryOp()
static bool addHeapAllocSiteMetadata()
static bool mayHaveIntegerOverflow()
static bool emitMatrixIndexAssumption()
static bool openMPLastprivateConditional()
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.